subclassing initWithFileURL of an UIDocument - iphone

I'm trying to overwrite the initWithFileURL of an UIDocument as I need to call some custom methods once an UIDocument is initialised.
I thought this may be a good idea:
-(id)initWithFileURL:(NSURL *)url {
self = [super initWithFileURL:url];
// do some custom stuff
return self;
}
Is there anything else I need to do if I overwrite this? I have the feeling that I need to check for NIL or something. Where do you usually look if you need to overwrite a method with something custom? I was only able (via jump to definition when right clicking UIDocument) to see this:
#pragma mark *** Initialization ***
// The designated initializer. Passing an empty URL will cause this method to throw an NSInvalidArgumentException.
- (id)initWithFileURL:(NSURL *)url;

You should probably be doing this.
-(id)initWithFileURL:(NSURL *)url {
self = [super initWithFileURL:url];
if(self) {
// Your custom stuff here
}
return self;
}

Related

MainViewController init

I have set up a utility application and I found that the init method of MainViewController is not called automatically. Is there some other method that is set up automatically by XCode for initialization? Or if I have to add it, where would I add it? I was just going to call init manually from an IBOutlet method but I would prefer that the initializations be done when the view is first initialized.
Not sure where you'r going but (generated) .xib files are called using the withCoder init.
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
//self implementation
}
return self;
}
See the Utility Template in Xcode.
And check this method called..
- (IBAction)done:(id)sender
{
[self.delegate flipsideViewControllerDidFinish:self];
}
check it..

Creating constructors in Objective-C

Why do we always do this when creating constructors in Objective C?
self = [super init];
if ( self ) {
//Initialization code here
}
you can create constructor and destructor in objective-c with
-(id) init
{
self = [super init];
if(self)
{
//do something
}
return self;
}
-(void) dealloc
{
[super dealloc];
}
We reassign to self because [super init] is allowed to return a different object than the one it was called on. We if (self) because [super init] is allowed to return nil.
self is a class based on some superclass (e.g. UIViewController, NSObject - see your interface file to be sure which one). The superclass might need some form of initialization in order for the subclass to work as expected. So by first initializing the superclass we make sure default properties and the like are set. Without initializing the superclass first, we might experience some very unexpected behavior, especially in more complex objects like ViewControllers and the like.
Read this apple document on initialization
http://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/ObjectiveC/Chapters/ocAllocInit.html

Strange custom delegate actions

Ok -- this one is weird. I have a singleton class that loads information from an XML file. I am using a delegate definition as follows (I define the delegate in a separate header file to make life easier):
#protocol ResourceClassDelegate <NSObject>
#optional
- (void)picturesDidStartLoading;
- (void)picturesDidFinishLoading;
#end
In the resource file, the delegate is defined correctly (I believe):
#property (assign) id<ResourceClassDelegate> delegate;
When using the delegate, the code in the resource class is as follows:
-(void)refreshPiecesOfHistoryWithOperation {
NSLog(#"Operation Started");
if ([delegate respondsToSelector:#selector(picturesDidStartLoading)])
[delegate picturesDidStartLoading];
self.picturePacks = [HistoryXMLParser loadPicturePacks];
[self.allPiecesOfHistory removeAllObjects];
// now lets put all of them in one big file...
for (PicturePack *pp in self.picturePacks) {
for (int ct = 0; ct < [[pp piecesOfHistory] count] ; ct++) {
[self.allPiecesOfHistory addObject:(PieceOfHistory *)[[pp piecesOfHistory] objectAtIndex:ct]];
}
}
NSLog(#"Operation Ended");
if ([delegate respondsToSelector:#selector(picturesDidFinishLoading)])
[delegate picturesDidFinishLoading];
}
Now... in the class that is listening to the delegate, it is assigned:
- (void)viewDidLoad {
[super viewDidLoad];
// now for the part that makes the loading all happen...
[[ResourceClass sharedResourceClass] setDelegate:self];
}
And in the listening class, the methods are defined....
#pragma mark ResourceClassDelegate
-(void)picturesDidStartLoading {
if (loadingActivity == nil)
loadingActivity = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[self.view addSubview:loadingActivity];
[loadingActivity setCenter:[self.view center]];
[loadingActivity startAnimating];
}
-(void)picturesDidFinishLoading {
if (loadingActivity != nil) {
[loadingActivity stopAnimating];
[loadingActivity removeFromSuperview];
}
[self.tableView reloadData];
}
Now for the problem... every single time, in the listening class, the method (void)picturesDidFinishLoading is called. The method (void)picturesDidStartLoading never is called.
When I debug the code, in the resource class, the line
if ([delegate respondsToSelector:#selector(picturesDidStartLoading)])
[delegate picturesDidStartLoading];
never reaches the delegate method call - even if I remove the if statement. The line
if ([delegate respondsToSelector:#selector(picturesDidFinishLoading)])
[delegate picturesDidFinishLoading];
is always called.
any ideas?
Ok -- I figured it out....
The delegate was nil during the first call. The reason it is nil is because the function using the delegate was called in the source during the init method. The init method was not complete when the first test of the delegate was performed. At this time the delegate was nil because it is not instantiated until the the init method completes. The reason the second test of the delegate worked is because I submitted the process using an NSOperationQueue.
To fix the problem I have to move things around a bit... it's all about the timing!
Well now that was fun....
That's weird, try to remove #optional in the protocol declaration, and see if you get some warnings.
Try to print a log inside the method as well, other than that it looks fine.

initWithCoder: getting called by nib & NSCoding!

Ok, I'm having a lot of problems right now trying to get initWithCoder: to work right. I have a nib file that gets loaded, and in my app delegate, I call unarchiveWithFile: for the view controller that is associated with that nib, and now my app crashes. I can see that initWithCoder: is being called twice, presumably once from when awakeFromNib: is called, and then from when I call unarchiveWithFile: since the view controller conforms to NSCoding. But now either it crashes as soon as the view loads or when I press an IBOutlet. Any suggestions??
Edit: Here's the code for initWithCoder:
- (id)initWithCoder:(NSCoder *)coder {
[super initWithCoder:coder];
[[self mapView] addAnnotations:[[coder decodeObjectForKey:#"Annotations"] retain]];
return self;
}
All I'm doing is decoding an array of annotations for a map view, but somewhere along the line this method is being called twice and then it crashes.
Don't forget to put the nil check in your init methods. E.g. the method you posted would be more correct if you wrote it as:
- (id)initWithCoder:(NSCoder *)coder {
if (self = [super initWithCoder:coder]) {
[[self mapView] addAnnotations:[[coder decodeObjectForKey:#"Annotations"] retain]];
}
return self;
}
That's not the cause of your problem, however.
Is there are good reason for you unarchiving your view controller yourself? If you're not doing anything special, you can rely on the existing mechanisms to do it. The default implementation of init for a UIViewController looks for a nib with the same name as your view controller, and if it exists, it loads the nib (via initWithNibName).
If there is data which you need to archive in and out, it may be that it shouldn't be actually part of the UIViewController. Factor it out elsewhere perhaps?
you can try
- (id)initWithCoder:(NSCoder *)coder {
if(self == nil)
{
[super initWithCoder:coder];
[[self mapView] addAnnotations:[[coder decodeObjectForKey:#"Annotations"] retain]];
}
return self;
}

iPhone: Error when using -(id)initWithNibName

I am trying to use the following code, but I always get an error that I can find little information about:
- (id)initWithNibName:#"MyRidesListView" bundle:nil {
if ((self = [super initWithNibName:#"MyRidesListView" bundle:nil])) {
// Custom initialization
}
return self;
}
Error:
expected identifier before 'OBJC_STRING' token
This seems like a simple method to be calling. This is for a UINavigationController.
Ideas?
It looks like you are trying to implement a constructor method in a subclass of UIViewController or UINavigationController.
YOur syntax is a bit off. Without seeing what you are doing in a broader context I don't really know what is going on here, but this might help you out a bit. Its the closesest to your code while being syntactically correct.
- (id)initWithNibName:(NSString *)nibNameOrNull bundle:bundle {
if ((self = [super initWithNibName:nibNameOrNull bundle: bundle])) {
// Custom initialization
}
return self;
}
Then you can do this outside of your class:
[[MyRidesListView alloc] initWithNibNamed:#"MyRidesListView" bundle:nil];