Using makeObjectsPerformSelector with an object - ios

I have an NSArray of objects and I want to perform the selector pinInBackgroundWithName:(NSString *) on each object. I know that I can use [arr makeObjectsPerformSelector:#selector(selector_name) withObject:obj]; but how does passing in the string to the withObject: argument work? For example, what if the selector I wanted to perform on the objects in the array had multiple arguments? Then would the withObject: argument we an NSArray of objects?

From the docs:
A selector that identifies the message to send to the objects in the array. The method must take a single argument of type id
So you can't use this for a selector with multiple arguments.
If you want to send a message with multiple arguments to each object in the array, you could roll your own version that takes an array, and then fills out an NSInvocation object that it then invokes on each object, or, if you wanted to be really fancy, use higher order messaging.

I would suggest ditching the selector-based calls and using enumerateObjectsUsingBlock or one of it's variants.
Blocks inherit their enclosing scope, so you can invoke a block of code that uses as many variables as you want from the scope of the call.

Related

How to call a method from an object in an array?

I'm new to Objective-c and I think this should be really easy but somehow I can't figure it out.
I need to call a method from an object which is stored in an NSArray.
The Java code would be: myArray[0].getMyValue();
So I read on the internet that in Objective-c it should look like this: [[myArray objectAtIndex: 0] getMyValue]. Unfortunately this didn't work.
I found other solutions on the internet but none of them worked.
So I hope you guys could help me out?
Update
I'm getting these two error messages:
No known instance method for selector 'getMyValue'
Sending 'id' to parameter of incompatible type 'CGFloat' (aka 'double')
This doesn't work because Objective-C doesn't know what is the type of the object in the array.
Luckily, Apple has added lightweight generics in Xcode 7, which allow you to create typed arrays. This will of course work only if you intend to have one type of object in the array. The syntax looks like this:
NSArray<NSString *> *stringArray;
If you plan to have objects with different types in the array, then you need to cast the object to your type, to be able to call your method. That would look like this:
[((YourObject *)[myArray objectAtIndex: 0]) getMyValue];
And as #Michael pointed out in the comment, another and nicer way to do this would be:
[((YourObject *)myArray[0]) getMyValue];
Objects are stored with id type in NSArray, so you can cast this object to the object type you want. For instance :
NSNumber *myNumber = (NSNumber *)[NSArray objectAtIndex:0];
[myNumber myMethod];

Difference between selector and SEL and method call [ ]? [duplicate]

What the difference between a method, a selector and a message in Objective-C?
This is a great question.
Selector - a Selector is the name of a method. You're very familiar with these selectors: alloc, init, release, dictionaryWithObjectsAndKeys:, setObject:forKey:, etc. Note that the colon is part of the selector; it's how we identify that this method requires parameters. Also (though it's extremely rare), you can have selectors like this: doFoo:::. This is a method that takes three parameters, and you'd invoke it like [someObject doFoo:arg1 :arg2 :arg3]. There's no requirement that there be letters before each part of the selector components. As I said, this is extremely rare, and you will not find it used in the Cocoa frameworks. You can work with selectors directly in Cocoa. They have the type SEL: SEL aSelector = #selector(doSomething:) or SEL aSelector = NSSelectorFromString(#"doSomething:");
Message - a message is a selector and the arguments you are sending with it. If I say [dictionary setObject:obj forKey:key], then the "message" is the selector setObject:forKey: plus the arguments obj and key. Messages can be encapsulated in an NSInvocation object for later invocation. Messages are sent to a receiver. (ie, the object that "receives" the message).
Method - a method is a combination of a selector and an implementation (and accompanying metadata). The "implementation" is the actual block of code; it's a function pointer (an IMP). An actual method can be retrieved internally using a Method struct (retrievable from the runtime).
Some other related things that you didn't ask for:
Method Signature - a method signature represents the data types returned by and accepted by a method. They can be represented at runtime via an NSMethodSignature and (in some cases) a raw char*.
Implementation - the actual executable code of a method. Its type at runtime is an IMP, and it's really just a function pointer. iOS 4.3 includes a new ability to turn a block into an IMP. This is really cool.
One of the fun things to realize is that the name of a method (the selector) is distinct from the implementation of the method (the IMP). This means that you can swap them around, if you're feeling daring. You can also add and remove methods at runtime, because all you're doing is editing an entry in a hash table: the key is the selector, and the value is the IMP of the method. This allows you to do some really crazy and trippy stuff. It's not for the faint of heart. :)
A method is the implementation which is run when an object or class is asked to perform some action. It is in the scope of its containing class and is therefore different when referenced through some other class. A selector is an identifier which represents the name of a method. It is not related to any specific class or method, and can be used to describe a method of any class, whether it is a class or instance method.
Simply, a selector is like a key in a dictionary. It can tell you what method someone is talking about, but only if you also have the dictionary itself (the class or object). The method is what you get when you ask for the value from the dictionary using the selector as a key.
This site has a good overview of all the terminology in question: http://www.otierney.net/objective-c.html
Check out the link, but I'll give a quick summary:
A method is essentially like a method of function that you are used to in your favourite programming language.
A message (from the article) "A message can be dynamically forwarded to another object. Calling a message on an object in Objective-C doesn't mean that the object implements that message, just that it knows how to respond to it somehow via directly implementing it or forwarding the message to an object that does know how to."
Selectors can mean two things. It can refer to the name of a method, or "refers to the unique identifier that replaces the name when the source code is compiled. Compiled selectors are of type SEL." (from: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocSelectors.html)

Accessing obj as property vs method param (style preferences)

When it comes to accessing objects from different methods in the same class, from what I understand, these are two ways to do it. Given that I DO want to hold a property pointer to this object, which is the better way to go about this? I've been thinking about this for a while, and wondered if there is a preference consensus.
#1:
NSArray *array = ... // Get array from somewhere
self.myArray = array;
[self doSomethingToMyArray];
This method takes no parameter and accesses the array via its own property via self
- (void)doSomethingToMyArray
{
// Do stuff with/to the array via self.myArray
[self.myArray ...];
}
Vs #2:
NSArray *array = ... // Get array from somewhere
self.myArray = array;
[self doSomething:array];
This method takes an array and accesses the array via its own method parameter
- (void)doSomething:(NSArray *)array
{
// Do stuff with/to the array via method parameter "array"
[array ...];
}
I think it's primarily going to depend on what doSomethingToMyArray does and who calls it.
Fairly obvious comments:
if you want to do that to more than one array, you need to take an argument;
if what you're doing is actually logically more to do with the array than with your class (e.g. you've implemented randomisation of the order of the array) then it'd be better as a category on NSArray rather than being anywhere in that class at all;
if there's any possibility of subclasses wanting to redefine the manner in which the array is obtained then you'll want to invoke the getter somewhere;
similar concerns apply if a subclass or an external actor should be able to intercede anywhere else in the process.
Beyond those concerns there are a bunch of us that just prefer this stuff to be functional anyway — noting that you're doing something to the array, not with the array, in which case you'd tend more towards self.myArray = [self processedFormOf:array] (or self.myArray = [array arrayByDoingSomething]; if the category tip makes sense).
So, ummm, I don't think there's a clear-cut answer.
That depends on what you want to do, just by reading it:
doSomething:array
I would assume the above method takes ANY array and performs an action, whereas:
doSomethingToMyArray
with this method you are describing the intention of doing something to your instance's array. Inside this method (given that you followed Apple good coding practices and you synthesized your property to _myArray) , you could either go with:
[self.myArray message]
or preferably
[_myArray message]
Your second option is sort of silly. If you're storing a pointer in an instance, then it's so that you can use it later (within that instance) without needing to pass it around whenever you call a method.
This is also dependent on whether you're using ARC or not (use ARC if this is a new project). In a non-ARC project, self.myArray = foo; will do a very different thing than myArray = foo; (the self. syntax calls a property, which in many cases will correctly retain the thing you've assigned). In an ARC project, they'll generally have the same behavior, and there's less room for error.
Personally, in my ARC projects, I do not use the self. syntax from within a class, since it's just extra typing for the same effect. This ties in nicely with the new usage of #property, where you're no longer required to write a #synthesize block, and Objective-C will automatically generate an ivar for you, with the name of your property prefixed by an underscore, i.e. _myPropertyName. That makes it very clear visually when you're accessing code from outside the class (crossing the encapsulation boundary), where things will look like foo.bar = baz; versus inside the class, where it's just _bar = baz;.
IMHO, clearly, a function call would incur an extra overhead.
you would have to allocate an object pointer (though minimal) over the stack (extra memory)
Have to pass it (extra processing)
Property is actually a small function call unless you have made customizations to the getter. I also assume that compiler may have its own optimizations put in place for such accessors so that you can access them with minimal overhead, though I do not have any source to cite this.

Can blocks/methods be interchangeable?

I'm coming from C#/Java/JS to objectiveC and I'm only a couple of days in, so go easy on me.
...so I have a method that takes a block as a parameter:
-(void)subToPub: (NSString*)publisherName
channelId: (NSString*)channelId
callback: (void(^)(NSDictionary*))cb
which I would usually use as follows:
[myObj subToPub:#"someId"
channelId:#"someOtherId"
callback:[(^(NSDictionary* msg){
NSLog(#"cb2: %#",msg);
}) copy]
];
Now, say I have another method with a compatible signature, for instance:
-(void)subscribeHandler:(NSDictionary*)msg{
NSLog(#"cb2: %#",msg);
}
is it possible to pass this in as the callback to the subToPub method above, or do I need to wrap this method call in a block?
Logically you need three pieces of information to make a call to the selector described. The object instance, the name of the selector and the dictionary parameter.
The block you pass accepts only one piece of information when called — the dictionary. Everything else needs to be captured within the block.
So, logically, the selector can't be a straight substitution for the block. Besides anything else, where does knowledge of which instance to call it on come from?
The only way to produce a record of 'this method on this specific object' and compact that into a single object is to put it into a block.
If you have a defined format of method you want to call (in this case, one with a single argument) and know the object implicitly then you might consider passing in a selector (SEL). So e.g.
[myObj subToPub:#"someId"
channelId:#"someOtherId"
callback:#selector(subscribeHandler:)
];
... and subsequently, assuming you know the object you want to talk to as obj and have stored the SEL you received as selector:
[obj performSelector:selector withObject:msg];
If you want to pass more than one argument then you need to start fooling about with NSInvocations; it's quite ugly and you'll soon start to appreciate why closures were added to the language.
you can do this
[myObj subToPub:#"someId"
channelId:#"someOtherId"
callback:[(^(NSDictionary* msg){
[object subscribeHandler:msg];
}) copy]
];
You need to wrap it. Clearly you know how to do that, e.g. ^(void)subscribeHandler:#[#"key": #"value"].

Possible to send multiple data to selector with CCCallFuncND without creating a new class?

In cocos2d the action CCCallFunND allows you to call a selector and send it data, but the selector I want to call takes both an NSString and a float. Can you send more than one datum and if so, what is the syntax.
I know I can make a new object class that contains both types and pass that, but that seems kludgy to me. The whole idea of the method I'm calling is to cut down the overhead, and doing it with a new class seems like it defeats the purpose.
Here's the syntax...
CCCallFuncND actionWithTarget:(id) selector:(SEL) data:(void *)
I think the best solution will be to create a structure with your string and float. But you can also create a NSArray and put your NSString and NSNumber to it. Then just pass the array.

Resources