What (void(^)(NSString *)) as method parameter means in Objective-C? - objective-c

I have to use some private API of my employer and i've got method like this:
- (void)login:(NSString *)username password:(NSString *)password delegate:(void(^)(NSString *))delegate;
What (void(^)(NSString *))delegate means?
This is parameter but i don't know what must be here.

This is a block pointer. If you are unfamiliar with blocks, this basically lets you assign an annonymous function inline as a parameter. The signature here says that the block takes an NSString as a parameter, and returns nothing. You would use it like this:
- (void)login:(NSString *)username password:(NSString *)password delegate:(void(^)(NSString *))delegate;
[someReceiver login:yourUsername password:yourPassword delegate:^(NSString *aString)
{
// This is the block (annonymous function). Do something with the aString paramter
}];

It denotes a block - it's essentially a closure (lambda function, whatever you call it) - Apple's addition to the C language. In this case, it returns void and accepts an NSString object as its only argument.

Related

How to extract an argument of 'function' type from NSInvocation

I am writing a unit test for the function that receives a protocol as input argument.
This function that I am testing calls some method of that protocol inside.
I want to mock this protocol and that method.
To mock the protocol using OCMock I wrote the following:
id<MyProtocol> myProtocol = OCMProtocolMock(#protocol(MyProtocol));
Now to mock the function I am using OCMStub.
The interesting part is that the function doesn't return any value but rather gets the callback as input argument and invokes it.
Here is its signature:
- (void)myFunction:(void (^ _Nonnull)(NSDictionary<NSString *, NSString *> * _Nonnull))completion;
I am writing the following code to mock this function:
OCMStub([myProtocol myFunction:[OCMArg any]])._andDo(^(NSInvocation *invocation){
void (^ _Nonnull)(NSDictionary<NSString *, NSString *> * _Nonnull) completion;
[invocation getArgument:&completion atIndex:0];
// Here I will invoke the completion callback with some dictionary and invoke the invocation
});
However I am getting the following error: "Expected identifer or '('". The error points to the line that defines completion variable.
How can I define the function variable of signature void (^ _Nonnull)(NSDictionary<NSString *, NSString *> * _Nonnull)?
That ain't a function. It is a block!
Regardless, both functions and blocks can be treated as void * in declarations. You'll need to cast them to the appropriate type after.
But that's probably the easiest way to deal with it; extract from the invocation as a void*, cast to a block, call it.
Actually I was able to extract a first argument by doing the following:
OCMStub([myProtocol myFunction:[OCMArg any]])._andDo(^(NSInvocation *invocation){
void (^ completion)(NSDictionary<NSString *, NSString *> * _Nonnull);
[invocation getArgument:&completion atIndex:2];
// Do other stuff
});
I was just declaring a variable of 'block' type incorrectly.
And I have also realized that the first argument should be accessed by index = 2;

Obj-C: Difference between calling a method (with no input) on an object vs calling a method with input

I am an absolute beginner in objective-c and just read an overview of the language on cocoadevcentral.
The first section briefly discusses syntax for calling methods and gives two examples; one for calling a method on an object and the second is a method with input being called on an object,
[object method];
[object methodWithInput: input];
Can anyone explain the difference to me, possibly with a simple example?
There is no huge difference between the two and all depends on what you are doing.
Method 1
[object method];
There are two parts to this method.
object this is either an instance of a class or is a class itself all depends on the type of method you are calling whether it be an instance method or a class method. Each are declared differently.
A Class method is declared like + (void)myClassMethod; and would be called like [NSString myClassMethod];
An Instance method would be declared like - (void)myInstanceMethod; and would be called like [myStr myInstanceMethod]; (Where myStr is an instace of NSString)
method The second part is the actual method that you are calling this all that this will do when you call something like [myStr myInstanceMethod]; it will call the implementation of that method so it would call
- (void)myInstanceMethod
{
NSLog(#"We called our instance method");
}
Method 2
[object methodWithInput: input];
The only difference here is that we are passing in an argument. So here we have three parts the same first two from method 1 and the argument
input All this is, is the value that you are passing into the method to be used within it.
This type of method would be declared something like - (void)myInstanceMethodWithArgument:(NSString *)str;. Here are just saying that we have an argument of type NSString so when we call this like [str myInstanceMethod:#"Some Random String I want to pass in"]; it will run the following implementation code
- (void)myInstanceMethod:(NSString *)str
{
NSLog(#"My str value is : %#", str);
}
Method 3
[object methodWithInput1:input1 andInput2:input2];
Just throwing this in because you my get a little confused later when dealing with multiple arguments. This is exactly the same as method 2 except it has two arguments and not one. This would be declared like - (void)myInstanceMethodWithInput1:(NSString *)str1 andInput2:(NSString *)str2;. Does exactly the same is method 2 except it has multiple arguments that's it nothing to be scared of.
I would recommend that you have a read of the Apple Coding Guidelines for Cocoa. Best of look with learning as it's probably not the easiest language to learn.
Try substituting 'input' for 'argument'..
[object someMethod:(CGFloat )floatArgument];
The type should be there in the brackets, with a dereference operator (*) eg (NSObject *)theArgument if that argument is a pointer.
So basically some methods supply one or more arguments, and some do not, just as with C
When you call method without input data it means that method will work with already existing class's properties.
- (void)someMethod {
self.var_1 = self.var_2 + self.var_3; //or any other implementation
}
You will call this method like this
[self someMethod];
When you call method with some input data it means that this data will be used in method's implementation
- (void)someMethodWithInputData:(NSInteger)inputData {
self.var_1 = self.var_2 * inputData;
}
You will call it like this
[self someMethodWithInputData:10];
It's just the difference between saying "I wait" and "I eat an omelette". In some cases you can say what you mean with just a verb. In some cases a sentence needs an object in order to communicate its meaning.
The same thing applies in programming. Sonetimes you're going to need to specify more than just the action. But not always.

Problem declaring and calling internal metthods

How do I declare and use small helper functions inside my normal methods ?
In on of my objective-c methods I need a function to find an item within a string
-(void) Onlookjson:(id) sender{
NSString * res = [[sender gstring] copy];
persInfoBirth.text = getKeyValue(res, #"Birth");
}
I came up with a normal C type declaration for helper function getKeyvalue like this
NSString * getKeyvalue(NSString * s, NSString * key){
NSString *trm = [[s substringFromIndex:2] substringToIndex:[s length]-3];
NSArray *list = [trm componentsSeparatedByString:#";"];
//....
NSString res;
res = [list objectAtIndex:1];
//...
return res;
}
Example input string in s:
s=#"{ Birth = "1910"; Death = "1936"; }";
Anyway I get an exception "unrecognized selector sent to instance" for any of the two first lines in the helper function
How do I declare helper functions that are just to be used internally and how to call them safely ?
regards
Martin
Is this the real code? Do you get zero errors and warnings from the compiler? You must not ignore compiler warnings and you should turn on the Static Analyser in addition to the standard warnings.
There are many things wrong with the above code, most of which are nothing todo with declaring and calling methods. There is no way the above code could compile so maybe it pasted incorrectly or something..
Anyway.. declaring and using methods. Why are using a c function? Unless you have a good reason why not use Objective-c ? If you do have a good reason to use a C function the your definition should be:-
NSString *getKeyvalue( NSString *s, NSString *key ){
...
}
note the arguments. As NSString instances reside in the heap (not on the stack) you always want to pass pointers to them.
You then need to put the declaration in the header file:-
NSString *getKeyvalue( NSString *s, NSString *key )
EDIT:
In Objective-c there is no distinction between normal methods and helper methods, there is only one kind, and you have aleray written one
- (void)onLookJson:(id)sender { .. }
Taking it apart..
All methods begin with + or –, indicating Class method or Instance method. As you are familiar with C++ i guess you know what this means.
(void) is the return type. ie this method doesn't return a value. If it did it might look like (float) or (NSString *) or (id).
onLookJson: is the method name and the method takes 1 argument. Notice that the ':' is actually part of the name. This method is never is any circumstance just 'onLookJson'. An argument must always follow the :, so a method that doesn't take any arguments must not have one.
Ex
- (NSString *)fullName { .. }
This is an instance method, for example of a Person Class, you would call it like:-
NSString *theName = [aPerson fullName];
So
a method name that takes no
arguments is like 'speak'
a method
name that takes 1 argument is like
'speakTo:'
a method name that takes 2
arguments is like 'speakTo: language:'
a method name that takes 3
arguments is like 'speakTo: language: volume:'
etc.
All that is left is to put in the argument types and names.
Your function definition:
NSString *getKeyvalue( NSString *s, NSString *key ){
would become..
- (NSString *)getValue:(NSString *)s key:(NSString *)key { .. }
again, you need to declare it in the header or you will get a compiler warning.
- (NSString *)getValue:(NSString *)s key:(NSString *)key;

What does the "*" mean in Objective C?

Sometimes I encounter code that has *, sometimes **. Can anyone explain what they mean in Objective C? (I used to be a Java programmer, with experience in C/C++.)
The * denotes that you are using a pointer to a variable, and is most commonly used to store a reference to an Objective-C object, objects which can only live on the heap and not the stack.
Pointers are not a part of Objective-C exclusively, but rather a feature of C (and therefore its derived languages, of which Objective-C is one of them).
If you are questioning the difference between * and **, the first denotes a pointer, whereas the second denotes a pointer to a pointer; the advantage of the latter to the former is that when passing in an object using ** in a method parameter, the method can then change this parameter and the new value is accessible in the calling method.
Perhaps the most common use of ** in Cocoa is when using NSError objects. When a method is called that can return an NSError object on failure, the method signature would look something like this:
- (id)someMethodThatUsesObject:(id)object error:(NSError**)error;
What this means is that the calling function can pass in a pointer to an NSError object, but someMethodThatUsesObject: can change the value of error to another NSError object if it needs to, which can then be accessed by the calling method.
This is often used as a workaround for the fact that functions can only return one value.
A * in Objective-C means exactly the same as in C; and you'll usually see it (or not) in these situations:
// Method signatures:
// Here the asterisk (*) shows that you have a pointer to an NSString instance.
+ (NSString *)stringWithString:(NSString *)aString;
// Method signatures, part two:
// Here the double asterisk (**) signifies that you should pass in a pointer
// to an area of memory (NSError *) where outError can be written.
- (BOOL)writeToURL:(NSURL *) atomically:(BOOL) error:(NSError **)outError;
// Method signatures make for good examples :)
// Here the asterisk is hidden; id is a typedef for void *; and it signifies that
// a pointer to some object of an indeterminate class will be returned
- (id)init;
// And a forth example to round it all out: C strings!
// Here the asterisk signifies, you guessed it, a pointer! This time, it's a
// pointer to the first in a series of const char; terminated by a \0, also known
// as a C string. You probably won't need to work with this a lot.
- (const char *)UTF8String;
// For a bit of clarity, inside example two, the outError is used as follows:
// Here the asterisk is used to dereference outError so you can get at and write
// to the memory it points to. You'd pass it in with:
// NSError *anError;
// [aString writeToURL:myURL atomically:YES error:&anError];
- (BOOL)writeToURL:(NSURL *)url atomically:(BOOL)atom error:(NSError **)outError {
// do some writing, and if it went awry:
if (outError != NULL)
*outError = [NSError errorWithName:#"NSExampleErrorName"];
return NO;
}

Method Syntax in Objective-C

Can someone explain this method declaration syntax for me? In this function, the number of rows of a UIPickerView (slot machine UI on the iPhone) is being returned. From my understanding, the Method is called 'pickerView', and returns an NSInteger.
It passes in a pointer to the UIPickerview called 'pickerView' ... first, why is the method called the same name as the parameter?
Next there is NSInteger parameter called component that tells us which component we are counting the rows for. The logic to decide which is in the body of the method.
What is 'numberOfRowsInComponent? It seems to describe the value we are returning, but it is in the middle of the parameters.
- (NSInteger) pickerView:(UIPickerView *)pickerView
numberOfRowsInComponent:(NSInteger)component
{
if (component == kStateComponent)
return [self.states count];
return[self.zips count];
}
Objective-C methods are designed to be self documenting, and they borrow from the rich tradition of Smalltalk.
I'll try to explain what you have here, -(NSInteger) pickerView:(UIPickerView*)pickerView numberOfRowsInComponent:(NSInteger)component.
- (NSInteger)
This first portion indicates that this is an Objective C instance method that returns a NSInteger object. the - (dash) indicates that this is an instance method, where a + would indicate that this is a class method. The first value in parenthesis is the return type of the method.
pickerView:
This portion is a part of the message name. The full message name in this case is pickerView:numberOfRowsInComponent:. The Objective-C runtime takes this method information and sends it to the indicated receiver. In pure C, this would look like
NSInteger pickerView(UIPickerView* pickerView, NSInteger component). However, since this is Objective-C, additional information is packed into the message name.
(UIPickerView*)pickerView
This portion is part of the input. The input here is of type UIPickerView* and has a local variable name of pickerView.
numberOfRowsInComponent:
This portion is the second part of the message name. As you can see here, message names are split up to help indicate what information you are passing to the receiver. Thus, if I were to message an object myObject with the variables foo and bar, I would type:
[myObject pickerView:foo numberOfRowsInComponent:bar];
as opposed to C++ style:
myObject.pickerView(foo, bar);.
(NSInteger)component
This is the last portion of the input. the input here is of type NSInteger and has a local variable name of component.
In Objective-C, the name of a method is composed of all of the portions of the declaration that are not arguments and types. This method's name would therefore be:
pickerView:numberOfRowsInComponent:
The method would be equivalent to a C-style function that looked as follows:
edit: (with thanks to Jarret Hardie):
NSInteger pickerViewNumberOfRowsInComponent(UIPickerView * pickerView, NSInteger component)
Adding to the previous answers, I'd just like to say that Objective-C methods (or messages if you prefer) have external and internal parameter names.
So in this case:
- (NSInteger) pickerView:(UIPickerView *)pickerView
numberOfRowsInComponent:(NSInteger)component
numberOfRowsInComponent is the external name, the one that you would use when calling this method from the outside.
And component is the internal name of the parameter, the one you use to refer to the parameter from inside of the method.
Hope that clears it up a bit.
It seems to me that Objective-C method signatures are more like sentences. Each parameter deserves a part in method's name. For instance, in C we could have a method (setPersonData) for setting some information about person:
void setPersonData( char* name, int age, float height ) {
and in Objective-C the method would be more descriptive (setPersonName:andAge:andHeight:), like
- (void) setPersonName: (char *)name andAge:(int)age andHeight:(float)height {