When are the properties of the XIB outlet set?

I am trying to implement inheritance with xib files. Yes, a little strange, but let me tell you why.

I have a class SLBaseViewController, which many of my controllers inherit from. When I want a child view controller, I create it in the usual way:

SLHomeViewController *controller = [[SLHomeViewController alloc] initWithNibName:@"SLHomeViewController" bundle:nil]; 

It works great. SLHomeViewController is a SLBaseViewController (which is a UIViewController).

I do this because I have other view controllers that I want to inherit the behavior of SLBaseViewController. In my case, I have a navigation widget, which is a common occurrence for my application, so SLSceneViewControll inherits from SLBaseViewController, and both SLHomeViewController and SLSceneViewController also get user navigation widget behavior.

The custom navigation widget also has location information that is common to SLBaseViewControllers. Thus, I implemented a bad way to do xib inheritance.

 @interface SLBaseViewController : UIViewController <SLNavBarViewControllerDelegate> @property (strong, nonatomic) IBOutlet UIView *navBarExtendedFPO; 

and inheritance is done in initWithNibName

 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { Class callingClass = [self class]; Class slBaseViewControllerClass = NSClassFromString (SL_BASE_VC_CLASS_NAME); if (callingClass != slBaseViewControllerClass) { SLBaseViewController *controller = [[SLBaseViewController alloc] initWithNibName:@"SLBaseViewController" bundle:nil]; // now load all the properties by hand self.navBarExtendedFPO = controller.navBarExtendedFPO; } } return self; } 

If I create a SLHomeViewController, it loads the xib SLBaseViewController, and then copies an interesting property from it. If initWithNibName detects that it is loading the SLBaseViewController, it just does nothing, preventing an infinite loop.

The problem, of course, is that the output properties are not yet set. Therefore, it simply copies zero.

So, when are these outlet properties set?

Or - is there a better way to do what I'm trying to do? It all seemed pink until I copied the properties manually. It seems pretty fragile to me.

(Note that I'm fine with iOS6-only solutions.)

+4
source share
1 answer

This is due to the UIViewController lazy initialization.

The UIViewController view will only be loaded after some one invokes the view property.

like this:

 controller.view 

So, in your case, you can just call controller.view to self.navBarExtendedFPO = controller.navBarExtendedFPO;

To make the browsing life cycle more understandable, there is an example:

your SLBaseViewController has overridden methods, self.label is the analog of navBarExtendedFPO defined in the XIB file

 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { NSLog(@"initWithNibName: view loaded - %d , IBOuttlet loaded - %d", [self isViewLoaded], self.label != nil); } return self; } - (void)loadView { NSLog(@"loadView1: view loaded - %d , IBOuttlet loaded - %d", [self isViewLoaded], self.label != nil); [super loadView]; NSLog(@"loadView2: view loaded - %d , IBOuttlet loaded - %d", [self isViewLoaded], self.label != nil); } - (void)viewDidLoad { NSLog(@"viewDidLoad1: view loaded - %d , IBOuttlet loaded - %d", [self isViewLoaded], self.label != nil); [super viewDidLoad]; NSLog(@"viewDidLoad2: view loaded - %d , IBOuttlet loaded - %d", [self isViewLoaded], self.label != nil); } 

and there is a method that creates an SLBaseViewController

 SLBaseViewController *testController = [[SLBaseViewController alloc] initWithNibName:@"SLBaseViewController" bundle:nil]; NSLog(@"after initialization: view loaded - %d , IBOuttlet loaded - %d", [testController isViewLoaded], testController.label != nil); UIView * testView = testController.view; NSLog(@"after calling testView.view: view loaded - %d , IBOuttlet loaded - %d", [testController isViewLoaded], testController.label != nil); 

So there are our magazines:

 initWithNibName: view loaded - 0 , IBOuttlet loaded - 0 after initialization: view loaded - 0 , IBOuttlet loaded - 0 loadView1: view loaded - 0 , IBOuttlet loaded - 0 loadView2: view loaded - 1 , IBOuttlet loaded - 1 viewDidLoad1: view loaded - 1 , IBOuttlet loaded - 1 viewDidLoad2: view loaded - 1 , IBOuttlet loaded - 1 after calling testView.view: view loaded - 1 , IBOuttlet loaded - 1 
+5
source

All Articles