I have a ObjC method that is setup like this:
- (void) doSomethingWithReply:(void(^)(NSError *))reply
I'm calling this method from another class where I have it setup like this:
[someObject doSomethingWithReply:^(NSError *error)
{
localerr = error;
}];
Ideally I would like to act on based on the return code I receive from my method. For instance, the method doSomethingWithReply could return EACCES or EBUSY. Depending on the return code received, I would like to do something in my calling method. What is the best way to compare localerr against EBUSY or EACCESS?
Using a simple comparison seems to throw an error.
Edit:
Comparison methods I tried:
if(localerr == EBUSY)
{
//do something
}
//Throws the following warning:
//Comparison between pointer and integer ('NSError *' and 'int')
if(*localerr == EBUSY)
{
//do something
}
//This throws the follow error:
//Invalid operands to binary expression ('NSError' and 'int')
Related
I have
OBJC:
- (void)doSomething:(void (^)(NSError *))block;
SWIFT:
let test = Test()
test.doSomething(<#T##block: ((Error?) -> Void)!##((Error?) -> Void)!##(Error?) -> Void#>)
I would rather
try? test.doSomething { }
I would like bridging-header to translate the function into
func doSomething(block: () throws -> ()) throws {
try block()
}
Is it possible? Thanks to all!
Your Objective-C method is declaring a parameter which is a block that receives an NSError object. It's basically declaring a callback.
If your method is not asynchronous you should declare it like this:
- (BOOL)doSomething:(NSError **)error;
Now the parameter is a pointer to an NSError* object. If the method fails for some reason, it should set an appropriate error for that parameter like so:
if (error != NULL) {
*error = <an appropriate error>
}
Also note the BOOL return type. According to Cocoa conventions the caller should refer to the return type to determine if the method failed or not, instead of testing for the existence of an NSError* object.
Declaring a method like this will expose it in Swift using the throws mechanics.
Update:
I don't think you can declare a Swift throwing block in Objective-C. If you go the other way around, and declare your desired method signature in Swift you'll see the compiler complains it can't be represented in Objective-C.
Most likely the (NSError **) to throwable convention never got implemented for blocks.
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.
Simple question. What is the meaning of the double asterisk in the interface below? It's not an NSError pointer, but what?
- (BOOL)checkResourceIsReachableAndReturnError:(NSError **)error
It's a pointer to a pointer to an NSError. It's used as an "out parameter" -- or you may want to think of it as a pointer to an NSError instance, considering an NSObject instance is always a pointer.
You use it like this:
NSError * outError = nil; << reserve place and a name for the out parameter
// pass the error so the client may return it to you:
BOOL ret = [obj checkResourceIsReachableAndReturnError:&outError];
if (nil != outError) { << the error was set in checkResourceIsReachableAndReturnError:
NSLog(#"Error: %#", outError); << log it
}
…
On the implementation side, it looks like this:
- (BOOL)checkResourceIsReachableAndReturnError:(NSError**)outError
{
if (self.isThingReachable) {
// okay - the caller may not be interested in the error, test it:
if (0 != outError) {
// they are interested this time!
*outError = [NSError errorWithBlahBlahBlah];
}
return NO;
}
return YES;
}
You call it by sending a reference to an NSError*, like so:
NSError *myError = NULL;
[foo checkResourceIsReachableAndReturnError:&myError];
if (myError) {
/* look through info, handle error, etc. */
}
The -checkResourceIsReachableAndReturnError: method can modify the pointer myError, including allocating space for a new NSError. This allows you to easily check if there was an error, by simply checking if myError is non-NULL.
Check out this blog post: "Using NSError To Great Effect" and pay particular attention to the section "Passing Pointers to Pointers."
Also the wiki page on pointers has a section on "Multiple Indirection"
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);
}
This is more of a C question but here it goes.
I've a method that receives as a parameter the address of a pointer to an NSError object. Now, that method is buried several levels deep in the class hierarchy and I need to make the error object bubble all the way to the top.
I could return the error object on each method but I'd rather do it the Cocoa way and return a boolean while passing the error object as a parameter.
How can I do this?
I could return the error object on each method but I'd rather do it the Cocoa way and return a boolean while passing the error object as a parameter.
The Cocoa way is the Boolean direct return with a by-reference (i.e., through pointer) return of the error value, like so:
NSError *error = nil;
if ([foo trySomething:bar error:&error]) {
//Success!
} else {
//Failure!
}
(Alternatively, trySomething:error: may return an object, in which case you treat that object as the Boolean return: non-nil is true/succeeded, nil is false/failed.)
To make this chainable, each method (except the outermost) should have an error-pointer parameter, and use that in its implementation:
- (void) trySomething:(MyBar *)bar error:(out NSError **)outError
if ([bartender restock:bar error:outError]) {
//Success!
} else {
//Failure!
}
}
You can combine both approaches, catching the error object in your own local variable in order to customize or wrap it in the failure case before storing the customized/wrapper error at the error-return pointer for your caller to receive.