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

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.

Related

Is it possible to pass a selector or a method signature as a parameter in Objective-C?

As my title states, I'm wondering if I can pass a method signature or an #selector as a parameter? I'm asking because I'm creating a framework and I want to be able to pass instances of a certain class within it a method name.
You can pass the selector itself of use the name of the method as a string:
- (void)myMethod:(SEL)selector
{
[aClass performSelector:selector];
}
or
NSString *myMethodName = NSStringFromSelector(#selector(myMethod));
NSLog(#"The name of the method is: %#", myMethodName);
Actually, you cannot not pass a selector to a method.
In Objective-C, every method gets two implicit arguments, passed as normal parameters: The instance pointer self and the target selector _cmd. They are present in each and every method. The _cmd parameter is of type SEL. It is used by the runtime to look up the method implementation (this is the core of objc's dynamism).
You can, of course, add additional parameter of SEL type.

Polymorphic methods in Objective C

In Java you can put in multiple constructors to a class that are called depending on the types and/or number of parameters that are used when an instance is constructed.
I assume that there is the equivalent in Objective C.
Can I have a polymorphic method?
I would like to build a method that acts slightly differently according to whether a string is passed or a double?
Does that sound bonkers or is it easy?
You're thinking of overloaded methods. Due to the way dynamic dispatch is implemented in Objective-C, it isn't currently possible to pass two unrelated types as arguments to the same (or same-named) method and have it understand.
In Objective-C, there are two related but distinct approaches to handling multiple kinds of input. Let's use your example of a string or a double as possible inputs. In Java, you might have:
void applyWidget(String s);
void applyWidget(double d);
And that's great, but not Objective-C. In Objective-C, you instead would use two different method names:
- (void)applyWidgetWithName: (NSString *)name;
- (void)applyWidgetWithValue: (double)value;
The same logic is in each method as in the Java version, but the distinct names let the compiler treat them as distinct methods (which they are, even in Java.) The code also becomes self-documenting: by reading it, you get an idea of what's happening even without comments. Alternatively, if you simply must have one method name, you change the parameter type to id and accept any object:
- (void)applyWidget: (id)widget;
Then pass either an NSString or an NSNumber wrapping your double. Then, in the implementation of the method, use Objective-C's introspection methods to determine how to proceed:
if ([widget isKindOfClass: [NSString class]]) {
...
} else if ([widget isKindOfClass: [NSNumber class]]) {
double d = [widget doubleValue];
...
}
This approach essentially tells callers "send anything--I'll handle it appropriately." It can be difficult to determine the behaviour of such a method without extensive documentation.
Absolutely easy:
- (id)initWithSomeObject:(id)object
{
if ([object isKindOfClass:[ClassOne class]) {
// do something
} else if ([object isKindOfClass:[ClassTwo class]) {
// do something else
} // etc.
return self;
}
yes, but objc does not have proper overloading.
so you see things like initWithDouble:, initWithBool: and so on. that's part of the reason it's a bit 'wordy' for some people's taste.
to use your example:
#interface MONClass
- (id)initWithString:(NSString *)pString;
- (id)initWithDouble:(double)pDouble;
...
but the following is an error:
- (id)initWith:(NSString *)pString;
- (id)initWith:(double)pDouble;
because the selector is the same -- the parameter/return types are omitted from the selector.
Basically Objective C does't have proper method overloading. It will support overriding only.
Suppose if you write functions like in same class,
(void) showMethod;
(void) showMethod:(int) aNumber;
This will support in Objective C.
Suppose if you write functions like,
(void) showMethod:(NSString*) aString;
(void) showMethod:(int) aNumber;
In this way the compiler gives Error because there conflicting parameter types in implementation of showMethod.

OCMock: Setup syntax for checking parameters

I am trying to setup a OCMock to be verified.
I have a protocol, TaskManagerDelegate, that contains the following method,
- (void) addTasks:(NSArray * ) tasksToAdd;
After setting up my mock object like this,
id mockTaskManagerDelegate = [OCMockObject mockForProtocol:#protocol(TaskManagerDelegate)];
I assign the object to the class under test like this,
taskManager.Whatever = mockTaskManagerDelegate;
I call a method on my taskManager and then want to verify the addTasks method was called on the TaskManagerDelegate and that the array that was passed to it contains exactly one object.
So far I have used the OCMArg class to detect if a parameter is being passed in, but I am struggling to understand how to check that specific types are sent are sent to the mocks, or that the objects sent to mock pass certain tests (have a .count of exactly one for a example). I come from a C# background and would normally use Moq, where you can use lamda functions to do specific checks on parameters being sent to the mocked object.
Does any one know how to do this with OCMock or if for some conceptual reason it is not possible to do?
Thanks,
The features description on the OCMock site has this: ;-)
"If Objective-C blocks are available it is possible to check the argument with a block as follows:
[[mock expect] someMethod:[OCMArg checkWithBlock:^(id value) { /* return YES if value is ok */ }]];
Would that work for you? Are you in an environment where blocks aren't available?
I had the same requirement and so created a category for it:
#implementation OCMArg (IsOfClass)
+ (id)isOfClass:(Class)aClass
{
BOOL (^classCheck)(id) = ^BOOL(id obj) {
return [obj isKindOfClass:aClass];
};
return [[OCMBlockConstraint alloc] initWithConstraintBlock:classCheck];
}
#end

Objective-c symbols ** & +-

Just when I think I'm getting comfortable with Objective-c the mentioned symbols totally throw me down a rabbit hole...
** a double pointer??
& what sort of things can I do with &reference, is a #property? a full on object? weird pointer razzledazzle?
± I see both a + or a - before method declarations; I've seen Java annotate some datatype declarations by manually typing the + and the magic of compiling in Eclipse would change them to a -
I'm likely asking repetitious questions and/or way outta the ballpark on my guesses; thanks for answers/edits.
You're getting into the C portion that objective-c is built on top of.
** is a pointer to a pointer. Since functions in C take arguments by value, it means you can't change the value of the argument in that function. But, by providing a level of indirection and passing a pointer to the pointer, you can change the value.
& means it's a reference. If an argument takes a ** and you have a * variable, pass a reference to it.
Foo *foo;
[self changeFoo: &foo];
- (BOOL)changeFoo: (Foo **)foo
{
// dereference the double pointer and assign a val = alloc init returns a *
*foo = [[Foo alloc] init];
return YES;
}
A common usage in objective-c / cocoa is NSError. It's essentially an out argument.
NSError *err;
BOOL success = [self doSomething:#"Foo" error:&err];
- (BOOL)doSomething:(NSString*)withData error:(NSError**)error
{
}
As you might know, a pointer points to the address of an object and is the way you reference an object. A double pointer is sometimes used in Objective-C, mainly for returning NSErrors, where you want to get back the address, i.e. a pointer, to an error object (NSError) if an error occurred, thus you pass in a pointer assigned to null and the caller can change that pointer so that it points to the address of another pointer which in turn points to an NSError object.
The ampersand (&) is mostly used by the lower level C APIs, e.g. Core Graphics. They are used to reference things, like the current context. As long as most of your code uses square brackets around its method calls you won't see these very often.
Using a + or a - before a method declarations is used to differentiate between class (+) and instance (-) methods. A class methods is called on the class itself (such as alloc), while a instance method is called on an instance of that object (such as init).
- and + before a method declaration designate an instance method and a static class method. To use an instance method you have to create an object of your class before you can call its method, a static method can be called directly from a class type

What does "-(void)" mean in this function declaration? `-(void)awakeFromNib`

How come whenever I have to use awakeFromNib protocol I have to put it in this format?
-(void)awakeFromNib
What is the need for -(void)?
The -(void) is used in the declaration of the method. Presumably, you are defining it for someone else to call, rather than calling it yourself.
The - sign indicates that the method is an instance method, as opposed to a class method. It requires an object to call it, and instance variables of the object are available to it inside its definition.
The (void) indicates the return type. This method doesn't return anything, so its result can't be assigned to anything.
think of it this way
say you have a Class you created that is called "Math"
and this class has a method called "calculate". It's type as
-(int)calculate {
2+2;
return 2+2;
}
When you alloc the class and initialize the object and perform the "calculate method on that object, it's going to do the calculation 2+2 and it will return the result, 4.
If you tried
-(void)calculate {
2+2;
}
it wouldn't do anything, it would just have that 2+2 information stored in the method but the calculation would never occur.
Because the method does not return anything, and giving a void return type is how you declare that in C and Objective-C.
(void) marks the return type - in this case, void means it's returning nothing.
If it was instead -(int)awakeFromNib, you'd be expected to return an integer.
The meaning of the return value (if any) should be explained in the documentation.