views:

44

answers:

4

Hello there!

I had asked a question similar to this before, but I have a new problem with it so I've reposted part of the question.

I have this before the interface declaration in my MainView.h header.

typedef enum { UNKNOWN, CLEAR, NIGHT_CLEAR, CLOUDY, NIGHT_CLOUDY } Weather;

Then I declared it (in my MainView) like this:

Weather weather;

Then made an accessor (and synthesized it):

@property Weather weather;

My question is, how can I use this in MainViewController without it crashing? I've imported the header for MainView. I tried to use it like this:

MainView* myView = (MainView*)self.view;

[myView setWeather: CLEAR];

It doesn't throw me any errors in Xcode, but it crashes when the code is run, saying:

-[UIView setWeather:]: unrecognized selector sent to instance *blah*

Am I doing something wrong here?

In my MainViewController:

- (void)viewDidLoad {
    [super viewDidLoad];
    MainView * drawBox = [[MainView alloc] initWithFrame:(CGRectMake(60, 80, 200, 200))];
    drawBox.backgroundColor = [UIColor clearColor];
    [self.view addSubview:drawBox];
}
+1  A: 

You need to declare the property inside the @interface section of MainView, and your Weather weather; needs to be in the instance variable section of MainView as well.

UPDATE: In your viewDidLoad, you're adding your MainView as a subview to your VCs view property. Then when you want to use it, you're getting the VCs view property, and casting it to a MainView. You're not getting the view you want when you do that. You're getting the view that's holding your MainView. This is the source of your problem. self.view as you're referencing it, is a UIView not a MainView. The MainView is a subview of self.view.

jer
It is declared in MainView, see the first part of my post.
willingfamily
The first part of your post doesn't indicate WHERE you declared either. Add that next time if you don't want this type of answer.
jer
I'm sorry I wasn't more clear, when I stated `I have this before the interface declaration in my MainView.h header` I assumed that people would assume that the rest of the declaration stuff was in MainView as well. I'll edit to clarify.
willingfamily
Oh I bet you're right! How could I get the view that I want, then? I really appreciate your help, and I apologize I a so new at programming. Maybe I'm a little bit too deep over my level. :)
willingfamily
If your MainView is the actual view that holds every other view, then there's no point in adding it as the subview of the VC's view property. Instead, create a `loadView` method, and add some code like: `self.view = drawBox;` (Note, at no other time should you use the dot syntax with the view property except when setting it in the `loadView` method, otherwise you'll loop infinitely.) If it's not the only view, then add it as an instance variable to your VC. Then you'll be able to reference it directly. Alternatively you can iterate the subviews, but I really don't recommend that.
jer
Thanks for your help, jer, I'll give it a good read and experiment around with it!
willingfamily
A: 

in .m did you synthesize weather? e.g.

@synthesize weather; 

so that you'll have the getter and setter created.

[update] After reading your update in viewdidload, it is clear that you are accessing the wrong view because you simply used [self.view addSubView:], this means that self.view is not the MainView, it's just a subview. You can just declare MainView * drawBox as a global and access [drawBox setWeather:] directly.

Manny
Yes I did. The weather variable is working just fine, just I'm having problems setting it from another class.
willingfamily
Then your `self.view` isn't the right view.
jer
It's in `MainViewController`, if that changes anything?
willingfamily
Doesn't change anything. Post more code. Specifically, your `loadView` if you have one, and your `viewDiDLoad`. If you're using IB to connect your MainView to the MainViewController's view property, then ensure that the thing the view property is set to's class is MainView in IB.
jer
you should declare MainView as a global then access it from there, and not use self.view because it's not the same view. Or declare self.view = //main view here, or use the MainView class in your xib's primary View
Manny
+3  A: 

As a follow-up to my comment above:

You're probably either saying [[UIView alloc] initWithFrame:...] somewhere or you have an Interface Builder file with a View object. If you look in the inspector window with that object selected, it will indicate its "Class Identity" as UIView. Change this to MainView so the object will have the correct type at runtime.

warrenm
I actually didn't make MainView in IB, I made it as a subview using a CGRect. I'm problably making no sense at all, but I edited my post to include my `MainViewContorller` viewDidLoad code.
willingfamily
Do you see the problem now? You explicitly add an instance of `MainView` **to** `self.view`, but `self.view` is still an instance of UIView. So either send the `setWeather` message to that subview, or assign that instance **as** `self.view`.
warrenm
I do see my problem now. Thanks for your help!
willingfamily
+1  A: 

You added the MainView as a subview of self.view. When you pass setWeather, you are actually calling it on self.view (main view of your view controller, which is a UIView), not on the MainView subview of self.view.

Get the correct MainView object by iterating through self.view.subviews.

Edit: Or just keep an ivar pointing to the MainView subview around, so you can access it anytime.

  1. declare MainView *drawBox; in .h
  2. in viewDidLoad, init as drawBox = [[MainView alloc] initWithFrame:(CGRectMake(60, 80, 200, 200))];
  3. simply call [drawBox setWeather:CLEAR]; when you need to
Altealice
If I do that it says "NSArray may not respond to '-setWeather'.
willingfamily
Did you do something like MainView* myView = (MainView*)[self.view.subviews objectAtIndex:0]; ? just provide the right index.
Altealice
Basically, you called setWeather on the array, not on the array element, when you got that message.
Altealice
Okay, I tried the code you suggested and then did `[myView setWeather: CLEAR"]`. It didn't give warnings, but it still crashes my app when run.
willingfamily
You probably didnt get the correct subview. For a better approach, see my edits.
Altealice
In which header do I create the drawBox object? My View controller?
willingfamily
Yes, your view controller.
Altealice
I appreciate your help, but it's getting too late for me to try it tonight. If I reply to this little thread tomorrow will you see it? Thanks!
willingfamily
I'll probably see it. Let me know how it works out. :)
Altealice
EDIT: Oh my word. What you did was genius. By what you did, you also helped me to fix the other problem I was experiencing in a WHOLE different part of the program. Enjoy your upvotes, good sir! :)
willingfamily
Well thank you! :)
Altealice