How to init integer in iOS? - ios

I define
#property (nonatomic, assign) int currentUserNum;
#property (nonatomic, assign) BOOL isAlive;
in #interface MyClass
and defined -init method in #implementation MyClass
#synthesize currentUserNum, isAlive;
-(id) init {
if (self = [super init]) {
self.currentUserNum = 0;
self.isAlive = YES;
}
return self;
}
self.currentUserNum = 0; is crashed , but self.isAlive = YES; can work ! They are both assign property.
I want to know why ? Thanks!

Your init method is missing a lot of important code.
- (id)init {
if ((self = [super init])) {
_currentUserNum = 0; // it's not wise to reference properties in the init method
}
return self;
}
Every init method should follow this basic pattern. You assign self the value of calling an appropriate super init or other self init. If that's not nil, you then perform appropriate initialization code, and finally you return self.

Related

Setting properties defined in a super class in the initialiser

From what I learned a general rule of thumb setting values in init is a matter of using the ivars directly.
For example
#interface CustomClass
#property (nonatomic, strong) NSString *name;
#end
and then:
- (instancetype)initWithName:(NSString *)name
{
if (self = [super init]) {
_name = name;
}
return self;
}
Now so far so good. I'm interested in a slightly different case. Let's say you're subclassing a UIView and in the initialiser you want to assign a background color to that subclass. Here, the property backgroundColor is defined in the parent class. My question is: Is it bad style or potentially wrong to use self in the initialiser? Would it be better to set the background color somewhere else?
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
self.backgroundColor = [UIColor greenColor];
}
return self;
}
I believe it is perfectly fine what you are doing there. At that point, after calling super.init, the self exists, and you can use it (you are calling return self, too, so why would other references to self be wrong?).

what's the use of #property(strong) in OC?

My English is not good, I try to describe the problem clearly.
I know that #property and #synthesize are just to get getter and setter methods. So we can use property by self.x and _x.
And self.x is just to call setter and getter methods.
The result of #property(strong) is get methods as following:
All is in ARC:
#property (nonatomic, strong) NSString *name;
- (NSString *)name {
return _name;
}
- (void)setName:(NSString *)name {
if (_name != name) {
_name = name;
}
}
So, my question is that if the use of #property(strong) is just to get methods, we can use the following.
- (void)setName:(NSString *)name {
if (_name != name) {
__weak _name = name;
}
}
When we use self.name to set setName: method call, and we get a weak name, even we use strong before, it looks right. But there is a other examples.
#protocol TestDelegate <NSObject>
#end
#interface Test : UIView
#property (nonatomic, weak) id<TestDelegate> delegate;
- (instancetype)initWithDelegate:(id<TestDelegate>)delegate;
#end
- (instancetype)initWithDelegate:(id<TestDelegate>)delegate {
self = [super init];
if (self) {
_delegate = delegate;
}
return self;
}
Use in ViewController, all is dealloc, no recycle. Then we use
#property (nonatomic, strong) id<TestDelegate> delegate;
- (instancetype)initWithDelegate:(id<TestDelegate>)delegate {
self = [super init];
if (self) {
self.delegate = delegate;
}
return self;
}
- (void)setDelegate:(id<TestDelegate>)delegate {
__weak _delegate = delegate;
}
All is dealloc, no recycle too. Because we use self.delegate in init method, setDelegate: method call and we get weak delegate, even we use strong before. Then we use _delegate = delegate, it will recycle!!!
It is puzzled for me that we use weak and _delegate = delegate, it run well, but we use strong, _delegate = delegate and custom weak set method, it is recycle.
Thanks!
The delegates must be weak type of properties. This will avoid retain cycle because there can be endless circle of retaining two objects between themselves. With using ARC this is example of using delegate: #property (nonatomic, weak) id <MyObjectDelegate> delegate;

ios - override init method throws method implementation does not match its declaration

Trying to override init method (to create instance with already initialized tag) in class and getting exception. Code sample:
#interface DiagnosticsReport : NSObject {
}
#property NSString *tag;
- (void) initWithTag:(NSString*) tag;
#end
#implementation DiagnosticsReport
- (id) initWithTag:(NSString*) tag {
if (self = [self init]) {
_tag = tag;
}
return self;
}
- (id) init {
if (self = [super init]) {
// default init here
}
return self;
}
Your declaration of method returns void, while definition returns id. Change both to return instancetype and you're good to go.

override property from superclass in subclass

I want to override an NSString property declared in a superclass. When I try to do it using the default ivar, which uses the the same name as the property but with an underscore, it's not recognised as a variable name. It looks something like this...
The interface of the superclass(I don't implement the getter or setter in this class):
//Animal.h
#interface Animal : NSObject
#property (strong, nonatomic) NSString *species;
#end
The implementation in the subclass:
//Human.m
#implementation
- (NSString *)species
{
//This is what I want to work but it doesn't and I don't know why
if(!_species) _species = #"Homo sapiens";
return _species;
}
#end
Only the superclass has access to the ivar _species. Your subclass should look like this:
- (NSString *)species {
NSString *value = [super species];
if (!value) {
self.species = #"Homo sapiens";
}
return [super species];
}
That sets the value to a default if it isn't currently set at all. Another option would be:
- (NSString *)species {
NSString *result = [super species];
if (!result) {
result = #"Home sapiens";
}
return result;
}
This doesn't update the value if there is no value. It simply returns a default as needed.
to access the superclass variables, they must be marked as #protected, access to such variables will be only inside the class and its heirs
#interface ObjectA : NSObject
{
#protected NSObject *_myProperty;
}
#property (nonatomic, strong, readonly) NSObject *myProperty;
#end
#interface ObjectB : ObjectA
#end
#implementation ObjectA
#synthesize myProperty = _myProperty;
#end
#implementation ObjectB
- (id)init
{
self = [super init];
if (self){
_myProperty = [NSObject new];
}
return self;
}
#end

Objective-C call specific class method

I have a class that has this in the initializer:
#implementation BaseFooClass
-(id) init
{
if (self = [super init])
{
// initialize instance variables that always need to start with this value
}
return self;
}
-(id) initWithSomeInt:(int) someInt
{
if (self = [self init]) // <-- I need to make sure that I am calling BaseFooClass's init here, not SubFooClass's, does that make sense?
{
self.someInt = someInt;
}
return self;
}
#end
That is all fine and dandy. My problem is that when I implement the subclass:
#implementation SubFooClass
-(id) init
{
return [self initWithSomeInt:0];
}
-(id) initWithSomeInt:(int) someInt
{
if (self = [super init]) // <--- Infinite loop (stack overflow :) )
{
// initialize other variables
}
}
#end
I basically need to specifically call the BaseFooClass's init rather than the SubFooClass's init.
I cannot change the way the objects are initialized, as I am converting a project from C# to use in my iPad application.
Thank you all in advance
EDIT:
Due to someone asking, here is my header:
#interface BaseFooClass : NSObject
// implicit from NSObject
// -(id) init;
-(id) initWithSomeInt:(int) someInt;
// more methods
#end
#interface SubFooClass : BaseFooClass
// implicit from NSObject
// -(id) init;
// implicit from BaseFooClass
//-(id) initWithSomeInt:(int) someInt;
#end
Objective-C doesn't work this way because of the way the runtime converts methods into function calls. Self is always an instance of the allocated class, even when invoking the super-class's methods. You need to create your designated initializer for your BaseClassFoo and always go there. So you should be doing something like this:
#implementation BaseFooClass
-(id) init
{
return [self initWithSomeInt:0]; // redirect super class's designated initializer
}
-(id) initWithSomeInt:(int) someInt
{
if ((self = [super init])) // Designated initializer always calls into super class's designated initializer (in this case, NSObject's designated initializer is init
{
self.someInt = someInt;
}
return self;
}
#end
#implementation SubFooClass
// Here we don't override init because our super class's designated initializer
// is initWithSomeInt:
// -(id) init
// {
// return [self initWithSomeInt:0];
// }
// we override this because it's our superclass's designated initializer, plus it
// is ours as well
-(id) initWithSomeInt:(int) someInt
{
if ((self = [super initWithSomeInt:someInt]))
{
// initialize other sub-class specific variables
}
}
#end
You have to call [super initWithSomeInt:someInt]; in the init method of your SubFooClass.
;)
ADDED:
I think is weird you try to call init within iniWithSomeInt . The usual thing would be to call [super initWithSomeInt:someInt] in initIthSomeInt method of SubFooClass and change what you need inside the if clause.

Resources