OCMock: Setup syntax for checking parameters - objective-c

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

Related

Store Objective-C classes in array and use them

Say I have two classes, BulbDevice and FanDevice, both are subclasses of Device and has a method signature like this:
+ (BOOL)isMyId:(NSInteger)someId;
If I wanted to create a class I could test it out:
if ([BulbDevice isMyId:someId]) {
Device *dev = [BulbDevice alloc] initWithId:someId];
}
But what I really want is to create a factory method inside a factory class, with minimum fuss when new device are added:
+ (Device)createDevice:(NSInteger)someId {
// say I have an array registered
NSArray *arr = #[[BulbDevice class], [FanDevice class]];
// Loop through it.
Device *device;
for (Class *c in arr) {
// The idea is kind of like this but I'm not sure how to make it work
if ([c isMyId]) {
device = [[c alloc] init];
}
}
}
The idea is that I only need to update arr in the factory method. So I think it is good to have something like this. But I am not sure how to make it work.
EDIT:
I took out the asterisk, but it won't work:
for (Class c in arr) {
// Now I want to access the isMyId which is a static method,
// but I how do I cast to that class? I mean not an object of the class, but to that class itself.
if ([(Device)c isMyId:]) {
}
}
But I still need a way to access that class method. Error says Used type 'Device' where arithmetic or pointer type is required, and even if it works, I want to access class method, not sending message to an object.
Or shall I store NSString in the array instead? But it is hard to find way to access the class method as well.
If I understand correctly what you are trying to achieve, then your approach seems to be correct.
There is only one thing that needs to be fixed:
for (Class c in arr)
c variable is not a pointer - the asterisk should be removed. Your code works.
The Class type is not an NSObject type, and although it is a bit special it is object-like or object-equivalent, so you are able to send it messages and store it in collections like you're doing.
You don't use the asterisk as #MaxPevsner says, because Class isn't used as a normal pointer-to-object. Think of Class as a special type like id which also doesn't get the * when you use it to reference an object.

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.

Objective-C iOS callback function between classes

I'm new to iPhone application development, but I seem to have somewhat managed so far (learning as I go).. however, I've run in to an issue I can't figure out. Here's the scenario:
I have an extension class called CoreAPI which I have my network functions inside. I have a function called "Login" inside CoreAPI which makes a request to a server, gets the 0 or 1 response and returns true or false. I had this working perfectly with Synchronous requests, but now I need to make everything asynchronous.
So, below is what I'm trying to do.. this is not working with the error along the lines of "Object of type ID has no method loginCallback"
loginViewController.m
- (void) login {
CoreAPI APIObject = [[CoreAPI alloc] init];
[APIObject login:self];
}
- (void) loginCallback {
NSLog(#"It called back.");
}
CoreAPI.m
- (void)login:(id)sender {
[sender loginCallback];
}
Thanks, and please let me know if I have missed any details needed to help me.
I'm seeing a couple problems. First, I'm guessing you don't provide visibility of the loginCallback function to CoreAPI.m. You should be able to send any message to an id type, so long as it's defined for a known type.
However, I'd recommend using a completion block in this case. Here's what that could look like:
(in CoreAPI.h)
- (void)login:(void (^)(void))completed;
(in CoreAPI.m)
- (void)login:(void (^)(void))completed {
// Login code
if (completed) completed();
}
Calling it would look like:
CoreAPI APIObject = [[CoreAPI alloc] init];
[APIObject login:^{
NSLog(#"It called back.");
}];
They have really goofy syntax, but blocks are really nice for this sort of thing. Hope this helped! Let me know if I didn't explain something clearly.
this should do the trick for you:
first, import loginViewController header inside CoreApi.m
#import "loginViewController.h"
Then, change login method to this:
- (void)login:(id)sender {
[(loginViewController*)sender loginCallback];
}
Or this:
- (void)login:(loginViewController*)sender {
[sender loginCallback];
}
Explanation: notice that your login method is receiving by parameter one object of type id . In objective C, id type means a reference to any Objective-C of unknow class. So, inside your login method, the compiler doesn't know that the sender is a instance of your loginViewController class, so it won't recognize loginViewController's methods.
To informations about this, please read: Objective-C: difference between id and void *
Notice that I only focused in remove your actual error. You should have to do more things in order to accomplish your code to run asynchronous.
In order to perform a better callback, please look for delegates or blocks (like in oltman's answer).
To run things in background, look for CDG : http://developer.apple.com/library/ios/#DOCUMENTATION/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html

How to convert a delegate-based callback system into block-based?

I have a class, which has a delegate based system for sending different type of requests. it uses delegate to tell the object when the request is complete and also if it was a success o an error.
Now, I also have to check what type of request was it in response to take appropriate action.
I have wrapper class that should give me a block based interface for the same.
I pass a completion-block and an error-block to a request method which should internally use this delegate based class.
And when the response comes, should automatically call the appropriate handler for that request type and depending on success and error as well.
I saw a similar question on SO, but it was a little unclear to me, So please give a general idea of how to go about it instead of marking it as duplicate straight away.
Here is one way to do it. Use this RAExpendable class to dynamically build a delegate with a block based implementation.
Let's say your delegate is:
#protocol XDelegate
-(void) foo:(id)response;
#end
Add RAExpendable.h, RAExpendable.m from https://github.com/evadne/RAExpendable to your project. Dynamically add the delegate method:
RAExpendable *expendable = [RAExpendable new];
[expendable addMethodForSelector:#selector(foo:) types:"v#:#" block:^(id x, SEL sel, id response){
NSLog(#"response is %#", response);
}];
And set the expendable class as your delegate:
someObject.delegate = expendable;
Now, if you do this:
[expendable performSelector:#selector(foo:) withObject:#"OK"];
You get the string response is OK. Replace NSLog with whatever success/failure implementation you see fit. From now on, when you call foo:, the block executes instead.
If you want to modify this for your use case, note that the parameters for this example were v#:#, which according to the Type Encoding guide of the runtime means: void return, self, SEL, object. self and SEL are the two hidden parameters present on every Objective-C methods, the third parameter is the first non hidden parameter of the method. The signature of the block has to match the signature of the method.
With REKit, you can make a delegate dynamically like below:
id dynamicDelegate;
dynamicDelegate = [[NSObject alloc] init];
[dynamicDelegate respondsToSelector:#selector(foo:) withKey:nil usingBlock:^(id receiver, id response) {
NSLog(#"response is %#", response);
}];
someObject.delegate = dynamicDelegate;

Explanation of Cocoa #selector usage

I'm new to Cocoa/Cocoa Touch, and working through a development book. I've come across situations where the #selector() operator is used. I'm a bit lost on how and when the #selector() operator should be used. Can someone provide a short and sweet explanation and example of why it's used and what benefit it gives the developer?
By the way, here is sample code taken from Apple's iPhone development site that uses #selector()
if ([elementName isEqualToString:#"entry"])
{
parsedEarthquakesCounter++;
// An entry in the RSS feed represents an earthquake, so create an instance of it.
self.currentEarthquakeObject = [[Earthquake alloc] init];
// Add the new Earthquake object to the application's array of earthquakes.
[(id)[[UIApplication sharedApplication] delegate]
performSelectorOnMainThread:#selector(addToEarthquakeList:)
withObject:self.currentEarthquakeObject waitUntilDone:YES];
return;
}
The selector operator provides a way to refer to a method provided by an object, somewhat similar to a function pointer in C. It is useful because it allows you to decouple the process of calling methods on an object. For example one piece of code could provide a method, and another piece of code could apply that method to a given set of objects.
Examples:
Test to see if an object implements a certain method:
[object respondsToSelector:#selector(methodName)]
Store a method to later call on an object;
SEL method = #selector(methodName);
[object performSelector:method];
Call a method on a different thread (useful for GUI work).
[object performSelectorOnMainThread:#selector(methodName)]
In addition to what's been said, you can also wrap up the #selector in an NSInvocation for later use. You can set the arguments to the NSInvocation a long time after it's created, and activate it when you need the message to be fired. This gives you a lot of power.
For an introduction to the concept, Scott Stevenson has a great post entitled "Dynamic Objective-C with NSInvocation".
#selector() is used each time you need to pass the name of a method as an argument to another method, a function or as a variable value. Passing directly the name doesn't work in objective-C.
One practical example is validateMenuItem method where menu items are identified with their target actions.
Simplified example:
- (BOOL)validateMenuItem:(NSMenuItem *)item {
if ([item action] == #selector(selectFiles:) && otherCondition) {
return YES;
} else {
return NO;
}
}
One reference to look at:
http://en.wikipedia.org/wiki/Multiple_dispatch
You can use a selector to invoke a method on an object—this provides the basis for the implementation of the target-action design pattern in Cocoa.
[myObject performSelector:#selector(runMYmethod:) withObject:parameters];
is equivalent to:
[myObject runMYmethod:parameters];