iOS - Method With Success And Error Callbacks Without Initial Parameter - objective-c

I use success and error callback blocks a lot in method definitions with initial parameters like so:
+(void)doSomethingWithObject:(MyObject*)myObject successCallback:(void (^)(NSArray*))success errorCallback:(void (^)(NSString*))error;
where myObject is the initial parameter. However, I have come across a situation right now where I don't need any parameters. I'm trying to define my method like so:
+(void)getSomeData successCallback:(void (^)(NSArray*))success errorCallback:(void (^)(NSString*))error;
But now Xcode is giving me some syntax complaints. How can I define a method without any initial parameters but also having a success and error callback? Is this impossible or is there just something I don't understand about the correct syntax?

You should edit to
+(void)getSomeDataSuccessCallback:(void (^)(NSArray*))success errorCallback:(void (^)(NSString*))error;

Related

Calling OCMStub and OCMReject on the same method

I've been attempting to write some fail fast tests using OCMReject. However I've found that if OCMStub is used in conjunction with OCMReject, this test will pass
id _mockModel = OCMProtocolMock( #protocol( CTPrefModelProtocol));
//It doesn't seem to matter what order these two are in, the test behaves the same
OCMStub([_mockModel getPreferences]);
OCMReject([_mockModel getPreferences]);
[_mockModel getPreferences];
Even though it should clearly fail because I'm calling the function that I've set in the OCMReject method.
I realise I can just stub getPreferences whenever I'm expecting a result from it and remove it from this test, but largely that means if I've set a stub on getPreferences in my setUp method, any test that calls OCMReject([_mockModel getPreferences]) will just be ignored.
Why am I not able to use OCMStub and OCMReject together? Is it because OCMStub alters getPreferences somehow and as a result whenever I call this method, it actually calls some other method instead?
So apparently I can't read. Reading through the OCMock 3 Documentation, under the limitations heading 10.2
Setting up expect after stub on the same method does not work
id mock = OCMStrictClassMock([SomeClass class]);
OCMStub([mock someMethod]).andReturn(#"a string");
OCMExpect([mock someMethod]);
/* run code under test */
OCMVerifyAll(mock); // will complain that someMethod has not been called
The code above first sets up a stub for someMethod and afterwards an
expectation for the same method. Due to the way mock objects are
currently implemented any calls to someMethod are handled by the stub.
This means that even if the method is called the verify fails. It is
possible to avoid this problem by adding andReturn to the expect
statement. You can also set up a stub after the expect.
I suspect this same limitation exists for OCMReject as well. Hopefully this helps equally blind people like myself. A link to the documentation for the lazy.

iOS Passing function as parameter with two input

I am still studying for passing function as parameter.
Currently, I can do like this.
- (void)getLocation:(void (^)(CLLocation *location))didUpdateLocation andTimeOut:(void (^)(void))timeout andDidFailUpdate:(void (^)(void))didFailUpdate
What I want to know is that "didUpdateLocation" can have multiple parameter? (Instead of just CLLocation *location) ? Currently, I can't find about syntax for that.
Since this is a block you have defined yourself, it can have as many parameters as you want. Just add the parameter you want to the parameter list of the block like this:
- (void)getLocation:(void (^)(CLLocation *location, NSString *otherParameter))didUpdateLocation andTimeOut:(void (^)(void))timeout andDidFailUpdate:(void (^)(void))didFailUpdate

OCMock report error from stub

I want to test that my code properly handles a particular error returned from dataWithContentsOfFile. The problem is that the error isn't specifically returned from the method, it is an output parameter (passed in as NSError **.
It is easy enough for me to simply have the mock return nil from the stub, but I want to specifically test that the error it outputs is handled. How can I achieve that?
I think what you're looking for is described in section 2.5 (Returning values in pass-by-reference arguments) in the documentation: http://ocmock.org/reference/#stubing-methods

Enforcing to supply a completion block

I'm wondering about whether or not this is good practice:
I have a method that takes in parameters and a callback block, let's say something along the lines of:
-(void)loginWithUsername:(NSString *)username andPassword:(NSString *)password withCompletion:(LoginManagerCompletionBlock)completionHandler;
Now in this specific case, there is no use in calling this method without a completion handler, as it triggers a redundant call to a login web service (also, it does not change the state of anything - not client side nor server side). I would like to avoid these situations by actively enforcing the requirement of passing me a completion block in order to make this web service call. I sort of think of this as a "#required" method in an Objective C protocol. So my questions are:
Is requiring a completion block in order to perform an action good practice in Objective C?
(Edit: Answered) How do I enforce this requirement? Is there built-in language syntax that can help me out here?
Thanks
You can use the function attribute nonnull(params), where params is 1 or more comma-separated parameter numbers, to indicate that a parameter should not be null (nonnull without parentheses means all pointer parameters should not be null). For your example:
- (void) loginWithUsername:(NSString *)username
andPassword:(NSString *)password
withCompletion:(LoginManagerCompletionBlock)completionHandler
__attribute__((nonnull(3)));
However, while this is a compile time check and produces a warning it will only do so if null is passed directly. If the argument value is an expression which evaluates to null, e.g. a variable with a null value, then this will not be caught.
If a parameter being null is an error you can add a runtime check within the method itself using NSParameterAssert(parameter), where parameter is the name of one of the method's parameters, to check for this condition. This call is defined to print an error message and throw an exception if its argument evaluates to false, and null evaluates to false.
This is exactly what NSParameterAssert is for. Use it to check that parameters aren't nil.
NSParameterAssert( completionParameter );
Though, in this specific case, it's probably best to log the completion handler being nil and return. There is no point doing any additional work. You probably want the assertion during development to make it obvious that you have an issue that needs to be resolved.

Defining protocols without parameters

I am trying to define a protocol method without adding parameters but couldn't find the correct syntax.
Here is the definition (it has a syntax error)
- (void)cameraOverlayView:(CameraOverlayView *)cameraOverlay didTakePhoto;
I don't want to pass any values with the second parameter. My aim is only to signal that something happened to the delegate instance.
How should I write the definition?
Your the second part of the method is not formatted correctly:
- (void)cameraOverlayView:(CameraOverlayView *)cameraOverlay didTakePhoto;
Because of the space, it's expecting a parameter. Instead, work the didTakePhoto part into the method name, like:
- (void)cameraOverlayViewDidTakePhoto:(CameraOverlayView *)cameraOverlay;
- (void)cameraOverlayViewDidTakePhoto:(CameraOverlayView *)cameraOverlay;
basically in objective c you can't have method name parts dangling after parameters...
so:
illegal:
-(void)methodWith:(int)theInt forMyMom;
normal:
-(void)methodForMyMomWithInt:(int)theInt;
legal but strange
-(void)method:(int)theInt :(int)theOtherInt;
with the selector: #selector(method::)
This is an issue of Objective-C convention. You could rewrite it as:
- (void)cameraOverlayView:(CameraOverlayView *)cameraOverlayViewDidTakePhoto;