0

I'm updating my code from iOS 8 to iOS 9+, and in Xcode 8.2 I'm getting these warnings and have no idea how to fix it. I've seen a couple SO posts from a few years ago suggesting the solution is to silence the compiler rather than adjust the code.

What is the best way to handle these warnings without jeopardizing acceptance in the App Store?

One thing to note that is not in the screenshot but is in the same file - this initializer:

-(instancetype)initWithCoder:(NSCoder*)decoder{
    if(self=[super init]){
        // If parent class also adopts NSCoding, replace [super init]
        // with [super initWithCoder:decoder] to properly initialize.
        text=[decoder decodeObjectForKey:@"text"];
        fontname=[decoder decodeObjectForKey:@"font"];
    }
    return self;
}

enter image description here

This is the accompanying Message.h:

#import <Foundation/Foundation.h>

@interface Message : NSObject <NSCoding>{
    NSString    *text;
    NSString    *fontname;
    UIColor     *color;
    NSInteger   speed;
    NSInteger   fontsize;
    BOOL        isMirror;
    BOOL        isReverse;
    NSInteger   transStyle;
    NSInteger   transDir;
    NSInteger   transSpeed;
    BOOL        isTransition;
    BOOL        isTextOnly;
    NSInteger   transOther;
    NSInteger   transPause;
}

@property (nonatomic,retain)NSString    *text;
@property (nonatomic,retain)NSString    *fontname;
@property (nonatomic,retain)UIColor     *color;
@property (nonatomic,assign)NSInteger   speed;
@property (nonatomic,assign)NSInteger   fontsize;
@property (nonatomic,assign)BOOL        isMirror;
@property (nonatomic,assign)BOOL        isReverse;
@property (nonatomic,assign)NSInteger   transStyle;
@property (nonatomic,assign)NSInteger   transDir;
@property (nonatomic,assign)NSInteger   transSpeed;
@property (nonatomic,assign)NSInteger   transOther;
@property (nonatomic,assign)NSInteger   transPause;
@property (nonatomic,assign)BOOL        isTransition;
@property (nonatomic,assign)BOOL        isTextOnly;

- (void) encodeWithCoder:(NSCoder*)encoder;
- (instancetype) initWithCoder:(NSCoder*)decoder NS_DESIGNATED_INITIALIZER;

@end
wayneh
  • 4,393
  • 9
  • 35
  • 70

2 Answers2

3

You've got two options:

  1. Remove NS_DESIGNATED_INITIALIZER from -initWithCoder:
  2. Add NS_DESIGNATED_INITIALIZER to -init
  3. Change -init to call [self initWithCoder:]

The first two make the most sense; 2 would be rather difficult with no coder.

Wevah
  • 28,182
  • 7
  • 83
  • 72
  • How does this fit the answer from @Maddy ? Are all of these valid, and if so is it just a matter of preference which to use? – wayneh May 17 '17 at 13:18
  • Either way works. The point is that any of your class's initializers that *aren't* a designated initializer should be calling a designated initializer *instead* of `[super init]`, and the designated initializers of your class *should* be calling `[super init]`. – Wevah May 18 '17 at 07:07
  • ok -that helps too - I guess it's pretty straight forward - have one designated initializer and any others must call it so that it always gets called. – wayneh May 19 '17 at 02:22
  • You can have more than one, as long as those rules are followed. – Wevah May 19 '17 at 02:32
2

Explanation on Apple Forum: https://forums.developer.apple.com/thread/6757

The rules for designated initialisers are complex and I'm going to bounce you to the docs for the general case. Curiously, I've found the best explanation of this to be the "Initialization" section of The Swift Programming Language, because the same concepts apply to both Swift and Objective-C. In your specific case you should override -init and have it fail at runtime. You should also tag it in your header with NS_UNAVAILABLE which will allow the compiler to catch this in the typical case. The above applies because your class can't possibly operate without a Model, and thus you can't reasonably implement -init in any useful way. If you could, you should. For example, if you were creating your own string object, it would make sense for it to implement -init by calling super and then initialising the string to the empty string.

Add below line to your Message.h file

-(instancetype)init NS_DESIGNATED_INITIALIZER;

For more details check the link below

Using NS_DESIGNATED_INITIALIZER

Community
  • 1
  • 1
Maddy
  • 1,660
  • 11
  • 24
  • Would adding that line cause an issue since there is already a line with `NS_DESIGNATED_INITIALIZER` ? (You might have answered before I added the Message.h code) – wayneh May 17 '17 at 13:07