7

Purely by accident I discovered that calling [bar.view addSubview:[foo view]] doesn't work, but [bar.view addSubview:foo.view] does in the following code.

foo=[fooViewController alloc] initWithNibName:@"fooViewController" andBundle:nil];
[self.view addSubview:foo.view];//here's where I swap the two commands out
[foo aFunctionThatSendsAMessageToOneOfFoosSubViews];

(That last line is because foo has some sub-views that need to be set up prior to running -- notably, a UIWebView. If they haven't been instantiated before the message is sent, the message winds up going to nil. With foo.)

I thought these two were functionally identical -- that foo.view calls the same getter that [foo view] does, but in practice that's not the case; the dot syntax gets the desired results, while using the brackets winds up sending the message to nil.

If you'd asked me ten minutes ago, I would have told you the difference between the two expressions was 'syntax, and nothing else'. Given that I'm clearly wrong, I need to understand HOW I'm wrong or I'm going to stumble over it again.

jscs
  • 63,694
  • 13
  • 151
  • 195
RonLugge
  • 5,086
  • 5
  • 33
  • 61
  • Did you try comparing actual output of `[foo view]` and `foo.view`? They _must_ be the same. – Costique Mar 28 '12 at 05:34
  • Actually, yes. I used NSLog(@"View Info: %@", [foo view]) and a similar foo.view statement. Identical -- even when I reverse them. The appear to return the exact same thing. – RonLugge Mar 28 '12 at 17:29
  • 1
    When you view your code in Xcode's Assistant Editor, and choose "Assembly" from the tuxedo drop-down, do you observe any difference between using dot syntax and brackets? – Carl Veazey May 10 '13 at 03:06
  • @CarlVeazey In all honesty, I don't even remember which project this was originally for. But I'll try to update this question with more info when I do. – RonLugge May 10 '13 at 03:09

2 Answers2

3

They are functionally equivalent. I think this is a race condition. When you first call foo.view in that code, the view is not loaded yet, and a call is sent to [foo loadView]. You can't be sure that the view is loaded until [foo viewDidLoad] is called or foo.isViewLoaded == YES.

You need to wait make sure the view is loaded before performing any actions that rely on it, such as [foo aFunctionThatSendsAMessageToOneOfFoosSubViews].

In your current case, sometimes it is loading in time and sometimes it isn't.

rosslebeau
  • 1,283
  • 6
  • 6
  • The problem with this answer (specifically, race condition) is that this is consistent over multiple tests. One approach works, the other does not. – RonLugge Mar 28 '12 at 02:46
  • Calling `self.view` forces the view to load _synchronously_. – Costique Mar 28 '12 at 05:32
-3

if i'm not mistaken the problem is that [foo view] tries to call a method named view (and if you don't have it the return is nil)

on the other hand in the case of foo.view, view is a property of the class

skytz
  • 2,201
  • 2
  • 18
  • 23
  • 2
    When you synthesize a property, it creates getter and setter methods. The default methods (which `UIViewController` uses for the `view` property) are `- (void)setProperty:(PropertyClass *)property;` for the setter and `- (PropertyClass *)property;` for the getter – rosslebeau Mar 28 '12 at 01:47
  • 1
    Additionally, if you tried to call a method that didn't exist, the app would crash due to an Unrecognized Selector error. – rosslebeau Mar 28 '12 at 01:48
  • 1
    yea..so i looked through `UIViewController.h` and the thing is that the property calls `[self loadView]` while `['class' view]` doesn't – skytz Mar 28 '12 at 02:06
  • 3
    The point is that viewController.view and [viewController view] are equivalent. The OP was correct in his original understanding and I believe his error is occurring for a different reason. – rosslebeau Mar 28 '12 at 02:17
  • Hey may be mistaken, but the idea that I'm getting a return of nil is interesting... I'll run some NSLogs to see what comes out of that. – RonLugge Mar 28 '12 at 02:47
  • Actually, the thought that the property calls [self loadView] is... possibly a solution to this type of issue in general. (I've run into the 'have to get the view on the screen before sending it a message' issue a few times...) (Oh, and if you made that an actual answer, you'd be much better off in terms of my accepting it...) – RonLugge Mar 28 '12 at 02:51
  • it wasn't an answer..it was more of an observation on whats happening here and the difference between a property and a method – skytz Mar 28 '12 at 11:39