1

Sorry, if found a lot of threads like the but they were not about this Error**-thing.

I tried to 'design' my methods like the error-examples I found. But calling the second, the error is not pointing to nil, the debugger says error: summary string parsing error.

This is my controller-method:

-(void) refresh {
  NSError *error;
  ServerApi *serverApi = [mainModel newServerApi];
  NSArray *newItems = [serverApi getNewItems: &error];
  ...

This is the called method:

- (NSArray *) getNewItems: (NSError **) error {
  // Breakpoint here, error is: 'error: summary string parsing error' 
      ...
  NSURLResponse *response;
NSData *responseData = [NSURLConnection sendSynchronousRequest: request returningResponse: &response error: error];

I thought, I did the same as Apple with sendSynchronousRequest.... Their comment tells

error     Out parameter (may be NULL) used if an error occurs
             while processing the request. >>>>Will not be modified if the 
             load succeeds.<<<<

What did I do wrong and why does this work for Apples sendSynchronousRequest...?

Sammy
  • 1,178
  • 1
  • 14
  • 27

2 Answers2

2

The code is fine, as error does not need to be initialized "from outside".

Also, if you use ARC it will automatically initialize local object pointers to nil, so

NSError *error;

is no different than

NSError *error = nil;

under ARC.

While explicit initialization is still a good practice, that's not the source of any error here.

That being said,

summary string parsing error

is a lldb error. My hypothesis is that it gets confused by the double pointer, but I wouldn't worry too much.

By the way, you're doing a slight mistake in implementing this pattern. Synchronous methods that may fail, should method to return a BOOL value indicating whether the computation was successful and then clients will check that value and subsequently inspect the error object in case it failed.

Checking the error object is in general a bad idea: even some Apple APIs can fail and yet return a nil error, so avoid doing that!

Community
  • 1
  • 1
Gabriele Petronella
  • 106,943
  • 21
  • 217
  • 235
  • it is fine under non arc too .. the error may not be nil. thats totally fine. LLDB then obviously cant show it but thats no real problem – Daij-Djan Mar 08 '14 at 20:30
  • Thx, so I don't have to ask about the debugger-info. The check was my problem (see Leo Natan's answer). – Sammy Mar 08 '14 at 20:30
  • @Daij-Djan Under non-ARC, if the `error` variable is not zeroed, you would not be able to tell if an error occurred or there was a garbage value. – Léo Natan Mar 08 '14 at 20:32
  • @LeoNatan: Checking the error object to determine success is contrary to [Cocoa convention](http://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ErrorHandlingCocoa/CreateCustomizeNSError/CreateCustomizeNSError.html#//apple_ref/doc/uid/TP40001806-CH204-SW1). The direct return value should be used for that, and the error inspected only on failure. – jscs Mar 08 '14 at 20:38
1

Remember to set your pointer to nil in refresh:

NSError *error = nil;

Also, remember, your checks should be:

  • Checking (*error) for nil (aka "there was no error passed") - operation may or may not have been successful;
  • Checking error for NULL (aka "there was no NSError* pointer passed, so don't assign it an object").
Léo Natan
  • 56,823
  • 9
  • 150
  • 195
  • under ARC `error` will be initialized to `nil` automatically. – Gabriele Petronella Mar 08 '14 at 20:20
  • @GabrielePetronella Are you sure? Only instance variables are initialized, if I remember correctly. We had some issues with uninitialized error pointers, and it was after moving to ARC. – Léo Natan Mar 08 '14 at 20:22
  • pretty sure, but I'll find a reference. – Gabriele Petronella Mar 08 '14 at 20:22
  • @GabrielePetronella Cool thx. Still good practice to initialize in my opinion. – Léo Natan Mar 08 '14 at 20:23
  • 1
    here you go: http://stackoverflow.com/questions/10022025/local-variables-set-to-nil-objective-c. Anyway still a good practice, but that's not cause of any problem under ARC. – Gabriele Petronella Mar 08 '14 at 20:24
  • @Leo Natan - Thx a lot, checking (*error) was my bad. The debugger with it's wrong information about 'error' did the rest ;-) – Sammy Mar 08 '14 at 20:28
  • @Sammy Yes, I am aware of debugger bugs with pointer to pointer. Recently, I came to prefer the `errorBlock:` pattern instead of `NSError**`. More elegant and less error-prone. – Léo Natan Mar 08 '14 at 20:30
  • 1
    Ok, ErrorBlock is an other option. But as I have some deeper method-stacks, I should test for *error correctly anyway. Thx – Sammy Mar 08 '14 at 20:32
  • 1
    @Sammy checking for error is not the right way of applying this pattern. You should have the method to return a `BOOL` indicating whether the computation was successful and check the return value. Even some Apple APIs may fail and yet return a `nil` error, so avoid doing that! – Gabriele Petronella Mar 08 '14 at 20:35
  • @Gabriele Petronella - the original meaning of that method is to provide items, read from an server-api, so I think it should return them. An other thing is, that the server has to be addressed multiple times in this case (I simplified this a bit), so I do a lot of calls to convenience-methods. The error-pointer is the only way (I saw) to pass back an error up the call-stack. – Sammy Mar 08 '14 at 22:07
  • @Sammy leaving aside the fact that you really should do this asynchronously, you can easily return a `BOOL` and return the items indirectly (in the same way you do with the error). – Gabriele Petronella Mar 09 '14 at 10:31
  • @Gabriele Petronella: I know, that you should normally do that call asynchronous. But my app only works in the own wlan, so there should be no long-running connections. Anyway, there's nothing the user can do since he was once connected to the server. – Sammy Mar 09 '14 at 12:46