Question

This is currently what I have for my init,

- (id)init 
{
    self = [super init];

    if (self) {
        self.url = [[NSURL alloc] init];
        self.blurb = [[NSString alloc] init];
        self.author = [[NSString alloc] init];
    }

    return self;
}

It does nothing, but I have another method called initWithObject: that will use its argument to fill up the instance variables url, blurb, and author. I don't know what I should be doing with this init. Should I throw an exception? What other options do I have?

Was it helpful?

Solution

If you want to override your standard -init method you could either return nil (if you do not want -init to be used) or do:

- (instancetype)init
{
    return [self initWithObject:nil];
}

If you want to stop the use of -init completely you can tag it as an unavailable attribute or use NSAssert:

// .h
// ...

- (instancetype)init UNAVAILABLE_ATTRIBUTE;

// ...

// .m
- (instancetype)init
{
    NSAssert(NO, @"This method should not be used");
    return nil;
}

You can use either UNAVAILABLE_ATTRIBUTE or NSAssert(), but if you use UNAVAILABLE_ATTRIBUTE you need some kind of implementation of -init, even if it just returns nil.

OTHER TIPS

You don't have to have a plain init—you can simply have your initWithObject: method. If you're doing any basic setup that will remain the same 80% of the time, or if you have some common code in all your initializers, you can override init, but you are not required to.

Also consider changing your initWithObject: name to be more specific, to something like initWithPost: (I'm assuming this is some kind of blog-entry fetcher based on your ivars) so it's more apparent what object is desired.

I think you misinterpreted what you read. I don't think you would throw an exception. You could; however, leak memory. If your initWithObject: method looks like this:

- (id)initWithObject:(id)obj {
     if ((self = [self init])) {
              self.url=[obj url];
              self.blurb=[obj blurb];
              self.author=[obj author];
     }
     return self;
}

And you would be perfectly fine. You could get an exception if your object was instantiated with -init and you used a variable which was assigned, assuming it was real. So in your subsequent methods be sure to check that the objects exist before using them.

If you made your object with -init rather than -initWithObject this could throw an exception:

- (void)dealloc {
         [url release];
         [blurb release];
         [author release];
         [super dealloc];
}

The rule that Apple has established for Cocoa programming is that every class must have one initializer method which is the "Designated Initializer". Every other initializer for the class must call that D.I.* The D.I. itself must call the superclass's D.I. Generally, the initializer with the greatest number of arguments (the one that most completely specifies the state of the new object) is the D.I.

In your case, with the bare init, and initWithObject:, the second would likely be the D.I. You would therefore override init to call initWithObject: with some default argument:

- (id) init {

    return [self initWithObject:[Object objectWithURL:[NSURL URLWithString:@"http://www.apple.com"]
                                                blurb:@""
                                               author:@""]];
}

This will result in a sort of dummy object, which is correctly initialized with useless data. (Outside of ARC, be sure to watch the memory management of the default argument(s) -- you want to use an autoreleased/unowned object(s).)

*Sometimes an exception is made for initWithCoder:.

If you have any method that you don't want called and that you don't want your subclass to support, throwing an exception in a Debug build is perfectly reasonable.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top