Ok, here's another question.
I am creating a UIView called ProgressView
that is a semi-transparent view with an activity indicator and a progress bar.
I want to be able to use this view throughout different view controllers in my app, when required.
I know of 3 different ways of doing this (but I am only interested in one):
1) Create the entire view programatically, instantiate and configure as required. No worries I get that one.
2) Create the UIView in interface builder, add the required objects and load it using a method like the below. Problem with this is that we are basically guessing that the view is the objectAtIndex:0 because nowhere in the documentation I found a reference to the order of the elements returned from the [[NSBundle mainBundle] loadNibName:
function.
NSArray *nibContents = [[NSBundle mainBundle] loadNibNamed:@"yournib"
owner:self
options:nil];
UIView *myView = [nibContents objectAtIndex:0];
myView.frame = CGRectMake(0,0,300,400); //or whatever coordinates you need
[scrollview addSubview:myView];
3) Subclass UIViewController and let it manage the view as per normal. In this case I would never be actually pushing the view controller onto the stack, but only its main view:
ProgressViewController *vc = [[ProgressViewController alloc] initWithNibName:@"ProgressView" bundle:nil];
[vc.view setCenter:CGPointMake(self.view.center.x, self.view.center.y)];
[self.view addSubview:vc.view];
[vc release];
As far as I can tell, #3 is the the correct way of doing this (apart from programatically) but I am not entirely sure if it is safe to release the ProgressView's view controller whilst another controller's view is retaining its main view (gut feel says it is going to leak?)?
What do I do in terms of memory management in this case, where and when should I release the ProgressView's view controller?
Thanks in advance for your thoughts.
Cheers,
Rog
A UINib object caches the contents of a nib file in memory, ready for unarchiving and instantiation. When your app needs to instantiate the contents of the nib file, it can do so without having to load the data from the nib file first, which improves performance.
The File owner is the object that loads the nib, i.e. that object which receives the message loadNibNamed: or initWithNibName: . If you want to access any objects in the nib after loading it, you can set an outlet in the file owner.
I think that your solution #3 adds unnecessary complexity by introducing a UIViewController instance just as a container for your ProgressView so that you can setup nib bindings. While I do think that it is nice to be able to work with an IBOutlet bound property rather than iterating through the nib contents you can do so without introducing a UIViewController whose behavior you neither need nor want. This should avoid your confusion around how and when to release the view controller and what, if any, side effects it might have on the responder chain or other behaviors of the loaded view.
Instead please reconsider using NSBundle and taking advantage of the power of that owner
argument.
@interface ProgressViewContainer : NSObject {
}
@property (nonatomic, retain) IBOutlet ProgressView *progressView;
@end
@implementation ProgressViewContainer
@synthesize progressView = progressView;
- (void) dealloc {
[progressView release];
[super dealloc];
}
@end
@interface ProgressView : UIView {
}
+ (ProgressView *) newProgressView;
@end
@implementation ProgressView
+ (ProgressView *) newProgressView {
ProgressViewContainer *container = [[ProgressViewContainer alloc] init];
[[NSBundle mainBundle] loadNibNamed:@"ProgressView" owner:container options:nil];
ProgressView *progressView = [container.progressView retain];
[container release];
return progressView;
}
@end
Create a nib named "ProgressView" containing a ProgressView and set it's File's Owner class to ProgressViewContainer. Now you can create ProgressViews loaded from your nib.
ProgressView *progressView = [ProgressView newProgressView];
[scrollView addSubview:progressView];
[progressView release];
If you have multiple configurations of your progress view then maybe you'll want to implement a -initWithNibNamed:
method on ProgressView instead of +newProgressView
so you can specify which nib to use to create each ProgressView instance.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With