Question

Some information about the way I am saving my data: I have an array of View Controllers that are added and deleted by the user (this is basically a note taking app and the View Controllers are folders). The View Controllers have several dynamic properties that the app needs to save as well as the notes array within them, and then the Note objects themselves have a few properties that need to be saved. The View Controllers and the Notes both of course have the proper NSCoding stuff, this is the one on the View Controller for example:

- (void) encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeObject:self.folderName forKey:@"lvcTitle"];
    [encoder encodeObject:[NSNumber numberWithInt:self.myPosition] forKey:@"myPosition"];
    [encoder encodeObject:self.notes forKey:@"notes"];
}

- (id)initWithCoder:(NSCoder *)decoder {
    self.folderName = [decoder decodeObjectForKey:@"lvcTitle"];
    NSNumber *gottenPosition = [decoder decodeObjectForKey:@"myPosition"];
    int gottenPositionInt = [gottenPosition intValue];
    self.myPosition = gottenPositionInt;
    self.notes = [decoder decodeObjectForKey:@"notes"];
    return self; }

The array of Controllers belongs to a Singleton class. NSCoding is pretty confusing to me even though it's considered to be simple stuff, but so far I've had success with only telling the Singleton to save the Controllers array - which then (successfully) saves all of the contained properties of the View Controllers, their properties and all of the Notes' properties as well. Here is the code in the Singleton:

- (void) saveDataToDisk:(id)object key:(NSString *)key {
    NSString *path = [self pathForDataFile];

    NSMutableDictionary *rootObject;
    rootObject = [NSMutableDictionary dictionary];

    [rootObject setValue:object forKey:key];
    [NSKeyedArchiver archiveRootObject:rootObject toFile:path]; } 

- (void) loadDataFromDisk {
    NSString *path = [self pathForDataFile];
    NSDictionary *rootObject;

    rootObject = [NSKeyedUnarchiver unarchiveObjectWithFile:path];    

    if ([rootObject valueForKey:@"controllers"] != nil) {
        self.controllers = [NSMutableArray arrayWithArray:[rootObject valueForKey:@"controllers"]];
        firstRun = false;

        LabeledViewController *lastOneThere = [self.controllers objectAtIndex:self.controllers.count-1];
        lastOneThere.isFolderAddView = TRUE;

    }else{
        firstRun = true;
    } 
}

I then call the save method several times in the Folder View Controllers:

[singleton saveDataToDisk];

And this will work well several times, until I randomly get a crash right when the app is loading up. The culprit is heightForRowAtIndexPath:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

Note *currentNote = [self.notes objectAtIndex:indexPath.row];
if (currentNote.associatedCellIsSelected) {
    return currentNote.myHeight + NOTE_BUTTON_VIEW_HEIGHT;
}

return NORMAL_CELL_FINISHING_HEIGHT;  }

I get the following error:

2012-06-07 08:28:33.694 ViewTry[1415:207] -[__NSCFString associatedCellIsSelected]: unrecognized selector sent to instance 0x8904710
2012-06-07 08:28:33.696 ViewTry[1415:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString associatedCellIsSelected]: unrecognized selector sent to instance 0x8904710'
*** First throw call stack:

I understand that "__NSCFString" and "unrecognized selector sent to instance" means that there is a string somewhere there shouldn't be, as associatedCellIsSelected is a bool. However, if I only return "currentNote.myHeight" in heightForRow, I also get the same __NSCF error with myHeight, which is a float. If I take out heightForRow all together, everything works except for the appropriate height definitions.

BTW, the table view that heightForRowAtIndexPath is referencing is made in loadView AFTER the notes array is made and populated. I just don't understand why this error would only pop up every once in a while (like 5-10 opens, savings, closings and reopenings of app), seemingly random - I cannot find the pattern that causes this behavior. Any pointers?

Sorry for the mess, I'm new to iOS programming and I'm sure I'm doing a lot of things wrong here.

Edit - Also, once the app has crashed, it stays crashed every time I reopen it (unless I disable heightForRow) until I uninstall and reinstall it.

Was it helpful?

Solution

When you see an "unrecognized selector" error and the receiver type is not the kind of object that you coded (in this case __NSCFString instead of Note), the odds are that you have a problem where the object you intended to use has been prematurely released and its address space is being reused to allocate the new object.

The fix depends on tracking down where the extra release is happening (or retain is not happening). If you can show the @property declaration for notes it might shed more light on the situation.

One quick thing to do is choose Product->Analyze from the menu and fix anything it flags. It won't catch everything but it's a good sanity check to start.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top