Objective-C: What is the difference between + and - in getters and setters? - objective-c

What is the difference of using:
+ (id) myMethod;
// Rather than
- (id) myMethod;

Using a + declares the method as a class method, or a method that can be called directly on the class, where the class is the object. So when you have this:
#implementation Foo
+(NSString*)method1 {
return #"Foo";
}
-(NSString*)method2 {
return #"Foo";
}
#end
The methods are called in different ways:
[Foo method1]; //=> #"Foo"
Foo* f=[[Foo alloc] init];
[f method2]; //=> #"Foo"
One other thing to note is that class methods don't have access to an instance, which means they can't access any kind of instance variables.

#Linuxios pretty much summed up the concept of class and instance method. However, since you mentioned getters and setters in your title, I want to point out that in Objective-C you can use properties instead of writing your own accessor methods. For example,
In the header file, you will have something like this:
#interface MyObject : NSObject
#property (nonatomic,retain) NSSet* mySet;
#end
In the m file, you wil have something like this:
#implement MyObject
#synthesize mySet;
#end
To access the set in another class you can do it like this:
myObject.mySet; // assuming myObject is an instance of the MyObject class

The top one is a class method (no instance required)
The second one is a instance variable (attached to a specific instance).
This answer explains the methods quite well:
Method Syntax in Objective C
[MyObject myMethod]; // did not have to create an instance
MyObject* myNewObject = [[MyObject alloc] init] autorelease];
[myNewObject myMethod]; // had to create an instance

Related

Objective-C class method local variables of type "self"

We're all familiar with the following pattern for instantiating instances of a class:
+ (instancetype)createInstance {
return [[self alloc] init];
}
This works because "self" in this case refers to the class rather than an object built from the class blueprint.
We also know this declaration, most commonly used in avoiding retain cycles:
typeof(self) someStrongSelf = self;
This is allows self's type to be dynamic and that code could be copy-pasted wherever needed no matter the class.
My question deals with combining the above two patterns when instantiating from a class method:
+ (instancetype)createInstance:(MyObject*)dependency {
typeof(self) instance = [[self alloc] init];
instance.dependency = dependency;
return instance;
}
This won't work because self is a class, and a typeof(class) is just a Class, but is there some mechanism for local variables equivalent to instancetype that would allow me the same flexibility as typeof(instance)? For example:
+ (instancetype)createInstance:(MyObject*)dependency {
instanceof(self) instance = [[self alloc] init]; //desired keyword
instance.dependency = dependency;
return instance;
}
If I really wanted this formalized, I know an alternative to this would be defining a protocol that does basically the same thing as above, but I'm curious if Objective-C allows the desired declaration style out of the box.
I understand what you're looking for, but there is no instanceof(self) pattern. The following achieves what you want, though admittedly doesn't have the elegance of typeof(self) pattern:
#interface Foo: NSObject
#property (nonatomic, copy) NSString *string;
#end
#implementation Foo
+ (instancetype)fooWithString:(NSString *)string {
Foo *foo = [[self alloc] init];
foo.string = string;
return foo;
}
#end
#interface Foobar: Foo
// perhaps some more properties here
#end
#implementation Foobar
// and perhaps some more methods here
#end
This implementation demonstrates that the convenience method still allows subclassing. I.e., you can do:
Foobar *foobar = [Foobar fooWithString:#"baz"];
And the resulting object will be a Foobar instance.

Variable losing value in delegation pattern

I'm trying to learn about delegation in Objective-C, and am having a minor issue with a variable losing it's data in the transfer process. I have Class1 that contains an NSMutableArray. The array gets populated, then I would like to transfer the array's values to Class2, and display it. Here is the relevant code in Class1:
//Class1.h
#class Class1;
// define the protocol for the delegate
#protocol Class1Delegate
#required
-(void)sayHello:(Class1 *)customClass withAntArray:(NSMutableArray *)antArray;
#end
#interface Class1 : MySuperClassName
#property (nonatomic, assign) id delegate;
-(void)helloDelegate;
#end
//Class1.m:
#interface Class1 ()
#property (nonatomic, strong) NSMutableArray *antOccurenceTimes;
#end
#implementation Class1
#synthesize antOccurenceTimes;
-(void)helloDelegate
{
// send the message to the delegate
[_delegate sayHello:self withAntArray:self.antOccurenceTimes];
}
Now, this is what I have in Class2:
#import "Class1.h"
#interface Class2 : UIView <Class1Delegate>
#end
// Class2.m:
- (void)appropriateTimeToCallMethod {
Class1 *initAntMarks = [[Class1 alloc] init];
initAntMarks.delegate = self;
[initAntMarks helloDelegate];
}
-(void)sayHello:(Class1 *)customClass withAntArray:(NSMutableArray *)antArray {
NSLog(#"Hello! %#", antArray.description);
}
The antArray.description reads as "NULL". Now, I figured that obviously it will be null, because I just created an entirely new instance of the class right before calling upon the needed method. I feel like I may have something mixed up, and being so new to delegation, I'm not sure exactly what. Does anyone know what I need to tweak to utilize Delegation?
I forgot to add that I did initialize it in Class1, and it gets populated just fine. It's only in class2 that this is occurring.
I initalize antOccuranceTimes in a separate method in ClassA in the snippet below, and the NSLog fires twice...
NSLog(#"Array initalized in class A");
antOccurenceTimes = [NSMutableArray new];
Change this line:
#property (nonatomic, assign) id delegate;
to:
#property (nonatomic, weak) id <Class1Delegate> delegate;
assign should only be used for C primitives, not Objective-c object references. You should also be checking if your object actually conforms to the delegate before messaging the delegate.
Edit:
I think you may be confused about the purpose of delegation.
Class1 *initAntMarks = [[Class1 alloc] init];
initAntMarks.delegate = self;
[initAntMarks helloDelegate];
Why are you calling a method on an object which in turn calls a delegate method when you could simply create a method that returns the NSMutableArray? The way you have your code currently set up requires that before the call to -helloDelegate you have to have filled the array with the appropriate objects. The purpose of delegation in MVC is to inform an object about an event that took place inside of another object. You are "delegating" the task off to another object, or you could say, that another object if responsible for the fulfillment of the task. Read the Apple Docs on Delegation. Delegation in your code is not the correct pattern to implement, as I stated you can simply return that array with a method call.
Edit 2:
There are two ways you can achieve this, through property methods or through an explicit method that returns your array. If you choose to use property methods, the property declaration must be in the public interface i.e. the .h file so that your class can all the accessors when the object is being implemented.
//Inside the .h
#property (nonatomic, strong) NSMutableArray *antOccurenceTimes;
This will automatically provide you with two accessor methods for the antOccurenceTimes property. These are the getter -antOccurenceTimes and setter -setAntOccurenceTimes: methods. Now after you initialize the class and fill your array you can call -antOccurenceTimes to return the array.
You can also create an explicit method that return the array:
- (NSMutableArray *)hello{
//Do something here
return _antOccurenceTimes;
}
You have not yet initialized the antOccurenceTimes. Of cause it is nil. There are many options depending on what you need. You can, for example, initialize it in a init function:
- (instancetype)init {
self = [super init];
if( self ) {
antOccurenceTimes = [NSMutableArray array];
[antOccurenceTimes addObject:#"Hello World"];
}
}
Or maybe initialize it before you call the delegate the function.
-(void)helloDelegate
{
// send the message to the delegate
self.antOccurenceTimes = [NSMutableArray array];
[self.antOccurenceTimes addObject:#"Hello World"];
[_delegate sayHello:self withAntArray:self.antOccurenceTimes];
}
I think you get my point.

What is the difference between declaring a member in the extended interface versus in the implementation?

I am seeing two very different behaviors for something that I thought were the exact same.
Defining my private member in the class extension like this:
#interface ClassA ()
#property ClassB* b;
#end
#implementation ClassA
-(ClassA*)initWithClassB:(ClassB*)newB
{
self.b = newB;
return self;
}
-(ClassB*)getB
{
return self.b;
}
Or defining my private member in the class implementation like this:
#interface ClassA ()
#end
#implementation ClassA
ClassB* b;
-(ClassA*)initWithClassB:(ClassB*)newB
{
b = newB;
return self;
}
-(ClassB*)getB
{
return b;
}
The way I am using this code is to create a ClassB object, initialize a ClassA object with that ClassB object, and then add the ClassA object to a mutable array
-(void)init
{
self.classAList = [[NSMutableArray alloc] init];
[self.classAList addObject:[[ClassA alloc] initWithClassB:[self createClassB1]]];
[self.classAList addObject:[[ClassA alloc] initWithClassB:[self createClassB2]]];
[self.classAList addObject:[[ClassA alloc] initWithClassB:[self createClassB3]]];
}
-(ClassB)createClassB1
{
ClassB* classB = new ClassB();
//do some init
return classB;
}
// Same thing fore createClassB2 and createClassB3 except with different data
When I use the first approach, and define my member in the interface extension, I see that each element in my mutable array is indeed what I would expect.
However, using the second approach, I see that my ClassB* b pointer in the ClassA object always ends up pointing to the most recently created ClassB object. That is, once the -(void)init method finishes, the ClassB pointers in each of the ClassA objects points to the ClassB object I created in createClassB3
What is happening here?
I should also mention that the ClassB object is a C++ object and this is a an objective-c++ class.
In your second snippet, b is just a global variable at file scope. The fact that it's inside of the #implementation ... #end is irrelevant. It is not an instance variable nor a property.
With the second approach you're creating a global variable, meaning it's not related to any instance of ClassA, so you will always have one and the same instance of *b pointing to the same object in memory. So anytime you change the value of the *b you're changing the object in memory at which the b variable is pointing, but never creating a new one; to understand it better you're basically initialising every ClassA object with the same ClassB variable (which is *b), so if you change the value at the portion of memory to which *b is pointing you're changing it for all the instances of ClassA created.
Hope it's clear enough.

Which one is initialized, property or its instance variable

Suppose I have a property called myPropertyName defined in my class MyClassName. Manual memory management is used throughout this post.
MyClassName.h
#import <UIKit/UIKit.h>
#interface MyClassName : NSObject {
#private
NSObject* myPropertyName;
#public
}
#property (nonatomic, retain) NSObject* myPropertyName;
// Some methods prototypes are here
#end
MyClassName.m
#import "MyClassName.h"
#implementation MyClassName
#synthesize myPropertyName;
// Some methods are here
#end
I'm confused with usages such as the place of myPropertyName declaration, its difference between instance variable. For example, what is the difference among these three statement of initialization code, for example, in the customized -(void)init method for my class myClassName.
self.myPropertyName = [[[NSObject alloc] init] autorelease];
This one is calling myPropertyName setter, but I'm not sure what is the name of the instance variable being used in the setter, myPropertyName (since I've declared a #private field named myPropertyName) or _myPropertyName (people say that this one with underbar is the default)?
myPropertyName = [[NSObject alloc] init];
Does this initialize the instance variable of the myPropertyName property? If I don't have #synthesize myPropertyName = _myPropertyName;, would it be wrong since the default instance variable for the property is said to be _myPropertyName.
_myPropertyName = [[NSObject alloc] init];
Is _myPropertyName still declared as the instance variable for my property myPropertyName even if I use #synthesize myPropertyName; and #private NSObject* myPropertyName;?
In my understanding, a property is just a name (such as myPropertyName), there should be some instance variable encapsulated to be used in actual operations in the code, such as assigning values.
First off, I highly recommend reading Apple's documentation on properties, also linked by nhgrif. However, I understand docs can be a bit dense reading material (though Apple's, I find, are not so bad), so I'll give a brief overview of properties here.
I like examples, so I'm going to rewrite your two classes in a bit more current form.
MyClassName.h
#import <UIKit/UIKit.h>
#interface MyClassName : NSObject
#property (nonatomic, strong) NSObject *myPropertyName;
// method prototypes here
#end
MyClassName.m
#import "MyClassName.h"
#implementation MyClassName
// some methods here
#end
The class MyClassName now has a property called myPropertyName of type NSObject *. The compiler will do a lot of work for you for "free" in this instance. Specifically, it will generate a backing variable, and also generate a setter and getter for myPropertyName. If I were to rewrite the two files, and pretend I'm the compiler, including that stuff, they would look like this:
MyClassName.h
#import <UIKit/UIKit.h>
#interface MyClassName : NSObject {
NSObject *_myPropertyName;
}
#property (nonatomic, strong) NSObject *myPropertyName;
- (void)setMyPropertyName:(NSObject *)obj;
- (NSObject *)myPropertyName;
#end
MyClassName.m
#import "MyClassName.h"
#implementation MyClassName
- (void)setMyPropertyName:(NSObject *)obj
{
_myPropertyName = obj;
}
- (NSObject *)myPropertyName
{
return _myPropertyName;
}
#end
Again, all of this is happening for "free": I'm just showing you what's happening under the hood. Now for your numbered questions.
self.myPropertyName = [[[NSObject alloc] init] autorelease];
First of all, you should probably be using Automatic Reference Counting, or ARC. If you are, you won't be allowed to call autorelease. Ignoring that part, this works fine. Excluding the autorelease, this is exactly equivalent to:
[self setMyPropertyName:[[NSObject alloc] init]];
Which, if you look at the second .m file I wrote out, above, will basically translate to:
`_myPropertyName = [[NSObject alloc] init];
myPropertyName = [[NSObject alloc] init];
As written, this code will give a compiler error, since there is no variable called myPropertyName in this class. If you really want to access the instance variable underlying (or, "backing") the myPropertyName property, you can, by using its real name:
_myPropertyName = [[NSObject alloc] init]; // note the underscore
But most of the time, it's better to use the setter, as in point 1., since that allows for side effects, and for Key-Value Coding, and other good stuff.
_myPropertyName = [[NSObject alloc] init];
Oh. Well you got it. See point 2.
You mentioned that:
I'm confused with usages such as the place of myPropertyName declaration, its difference between instance variable. For example, what is the difference among these three statement of initialization code, for example, in the customized -(void)init method for my class myClassName.
In case it hasn't been made clear, a property is something of an abstract concept; its data is stored in a normal instance variable, typically assigned by the compiler. Its access should usually be restricted to the setter and getter, with important exceptions. To keep this answer short, I won't go into more detail than that.
One more thing: as nhgrif mentioned, you don't need to use the #synthesize keyword anymore. That is implicitly understood by the compiler now.
If you're not sure about any of this, post a comment or, better yet, read the docs.
Let's take this example:
#property NSString *fullName;
If in the implementation, we override the setters and getters, and in these setters and getters, we don't use an instance variable fullName, it is never created. For example:
- (NSString *)fullName
{
return [NSString stringWithFormat:#"%# %#", self.firstName, self.lastName];
}
- (void)setFullName:(NSString *)fullName
{
//logic to split fullName into two strings
//self.firstName = etc
//self.lastName = etc.
}
In this example, there is no instance variable for fullName created.
This is according to Apple's Official Documentation
If, however, you don't override both the setter and getter, an instance variable is created.
As a sidenote, you can declare a property readonly, and then simply overriding the getter (without using the variable) will prevent an ivar being created. Likewise, you can declare a property writeonly and just override the setter.

About moving few methods to the superclass

I need to move the same method from 4 different classes to the superclass.
Such methods are exactly the same except for the type of a variable declared in them:
For example, in the method in the first class I have
FirstClass var = [[FirstClass alloc] init]
in the second class
SecondClass var = [[SecondClass alloc] init]
and so on.
What's the best way to implement this variation in the superclass ?
Should I use NSClassFromString in the superclass and get each string from each method in the subclasses?
thanks
I'm not 100% sure I get what you mean. So I could be answering the wrong question
If inside your class you need to use an object (I've called it worker below) to do your work, but the class of this object is not known til later, you can use dependency injection (DI).
MyClass.h
#interface MyClass : NSObject
#property (nonatomic, retain) id<WorkerInterface> worker;
#end
MyClass.m
#implementation MyClass
#synthesize worker = _worker;
- (void)myMethod;
{
[self.worker doSomething];
}
// You could also provide a default class to use if one is not passed in
//
// - (id<WorkerInterface)worker;
// {
// if (!_worker) {
// _worker = [[DefaultWorker alloc] init];
// }
// return _worker;
// }
#end
Now whenever I instantiate this class I can simply pass in the appropriate object to be used e.g:
MyWorkerClass *worker = [[MyWorkerClass alloc] init]; // <- Conforms to #protocol(WorkerInterface)
MyClass *instance = [[MyClass alloc] init];
instance.worker = worker;
[instance doSomething];
If all the different types of iVar's you intend on initializing in the subclasses are descended from a common class, then I'd store that class in the super, or else just store it as an id. Then, setup a property accessor in each of your subclasses the casts the iVar as you need it.
#interface superClass : NSObject{
id _superIvar;
}
#end
#implementation superClass : NSObject
....super's code....
#end
Now in the implementation of the subclass declare a property in a category, shown below (or in the interface, if you want it public)
#interface subClass (private)
#property (strong) ClassType *superIvar;
#end;
#implementation
- (void) setSuperIvar:(ClassType *)superIvar{
_superIvar = superIvar;
}
- (ClassType *) superIvar{
return (ClassType *) _superIvar;
}
- (void) someMethodThatUsesSuperIvar{
[self.superIvar doSomething];
}
#end
Alternatively, if you don't want to open your _superIvar to direct access, you can set a property on the superclass and access through the property on the subclass. But in this way you can easily access super's ivars cast to the appropriate type.