I am trying to use the completion handler on invoke to perform certain actions once the hub has return a result. Im using the following line currently:
myHub invoke:#"stpm" withArgs:messageParam completionHandler:^(SRHubResult *hubResult) {
NSLog(#"Complete");
}
But the block is never called. The invoke still works fine but the block never gets used. Any suggestions as to why?
I can only spot 1.5 issues with your snippet, completionHandler returns either NSDictionary, NSArray, NSNumber, or NSString. Also, is messageParam array?
I have found the issue. In SRHubProxy.m when the method send is called from SRHubProxy.m in invoke, the line:
[_connection send:hubData];
is wrong. The block never gets passed whether you have declared one or not. I changed it to:
[_connection send:hubData completionHandler:block];
which now passes the block correctly and it seems to work.
Related
I am bridging an objective-c library to React. In order to return the data I need, I have to use a callback. The only problem is, the native method that kicks off the process that generates the data (which is the method that I call from my React js file), is NOT the method that returns the data. In fact, there are quite a few methods between the one that I call, and the final result.
So I have a few options. Either completely rewrite the entire objective-c program (f*ck that), pass the callback function as an argument to every single method and ultimately to the final method where it will be used (this 'works' but is ugly), or a third option which this post is about.
I am new to objective-c (very new) so go easy on me.
Instead of passing the callback function around to every single method, I want to try and make it 'global'. My attempt at doing this looks like
#property(nonatomic,copy)RCTResponseSenderBlock globalCallback;
and the method where it is 'initialized' (which is also the method I call from js)
RCT_EXPORT_METHOD(startScan:(RCTResponseSenderBlock)callback) {
self.globalCallback = callback;
...
}
Now just to test that this works, I added a line of code immediately below the line where I 'initialized' my globalCallback:
RCT_EXPORT_METHOD(startScan:(RCTResponseSenderBlock)callback) {
self.globalCallback = callback;
self.globalCallback(#[[NSNull null], #"Test string"]);
...
}
And it works (as far as I can tell). The callback returns "Test String" to React, and I am able to see it. So I went over to the method where I actually want to return information from and added the same line of code to it (obviously removing the one from the above example):
-(void)theMethodIWantToReturnFrom {
self.globalCallback(#[[NSNull null], #"Test string"]);
...
}
However, this time it does not work. I get EXC_BAD_ACCESS. From what I understand, this may mean that my globalCallback has been deallocated. But whatever it means, I have not been able to figure out a solution yet. Any ideas / explainations regarding this error?
How do I verify a method is never called with OCMock 3?
I was thinking something like this:
XCTAssertThrows(OCMVerify([_restDataSource getSomeStuff:[OCMArg any]]));
But it seems like OCMVerify doesn't throw for a fail.
Please see first point under http://ocmock.org/reference/#advanced-topics
Note that reject at this point in time requires the old-style syntax and it must be called before the method may be invoked, ie.
// first set up the mock
[[mock reject] methodThatShouldNotBeCalled]
// then call method that should not result in the call
For a glimpse on what's planned, see https://github.com/erikdoe/ocmock/issues/109
As I answered here, starting from version 3.3 OCMock has OCMReject macro.
I failed miserably at getting the reject-method to work so my solution was to simply stub the method-not-to-be-called(notifyChange: in example below) with throwing an exception whenever it is called.
// Set up the mock.
id<TSModelObserver> observer = OCMProtocolMock(#protocol(TSModelObserver));
// Stub the forbidden method call with throwing an exception.
[OCMStub([observer notifyChange:model]) andThrow:[NSException new]];
I've inferred what a lot of things DO in Objective-C, and I've gone through several tutorials that simply talk about the data types, but I haven't run across anything that simply explains the syntax.
For starters, what does this mean? What it does is start a thread and get data returned from a server:
- (void)apiCall:(void (^)(NSMutableArray *list))block {
Does something in that function header tell me that it is asynchronous? is that what block means?
No, block doesn't mean asynchronous, a block in Obj-C is just a bit of code that can be passed as an argument to a method.
methods that start with - are instance methods and those that start with + are class methods.
^ is a syntactic marker to denote a block.
For your first question: you would have to look at the API documentation to find out if it is asynchronous.
For more information about blocks in general, see here:
Apple Blocks Programming Guide
Let's start with your second bullet:
Class methods are declared with +, instance methods are declared with -.
The first and third are related, the parameter named block is a code block, it's a piece of code intended to be run later. Given the name of this method apiCall, I suggest this being the method run after the call is done.
It would we natural to suspect that this method will do some work on another thread and then invoke the block you supplied, but for this you'd need to check the documentation or the code.
The signature: (void (^)(NSMutableArray* list)) block describes a code block with a void return type and a NSMutableArray* list as only parameter.
An example usage of the block parameter would be:
void (^apiCallCallback)(NSMutableArray*) = ^(NSMutableArray* list) {
NSLog(#"The API returned %d items in a list", [list length]);
}
[someApiInstance apiCall:apiCallCallback];
After the API instance is done doing whatever it is suppose to do, you'll see that the log statement is printed.
In the below method calls from a single object, how to make the handler method to run 1st and then the main method in Objective-C?
Does it run in Asynchonous or Synchronous way?
Main method :AuthenticateMobileServer
handler Method :Handler
[mobile_Obj authenticateMobileServer:self action:#selector(handler:)];
Thank You.
I'm not sure if I'm getting what you're asking. But first of all please do use correct naming/capitalization for Objective-C! So please take a look at (http://developer.apple.com/mac/library/documentation/cocoa/conceptual/objectivec/articles/ocLanguageSummary.html)
(method names and variable names are in lowerCamelCase! Only class names are in CamelCase)
so it should be [mobileObj authenticateMobileServer:self action:#selector(handler:)]
Now to your question. By sending a authenticateMobileServer:action: message to mobileObj only that method is executed. #selector(handler:) is only a function pointer.
Writing some Objective-C in one method, I call +alloc, then -init to set up an object.
object = [[MyClass alloc] init];
[object useFor:whatever];
The next few lines of code use the newly created object. If the aforementioned -init takes too long, I’m sure the program won’t “wait” before starting to use the new object, will it? If not, is there a quick way to assure the -init is completed?
I sometimes see programmers who write something along the lines of
if(object = [[MyClass alloc] init]) {
[object useFor:whatever];
}
Is this what I should go for?
When you call init the program will not go on to the next line until the init method returns. By the time you've reached the second line, the init method has completed. It may not have completed successfully, but it will have completed.
The second form is a test. First the if statement calls the init method. If a valid object is returned then the test is true and then the next statement is executed. This is why you see init methods that return self when they are successful and nil when there is a problem; so that tests like these can be run to be sure that the object has been successfully initialised before continuing.
commands are executed in sequential order and not paralell
(dude, learn some basics ;)
As a rule, statements in C and Objective-C functions (and methods) are executed in sequence, in the order you write them. If you write one thing before another in a function, the first one must complete execution before the next one can execute.
The compiler may reorder statements if it believes that doing so will not change the behavior of the program (which it can predict very well in situations that don't involve concurrency), but this is an optimization. The C standard treats statements as being sequential, but allows compilers to implement this any way they like as long as the behavior of the actual program is the same as if the statements had been executed in the sequence in which they were written.
All this is a long way of saying: Your init method will complete before the calling method can resume execution.