views:

61

answers:

1

I have just jumped into Objective-C and I got stuck pretty early on. I will post code with my question but to keep it readable i'll get rid of some of the crap, let me know if you want more code posted!

I have created a new object called 'Phrase' (subclassed from NSObject), and am reading items from JSON into these 'Phrase' objects and adding them to an array. Here's the first lot of code:

Example JSON:

    {
    "phrases": [
        {
            "title": "Title of my Phrase",
         "definition" : "A way to look at some words",
   "location" : "Irish Proverb"
        }   
    ]
    }

Script I'm reading it in with:

    - (void)viewDidLoad {
    [super viewDidLoad];

 self.phraseDictionary = [[NSMutableArray alloc] initWithObjects:nil];

 NSString *filePath = [[NSBundle mainBundle] pathForResource:@"phrase" ofType:@"json"];  
 NSString *myRawJSON = [[NSString alloc] initWithContentsOfFile:filePath];

 NSData *jsonData = [myRawJSON dataUsingEncoding:NSUTF32BigEndianStringEncoding];
 NSDictionary *entries = [[CJSONDeserializer deserializer] deserializeAsDictionary:jsonData error:nil];


 for (id key in entries) {

  NSObject *phrases = [entries objectForKey:key];

  for (id phrase in phrases) {

   Phrase *pushArrayToPhrase = [[Phrase alloc] initWithText:[phrase objectForKey:@"title"] definition:[phrase objectForKey:@"definition"] location:[phrase objectForKey:@"location"]];
   [self.phraseDictionary addObject:pushArrayToPhrase];

  }

    }
    }

Phrase m file:

#import "Phrase.h"


@implementation Phrase

@synthesize title;
@synthesize definition;
@synthesize location;

- (id)init {
 self = [super init];
 if (self != nil) {
  title = @"";
  definition = @"";
  location = @"";
 }
 return self;
}

- (id)initWithTitle:(NSString *)tit definition:(NSString *)def location:(NSString *)loc {
 self = [super init];
 if (self != nil) {
  title = tit;
  definition = def;
  location = loc;
 } 
 return self;
}


@end

From here I loop through the objects and add them to a list in my splitview:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

 static NSString *CellIdentifier = @"CellIdentifier";

 // Dequeue or create a cell of the appropriate type.
 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        cell.accessoryType = UITableViewCellAccessoryNone;
    }

    Phrase *cellPhrase = [self.phraseDictionary objectAtIndex:indexPath.row];
 cell.textLabel.text = cellPhrase.title;
 return cell;
}

But when I click an item, and ask for a phrase based on the indexPath.row of the one clicked, I can only ever access the property used in the cell.textLabel.text. Any other attempt from here on in to access a property from the Phrase object exits the simulator.

- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

 Phrase *cellPhrase = [self.phraseDictionary objectAtIndex:indexPath.row];
 detailViewController.detailItem = cellPhrase;
 //If i attempt 'cellPhrase.definition' here, the app will close without an error

}

Hope that's easy to follow, let me know if it's not and i'll try again!

+1  A: 

In the initWithTitle method you are assigning the variables but not retaining them. If they are not retained anywhere they will be released and when you try to access them your app will crash. If you are not getting any error messages make sure you turn debugging on.

skorulis
What do you mean by assigning but not retaining? (I'm new to this, so still getting my head around assign/retain etc) - Where i have title = tit;definition=def etc in the initWithTitle method, do i need to be doing this differently?
jamie-wilson
Also - I turned on debugging and I get "Program received signal: “EXC_BAD_ACCESS”."
jamie-wilson
When you do title = tit; there is nothing stopping the memory reserved by the string from being released later on. So next time you try to access the string your program will crash as the memory isn't valid anymore. To prevent this try title = [tit retain]; or if your properties are retain you can do self.title = tit; Then in your dealloc method do [title release]; to make sure the memory is cleaned up later on.
skorulis
Thanks heaps, that did the trick. Do you have any suggestions for good reading regarding memory management / retaining etc in objective-c or even around the general principles?
jamie-wilson