Incompatible block pointer type? Cannot return NSArray - objective-c

I have a block we return an array in callback. Then I create another method to store that array as below:
- (NSArray *)getUserData{
[self fetchDataByUserId:self.userID completionHandler:^(NSArray *record) {
return record;
}];
}
I received this kind of error so please help me, I don't understand.
"Incompatible block pointer types sending 'NSArray *(^)(NSArray * __strong) to parameter of type 'void (^)(NSArray *_strong)"

Reason is explained by #user3386109, this is the right way.
- (void)getUserData:(void (^)(NSArray *record))complete {
[self fetchDataByUserId:self.userID completionHandler:^(NSArray *record) {
complete(record);
}];
}
or
- (void)getUserData:(void (^)(NSArray *record))complete {
[self fetchDataByUserId:self.userID completionHandler:complete];
}
Moreover, about the Error Message: "Incompatible block pointer type", you should google "How to use Block in objective-c", ex: http://rypress.com/tutorials/objective-c/blocks
Because your completionHanler is not a return type block, it's a void block.
(void (^)(NSArray *record))
is different with
(NSArray * (^)(NSArray *record))

The completionHandler is not called immediately, and is not expected to return a value. You can think of the code in the completionHandler as a callback function. The caller is some framework code that executes whenever the fetch completes. The framework code calls your completionHandler to let you know that the fetch is finished, and doesn't expect any return value.
So the getUserData method should really be a startUserDataFetch method, and you need additional code to process the data if ever / whenever it actually arrives.

Related

Objective-C Block Syntax

Obj-C blocks are something I'm just using for the first time recently. I'm trying to understand the following block syntax:
In the header file:
#property (nonatomic, copy) void (^completionBlock)(id obj, NSError *err);
In the main file:
-(void)something{
id rootObject = nil;
// do something so rootObject is hopefully not nil
if([self completionBlock])
[self completionBlock](rootObject, nil); // What is this syntax referred to as?
}
I appreciate the assistance!
Blocks are Objects.
In your case inside the method you are checking if the block is not nil and then you are calling it passing the two required arguments ...
Keep in mind that blocks are called in the same way a c function is ...
Below i have split the statement in two to let you understand better :
[self completionBlock] //The property getter is called to retrieve the block object
(rootObject, nil); //The two required arguments are passed to the block object calling it
Its a block property, you can set a block at runtime.
Here is the syntax to set
As it is void type, so within the class you can set a method by following code
self.completionBlock = ^(id aID, NSError *err){
//do something here using id aID and NSError err
};
With following code you can call the method/block set previously.
if([self completionBlock])//only a check to see if you have set it or not
{
[self completionBlock](aID, nil);//calling
}

memory leak when using callback

I'm having an issue with memory management when dealing with callbacks and async code in objective c.
I cant seem to find a way to release the instance that the callback is set on.
For example:
MyClass *myArchive = [[MyClass alloc] init] ;
[myArchive callBack:^(RKObjectLoader* objectLoader, id object ) {
NSLog(#"success");
} fail:^(RKObjectLoader* objectLoader, NSError* error) {
NSLog(#"failed");
}];
[myArchive searchArchive:words:paging];
The problem being that I don't know when or how to release the instance *myArchive. Using Instruments within xcode to profile my code I always get a leak here. The function searchArchive performs an async request to a server using restkit. I wont reference the instance from within the callback as I heard this causes a retain cycle and I have done some reading about using __block and other c approaches to avoid retain cycles which is all fine but as it stands now with no actual code happening within the callback how do I release the *myArchive instance. anyone able to explain how I should deal with this within objective-c?
EDIT:
This is where I set the callback in myclass
// Sets internal backs on this object which basically wrap the delegate
//
- (void)callBack: (void (^)(RKObjectLoader* objectLoader, id object))success
fail: (void (^)(RKObjectLoader* objectLoader, NSError* error))fail {
//sanity check
NSAssert(_currentDelegate != self, #"Delegate is another object. Can not set callback");
// store our callback blocks in the instance
_success = [success copy] ;
_fail = [fail copy] ;
}
and then release _success and _fail in dealloc
and within the #interface
#interface myClass : NSObject<RKObjectLoaderDelegate> {
// holds the block callback for "success"
void (^_success)(RKObjectLoader* objectLoader, id object);
// holds the block callback for "fail"
void (^_fail)(RKObjectLoader* objectLoader, NSError* error);
}
I hope this gives more insight into what I'm doing wrong.
EDIT 2:
Ok I'm beginning to see the errors now:
-(void)retrieveGallery{
//create call back for async and deal with the result
[_galleryItems callBack:^(RKObjectLoader* objectLoader, NSArray *objects) {
//success happy days. do a bunch of code here that does not cause leaks
} fail:^(RKObjectLoader* objectLoader, NSError* error) {
//retry the attempt to retrieve gallery data from the server
_retryCount++;
if (_retryCount < _maxRetryCount) {
[self retrieveGallery];
}
}];
//read the collection of gallery items from server
[_galleryItems readGallery];
}
The only actual memory leaks are when the callback catches a fail for what ever reason and then calls the [self retrieveGallery] function from within callback to attempt again. this is what is causing the leak so I'm guessing that is a big no no. How should I attempt the function (retrieveGallery in this case) again.
Memory management isn't really any different because you are using an asynchronous callback. myArchive should be a property of whatever class you are doing this in. You want it to stick around until the task is complete, right?
#property (retain) MyClass *myArchive;
Then..
myArchive = [[MyClass alloc] init];
void (^on_success_callback)(void) = ^(void){
NSLog(#"success");
self.myArchive = nil;
};
You need to make sure you are managing the callbacks properly, i.e. copying them from the stack and releasing them when you are done.
If you have retains and releases in your code you probably aren't using the accessor methods properly.

Confused about the use of one or more asterisks in Objective-C

I'm reading a book on Core Data and at some point the author has this validation method:
- (BOOL)validateRadius:(id *)ioValue error:(NSError **)outError {
NSLog(#"Validating radius using custom method");
if ([*ioValue floatValue] < 7.0 || [*ioValue floatValue] > 10.0) {
// Fill out the error object
if (outError != NULL) {
NSString *msg = #"Radius must be between 7.0 and 10.0";
NSDictionary *dict = [NSDictionary dictionaryWithObject:msg forKey:NSLocalizedDescriptionKey];
NSError *error = [[[NSError alloc] initWithDomain:#"Shapes" code:10 userInfo: dict] autorelease];
*outError = error;
}
return NO;
}
return YES;
}
There are two things that confuse me and since I don't even know what they are technically called, can't seem to find in Google.
First one is the use of double asterisks ** in the method signature:
- (BOOL)validateRadius:(id *)ioValue error:(NSError **)outError {
The second is the use of a single asterisks * when on the reciever of a method call:
[*ioValue floatValue]
I haven't seen any of these two things before so I'm wondering what they are about. Just started iOS programming 6 or so months ago.
Any explanations or pointers to online documentation are very welcome.
(id *)ioValue means that ioValue is a pointer to an id, not an id itself. The expression *ioValue refers to the id that ioValue points to.
(NSError **)outError means that outError is a pointer to an NSError * (which is, in turn, a pointer to an NSError).
The usual reason for passing pointers to functions in this fashion is to allow the function to return something to the caller.
In the above case, the function could assign a new id to the variable that the caller passed in: *ioValue = something(). However, since the above function doesn't actually do this, it seems redundant; it could have been written as (id)ioValue, and then referred to it as ioValue instead of *ioValue.
The outError case makes perfect sense, however. In the event of an error, the function creates an error object (NSError *error = ...) and assigns it to the passed-in variable thus: *outError = error. This has the effect of changing the original variable that the caller passed in, so that when the function returns, the caller can inspect the variable to see the error that was produced:
id ioValue = something();
IOError *err;
if ([foo validateRadius:&ioValue error:&err]) {
NSLog("Yippee!");
} else {
reportError(err);
}

How to assign a value to an pointer-pointer passed in call by reference?

I want to achieve something similar to what these guys do here:
- (NSUInteger)countForFetchRequest:(NSFetchRequest *)request error:(NSError **)error
like you can see, you pass an NSError pointer and that nice method will assign a real NSError object to your pointer in case there is an error. So the cool thing about this is, that the method returns an NSUInteger but can ALSO return an NSError, without having to mess around with ugly and fat arrays or dictionaries.
So how could I assign an object to the passed-in error pointer?
It's easy. This Apple guide shows how you might implement a method that returns an NSError object. But to make a long story very, very short:
- (NSUInteger)countForFetchRequest:(NSFetchRequest *)request error:(NSError **)error
{
//Do stuff, including make MyCustomErrorDomain and errCode and eDict.
if (error != NULL) { // check to avoid crash if **error is not provided
*error = [[[NSError alloc] initWithDomain:MyCustomErrorDomain code:errCode userInfo:eDict] autorelease];
}
//Do some more stuff.
}
Note the asterisk. :)

Handling Callbacks

I have a method in an objective-C class. It has 2 callback functions written in C. The class pointer i.e. self is passed to these functions as void *. In the C functions I create a pointer of type class and assign the void * parameter.
The first callback function executes successfully. But the void * pointer becomes nil in the 2nd callback function. Note that I haven't tweaked pointer in the first callback but still I get nil in 2nd callback.
Any ideas what might be going wrong?
For example:
kr = IOServiceAddMatchingNotification(gNotifyPort, kIOFirstMatchNotification,
matchingDict, RawDeviceAdded, NULL,
&gRawAddedIter);
RawDeviceAdded(NULL, gRawAddedIter, self);
This works fine. But below function receives self as nil.
kr = IOServiceAddMatchingNotification(gNotifyPort, kIOFirstMatchNotification,
matchingDict, BulkTestDeviceAdded, NULL,
&gBulkTestAddedIter);
BulkTestDeviceAdded(NULL, gBulkTestAddedIter, self);
Are your problems specifically with the IOKit callback routines? The problem with the specific example you gave is that the IOServiceMatchingCallback takes only 2 parameters, not 3. You need your RawDeviceAdded() and BulkTestDeviceAdded() callback functions to match the IOServiceMatchingCallback prototype and to accept self as the first parameter (refCon), not the 3rd. Also, you need to pass in self as the second-to-last parameter of IOServiceAddMatchingNotification() to get it passed back to you by the callback.
A common method for handling C callbacks in Objective-C code is just to have a static function that forwards the callback to your instance. So, your example callback code would look like this:
static RawDeviceAdded(void* refcon, io_iterator_t iterator)
{
[(MyClass*)refcon rawDeviceAdded:iterator];
}
#implementation MyClass
- (void)setupCallbacks
{
// ... all preceding setup snipped
kr = IOServiceAddMatchingNotification(gNotifyPort,kIOFirstMatchNotification, matchingDict,RawDeviceAdded,(void*)self,&gRawAddedIter );
// call the callback method once to 'arm' the iterator
[self rawDeviceAdded:gRawAddedIterator];
}
- (void)rawDeviceAdded:(io_iterator_t)iterator
{
// take care of the iterator here, making sure to complete iteration to re-arm it
}
#end
Generally, callbacks in Objective-C are handled by passing a delegate object and a selector to perform on that delegate. For example, this method will call a method on its delegate after logging a message, passing both itself and the message that was logged.
- (void)logMessage:(NSString *)message
delegate:(id)delegate
didLogSelector:(SEL)didLogSelector
{
NSLog(#"%#", message);
if (delegate && didLogSelector && [delegate respondsToSelector:didLogSelector]) {
(void) [delegate performSelector:didLogSelector
withObject:self
withObject:message];
}
}
You might call it in code like this:
- (void)sayHello
{
[logger logMessage:#"Hello, world"
delegate:self
didLogSelector:#selector(messageLogger:didLogMessage:)];
}
- (void)messageLogger:(id)logger
didLogMessage:(NSString *)message
{
NSLog(#"Message logger %# logged message '%#'", logger, message);
}
You can also use objc_msgSend() directly instead, though you need to understand the Objective-C runtime enough to choose which variant to use and how to construct the prototype and function pointer through which to call it. (It's the mechanism by which message sends are actually implemented in Objective-C — what the compiler normally generates calls to in order to represent [] expressions.)
This is what Objective-C's selector is for:
http://developer.apple.com/iphone/library/documentation/Cocoa/Reference/NSInvocationOperation_Class
The API isn't very intuitive, but its fine once you understand it
You might need to do some refactoring as well, now there might be a better way, but when I had this problem my solution was to refactor and use InvoationOperation.