Sign In/My Account | View Cart  

advertisement

AddThis Social Bookmark Button

Article:
  Mac OS X's Preferences System (and More!)
Subject:   tests for nil in awakeFromNib incorrect
Date:   2001-08-29 19:55:01
From:   jeremym
Hi,


The test "if ( nil == records )" within the awakeFromNib method do not work. You use


records = [[NSMutableArray alloc] initWithArray:[prefs arrayForKey:@"Addresses"]];


To read the data from the preferences system into the data structure. Once the alloc is performed the pointer "records" no longer points to nil, regardless of what happened in the init code. You can test this by pointing a break point in the code, or like I did on accident. Run the program in the final form, add some stuff, and quit. Then delete the com.###.AddressBook.plist, but keep the AdressBookData.plist. Re-run the program and nothing shows up. The if statement returns NO, because your pointer has a value after alloc.


Here is what I used to solve the problem:


records = [[NSMutableArray alloc] initWithArray:[prefs arrayForKey:@"Addresses"]];
if ( nil == [records count]) {
records = [[NSMutableArray alloc] initWithContentsOfFile:recordsFile];
if ( nil == [records count] ) {
records = [[NSMutableArray alloc] init];
} else {
[self saveData];
}
}
}


The else { [self saveData] } serves to re create the preferences file from the AddressBookData.plist file if it is missing.


Great articles, I am learning a lot.
Jeremy

Full Threads Oldest First

Showing messages 1 through 3 of 3.

  • Michael Beam photo tests for nil in awakeFromNib incorrect
    2001-08-31 18:56:33  Michael Beam | O'Reilly Author [View]

    Indeed, records wouldn't be nil after doing [NSMutableArray alloc]. Thanks for catching that!

    Now, in your fix wouldn't we want to do
    if ( [records count] == 0 ) instead of
    if ( [records count] == nil )? I'm trying to think if there's a more fundamental to test whether or not the initialization was successful, but can't think of anything at the moment.


    The last [self saveData] isn't strictly necessary, as the preferences file would be re-written the first time a record is added. I was actually debating whether or not to do just this when i was writing this code, and I decided to keep things less cluttered, pedagogically speaking. But on the other hand, it's not a bad idea either.

    Thinking about it a little more, we could have two different types of if statements, rather than the way we've been doing it. For example, we could do the following:

    if ( nil != [prefs arrayForKey:@"Addresses"] ) {
    records = [[NSMutableArray alloc] initWithArray:[prefs arrayForKey:@"Addresses"] )
    } else if ( [[NSFileManager defaultFileManager] fileExistsAtPath:recordsFile] == YES ) {
    records = [[NSMutableArray alloc] initWithContentsOfFile:recordsFile];
    } else {
    records = [[NSMutableArray alloc] init];
    }

    (I hope this code posts right, tough in this small editing window :)
    • Michael Beam photo tests for nil in awakeFromNib incorrect
      2001-08-31 19:04:10  Michael Beam | O'Reilly Author [View]

      Okay, i posted before i finished what i wanted to say: So in the first if statement, we test to see if the key exists in the user's prefs, if so, then we go ahead and use prefs to initialize records, if not we move onto the next if statement. In if-number-two we test to see if the file recordsFile exists at the path, using the NSFileManager method fileExistsAtPath:, which returns a BOOL. If the return value is YES, then we initialize records from the file on disk. if now, then we initialize to an empty array. Again, if you want you can put [self saveData] in the code block for the second if statement and the else code block. As you can see this is only one way to do it. If someone comes up with another way, share it with us!

      Mike
      • tests for nil in awakeFromNib incorrect
        2003-05-18 20:33:11  anonymous2 [View]

        It is strange that according to my test, if an init... operation failed, it does return a nil. I read the manual from Apple, it also says that a failed init... operation will release the object and return a nil. So, I think your original code is correct. :-). But I agree that you should add a [self saveData]; statement in the awakeFromNib method. Coz, it seems that the [self saveData] in the dealloc can not really save the data, so you will not re-create the missing file is you haven't modified the data. Strange!