Tuesday, May 28, 2013

Selector on array - better way for fast enumeration

This entry will be short. It is continuation of last post about selectors. 
One of my students gave me a question how makeObjectsPerformSelector: works.

I will try to explain it fast. makeObjectsPerformSelector: is part od NSArray inmplementation. There is group of methods stacked under label 
"SendingMessagesToElements".

So how it works? We know that the array is collection of elements. Calling makeObjectsPerformSelector: on array will cause calling method on each element of array. It the object will respond to selector (if it will have implemented method) the method will run. 

There is also option to call selector with argument to each object in array makeObjectsPerformSelector:withObject:
So as I wrote in pervious blog entry about selectors - you can group arguments into one and pass them as collection by selector. 

So answer is: makeObjectsPerformSelector:  is a nice alternative for fast enumeration.

Few words about selector (SEL)


Introducing @selector



You are probably familiar to @selector or you should be, if you are interested in Objective-C programming. This blog entry is to describe it and make it clear how it works.


Selector is part of Cocoa framework and is widely used in many parts of system. (Ex. as part of Target-Action functionality or for Notification purposes). You can think of selector as about variable whitch holds method identificator. So why to use it? It allows us to define call to a method on object before we will knew what object it will be.

.

Selector have own type which is SEL. Lets have and example:


SEL aSelectorToAMethod = @selector(methodName);


@selector is compiler tag to interpret selector correctly. During a compilation time there is no validation on method if it exists, as selector from itself do not define on what type of object it will be used. Only its uniqueness is verified, but not even always as we can define selector on runtime (example 2):


SEL aSelectorToAMethod = NSSelectorFromString(@"methodName");

.

This way you can pass a method identifier as a variable.


How we use it? We can run it on any Objective-C Object via performSelector method. So simply as it can be - we have a method to run a method (from method variable - selector).


[object performSelector:aSelectorToAMethod ];

“performSelector”  can be called on any object, because it is defined in NSObject already - so we have this functionality out-of-the-box in every our class.


Flexibility od @selector call



“performSelector” have important overloads that can be very handy for development. 
You need to know that you can pass a value to a selector. As if one variable it is straight forward - we have overload performSelector:withObject: with two variables it can be done but with more there is a problem.
Solution is to pass all variables as array in first parameter.

SEL aSelectorToAMethod = @selector(methodName:);
NSArray *arr = [NSArray arrayWithObjects:@”one”, @“two”, nil];
[object performSelector:aSelectorToAMethod withObject:arr afterDelay:nil];

So we have array of arguments passed to a selector. There is one more thing - “afterDelay:. This is very strong advantage, that we can use to delay call for specified amount of time.
How it works? The "selected" method will run after declared time interval. Is it not beautifull?

There are more options - we can even attach a selector to thread we want or run it in a background. It is a perfect wy to initialize some communication with external service etc.

There is wide pallete of selector oriented methods described in NSObject definition you can find very useful.

Disadvantages of @selector


One of obvious things about selector is that we have to write more code for calling method and it become less readable and intuitive. As a result cod can become harder to maintain.

[object methodName];

[object performSelector:@selector(methodName)];


Second thing is that  until selector will be used in runtime we don’t know if it works. It can cause a runtime error instead of compilation error (with normal method call) and as a result it can be harder to debug and fix.

Responding to selector

There is also respondsToSelector: method. It verifies (YES/NO) if object have implemented given selector. It can help us processing different objects in different way or to run selector only on objects that have implemented given method.  

Thursday, May 23, 2013

Underscore before property name



_variableName vs self.variableName


I was asked today what is the difference between using underscore before property name and without underscore.


My student came with example:


“I have property with int type and I want to write setter. I can do it this way (Code Listing  1)  but when I will to it other way (Code Listing 2) the app always crashes.”



Code Listing 1- Example A



@property (nonatomic) int count;
- (void)setCount:(int)count
{
   _count = count;
}



Code Listing 2- Example B


@property (nonatomic) int count;
- (void)setCount:(int)count
{
   self.count = count;
}




So what is diffrence between them? Let’s think...

Notation is different... so is this working same in both cases? Is property with underscore prefix different than the other?

In most cases the result is same 

(not in Example 2)

, but the way how it work is completely different.
What is really happening in Example A and what in Example B?

In example A there is no direct assignment. Instead of assigning value the setter (method) is invoked. It work same as we would use setter as method or Key Value Coding (KVC). So the syntax of
self.count = count;
is equivalent of
[self setCount:count];
or
[self setValue:count forKey:@”count”]; //(KVC)

So … any ideas why Example B is crushing App on runtime?
“setCount” is setter for variable count. According to definition “self.count = “ is calling setter - “setCount” - so it starts calling itself recursively... endlessly.

And uderscore... syntax with uderscore is bypassing setter (or getter) method and allows accessing value directly. This is reason why we have to use it in our getter or setter. (Example A).

If this is still unlear try to implement Example 3 into your project. You can make a cusotm setter.  

Code Listing 3- Example C


@property (nonatomic) int count;
- (void)setCount:(int)count
{
   _count = count + 100;
}



Now try two types of calling.
self.count = 10;
and
_count = 10;

After first call count should have value of 110 and after second 10.

Hope you find this usefull.