How to retain objects in NSMutableArray IOS5 - iphone

I have an array of custom objects called array which stores a bunch of core data. I use this array to populate my UITableView and to create the cells. I then try to use the same array when UISearch is opened but at this point the array is empty, how could I retain the objects in the array?
EDIT
Ok, here is some of my code
my .h file
#interface SelectCourses : UIViewController <DataHandlerDelegate, UITableViewDataSource, UITableViewDelegate, UITableViewDataSource> {
DataHandler *dataHandler;
NSMutableArray *courses;
IBOutlet UITableView *table;
IBOutlet UISearchBar *searchFilter;
//NSMutableArray *filteredCourses;
BOOL isFiltered;
}
#property (retain) NSMutableArray* filteredCourses;
Then my .m file, I have left out several functions which I believe are irrelevant
#implementation SelectCourses
#synthesize Delegate;
#synthesize filteredCourses;
...
...
- (void) dataHandlerHasLoadedCourseData:(NSMutableArray *)courseData {
courses = courseData;
[table reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(isFiltered){
return filteredCourses.count;
}
if (courses) {
NSLog(#"Count: %i", [courses count]);
if (courses.count == 1) {
return 0;
}
return [courses count];
}
else
return 0;
}
...
...
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchFiltert {
NSLog(#"searchBarSearchButtonClicked");//More debugging
if(searchFilter.text.length == 0)
{
isFiltered = FALSE;
}
else
{
NSLog(#"%#", [NSString stringWithFormat:searchFilter.text]);
isFiltered = true;
for (Course *course in courses)
{
NSRange codeRange = [course.Code rangeOfString:searchFilter.text options:NSCaseInsensitiveSearch];
NSRange nameRange = [course.Name rangeOfString:searchFilter.text options:NSCaseInsensitiveSearch];
if(codeRange.location != NSNotFound || nameRange.location != NSNotFound)
{
[filteredCourses addObject:course];
}
}
}
[table reloadData];
}
I still get the following error when running the script, I simply assumed it was due to the array being empty
2012-04-11 20:54:23.067 scheduleTable[45885:fb03] -[__NSArrayM Code]: unrecognized selector sent to instance 0x897b360
2012-04-11 20:54:23.068 scheduleTable[45885:fb03] *** WebKit discarded an uncaught exception in the webView:shouldInsertText:replacingDOMRange:givenAction: delegate: <NSInvalidArgumentException> -[__NSArrayM Code]: unrecognized selector sent to instance 0x897b360
My course.h and .m looks like this
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#class Post;
#interface Course : NSManagedObject
#property (nonatomic, retain) NSString *Code;
#property (nonatomic, retain) NSString *Name;
#end
and
#import "Course.h"
#import "Post.h"
#implementation Course
#synthesize Code;
#synthesize Name;
#end

If I'm understanding your question correctly, to retain your array, declare the array in your .h file, like so:
#property (retain) NSMutableArray *yourArrayName;
Then,synthesize it in your .m file, like this:
#synthesize yourArrayName;

I tried using the retain method as Oral b answered but it got me nowhere, I am a bit of a newbie to Objective c which is why I am having the issues.
My courses array was declared in an interface and I was not able to achieve the same result with it as I did with the new array I created just for the search. So in ViewDidLoad I do this
coursesForSearch = [[NSMutableArray alloc] init];
Then where objects were added to my other array I simply added this array and also added the objects to it.
Now I can get objects from the array like so
[[coursesForSearch objectAtIndex:500] objectAtIndex:0]);

Related

exc_bad_access from nsstring in an instance - HARD, BUT COOL

I have read the posts I found here and in many other places - no answers.
I have a simple class that contains NSString:
MyItem.h
#import <Foundation/Foundation.h>
#interface MyItem : NSObject
{
NSString * ItemName;
NSNumber * TestID;
NSMutableArray * Items;
}
//property
#property (nonatomic,retain) NSString * ItemName;
#property (nonatomic,retain) NSNumber * TestID;
#property (nonatomic,retain) NSMutableArray * Items;
// methods
-(id)initWithName:(NSString*)theName;
#end
MyItem.M
#import "MyItem.h"
#implementation MyItem
#synthesize Items;
#synthesize TestID;
#synthesize ItemName;
-(id)initWithName:(NSString*)theName
{
ItemName=theName;
Items=[[NSMutableArray alloc]init];
return self;
}
#end
It is very simple, as the class is created, the name is retained and the array allocated.
In order to have view controllers sharing this class, I have created this protocol:
MasterPager.h
#import <Foundation/Foundation.h>
#class MyItem;
#protocol MasterPager <NSObject>
#required
#property (nonatomic,retain) MyItem * currentItem;
-(void)dumpItems;
#end
which I then use in my appdelegate:
ArrayTestAppDelegate.h
#import <UIKit/UIKit.h>
#import "MasterPager.h"
#class ArrayTestViewController;
#interface ArrayTestAppDelegate : NSObject <UIApplicationDelegate,MasterPager>
{
//MyItem * currentItem;
}
#property (nonatomic,retain) MyItem * currentItem;
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet ArrayTestViewController *viewController;
#end
I'm instanciating this property in the application didFinishLaunchingWithOptions as so:
#synthesize currentItem;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
// Override point for customization after application launch.
currentItem=[[MyItem alloc] initWithName:#"main stuff"];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
self.viewController.mainPage=self;
return YES;
}
and here is the dumpItem method:
-(void)dumpItems
{
NSLog(#"Dumping %#",currentItem.ItemName);
for(int i=[currentItem.Items count]-1;i>=0;i--)
{
MyItem * item=[currentItem.Items objectAtIndex:i];
NSLog(#"current item id:%#", item.TestID );
NSLog(#"current item name:%#", item.ItemName );
}
}
(Sorry for all this text, but it is probably required).
Now, I have a view controller that I use in order to test this.
This view controller has 2 buttons, each of them triggers different function.
the first function to create some (4) sub items in this object is working fine:
-(IBAction)onCreate:(id)sender
{
for(int i=0;i<4;i++)
{
MyItem * item=[[MyItem alloc] initWithName :[NSString stringWithFormat:#"Test number %d",i]];
item.TestID=[NSNumber numberWithInt:i];
[mainPage.currentItem.Items addObject:item];
}
[mainPage dumpItems];
}
As you can see the dumpItems is called and it does what its suppose to do, dumping the objects.
********NOW... here is the thing!*************
There is a second button, as mentioned, that execute the same function:
- (IBAction)onDump:(id)sender
{
NSLog(#"executing dump on the protocol");
[mainPage dumpItems];
}
After creation, clicking the second button is calling this method which in turn calls the same dumpItems! BUT, when this is executed, an exc_bad_access is thrown when the line
NSLog(#"current item name:%#", item.ItemName );
is reached. comment the line and it's all working.
un-commenting the //MyItem * currentItem; will do nothing. So, how could it be?
NSZombieEnabled ? Tried that, did nothing.
There is no release call in sight, and if there were, how come the NSNumber dump working just fine?
Also, nothing happen between the first button clicked and the second one.
but still, the strings somehow disappears!
is this ARC? If not, it's not that hard, and not that cool ;-)
You pass an autoreleased NSString to your init method
MyItem * item=[[MyItem alloc] initWithName :[NSString stringWithFormat:#"Test number %d",i]];
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ autoreleased object
Unfortunately you don't retain that autoreleased string in your init.
-(id)initWithName:(NSString*)theName {
ItemName=theName; // <- no retain
}
the code steps out of the init method and you run dumpItems on the newly created object
[mainPage dumpItems]; // <- within same runloop iteration. AutoreleasePool has not be drained.
since you call dumpItems before the end of the current runloop the autoreleased object still exists.
But the IBAction method happens after the autoreleased object has been deallocated (the object was deallocated when the autorelease pool was drained at the end of the current runloop).
- (IBAction)onDump:(id)sender
{
NSLog(#"executing dump on the protocol");
[mainPage dumpItems]; // <- not in the same runloop. AutoreleasePool has been drained. Autoreleased object has been deallocated
}
the fix:
-(id)initWithName:(NSString *)theName
{
if ((self = [super init])) {
itemName = [theName retain]; // to match your #property
items = [[NSMutableArray alloc] init];
}
return self;
}
By the objective-c code style guidelines only Class names (e.g. NSString, MyItem) should start with a capital letter. You should fix this to improve readability (and the code formatting on stackoverflow)
I had the same problem, you should change the code from:
#property (nonatomic,retain) NSString * ItemName;
#property (nonatomic,retain) NSNumber * TestID;
#property (nonatomic,retain) NSMutableArray * Items;
to:
#property (nonatomic,copy) NSString * ItemName;
#property (nonatomic,copy) NSNumber * TestID;
#property (nonatomic,copy) NSMutableArray * Items;

Error in Obj-C "unrecognized selector sent to instance"

Some information:
I have two different classes, "House" and "Treasury".
They are both inside the same NSMutableArray called "structures".
House has a (int) variable called "ownership".
I use a for loop (100 loops) to create houses and treasuries across an area.
Then I have another loop that loops through "structures" and assigns an "ownership" integer to it.
In that loop I use for(Houses *h in structures) but for some reason the loop also loops through the "treasury"s in structures as well.
Treasury has no ownership variable though and so I get that error telling me that "setOwnership:" does not exist.
I am also using Cocos2D but that shouldn't matter.
Here is what the code looks like:
// Variable
NSMutableArray *structures;
-(void) InitializeStructures
{
structures = [[NSMutableArray alloc]init];
for(int i = 0; i < initialColonies; i++)
{
House *h = [[House alloc]initWithFile:#"House.png"];
h.position = [self ReturnPositionOnMap]; // Returns a point in playing area
Treasury *t = [[Treasury alloc]initWithFile:#"Treasury.png"];
t.position = [self ReturnFarPointNearOrigin:h.position];
[structures addObject:h];
[self addChild:h z:1];
[structures addObject:t];
[self addChild:t z:1];
}
}
-(void) AssignOwnerships
{
for(House *h in structures)
{
// Simplified to only show where the error occurs.
h.ownership = [self ReturnID]; // Error occurs here.
// The error ONLY occurs when it is iterating through a Treasury.
}
}
Structure:
#import "CCSprite.h"
#import "ImportedGoods.h"
#interface Structure : CCSprite
{
int _integrity;
int _ID;
bool _occupied;
int _occupiedTimeLeft;
int _occupiedTimeMax;
Faction _faction;
}
#property(nonatomic, assign) int integrity;
#property(nonatomic, assign) int ID;
#property(nonatomic, assign) bool occupied;
#property(nonatomic, assign) int occupiedTimeLeft;
#property(nonatomic, assign) int occupiedTimeMax;
#property(nonatomic, assign) Faction faction;
#end
#import "Structure.h"
#implementation Structure
#synthesize integrity = _integrity;
#synthesize ID = _ID;
#synthesize occupied = _occupied;
#synthesize occupiedTimeLeft = _occupiedTimeLeft;
#synthesize occupiedTimeMax = _occupiedTimeMax;
#synthesize faction = _faction;
#end
House:
#import "Structure.h"
#import "ImportedGoods.h"
#interface House : Structure
{
int _ownership;
}
#property(nonatomic, assign) int ownership;
#end
#import "House.h"
#implementation House
#synthesize ownership = _ownership;
#end
Treasury:
#import "Structure.h"
#interface Treasury : Structure
{
int _storedWood;
int _storedWater;
int _storedStone;
int _storedFood;
}
#property(nonatomic, assign) int storedWood;
#property(nonatomic, assign) int storedWater;
#property(nonatomic, assign) int storedStone;
#property(nonatomic, assign) int storedFood;
#end
#import "Treasury.h"
#implementation Treasury
#synthesize storedFood = _storedFood;
#synthesize storedWood = _storedWood;
#synthesize storedStone = _storedStone;
#synthesize storedWater = _storedWater;
#end
This is the error:
2011-11-07 18:45:29.016 Virtual World[788:10a03] -[Treasury setOwnership:]: unrecognized selector sent to instance 0x7498cc0
2011-11-07 18:45:29.022 Virtual World[788:10a03] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Treasury setOwnership:]: unrecognized selector sent to instance 0x7498cc0'
*** First throw call stack:
(0x17fb052 0x198cd0a 0x17fcced 0x1761f00 0x1761ce2 0xcbe33 0xc2193 0xc1e5f 0xc1a34 0x3fc81 0xc185e 0x176151d 0x1761437 0x39b25 0x36ee2 0x17fcec9 0x91f91 0x92adf 0x94991 0x869a30 0x869c56 0x850384 0x843aa9 0x27affa9 0x17cf1c5 0x1734022 0x173290a 0x1731db4 0x1731ccb 0x27ae879 0x27ae93e 0x841a9b 0xc07ef 0x20c5 0x1)
terminate called throwing an exception(gdb)
I know that I can just make a different NSMutableArray called "treasuries" but I'd like to keep everything in one array if possible.
I want to know why it still iterates through treasuries even though I specified to iterate through "House *h in structures".
If you need any additional information comment below and I will add.
Thanks!
When you use fast enumeration in Objective-C, which is the syntax:
for (MyClass *item in someArray) {
...
}
What you're doing is looping over every item in the array, treating each item as a pointer to a MyClass object, whether that's what the item actually is or not. It does not do what you think it does, which is only iterate over the items in the array that are of the type you declare in your loop.
What you should probably do is store your House and Treasury items in separate arrays. Do you have a specific reason for putting them in the same structure?
If you really want to store them together, you can use:
for (id item in structures) {
if ([item isKindOfClass:[House class]]) {
House *house = (House *) item;
[house setOwnership:...];
} else {
continue;
}
}
Your assumption that
for(House *h in structures)
{
// Simplified to only show where the error occurs.
h.ownership = [self ReturnID]; // Error occurs here.
// The error ONLY occurs when it is iterating through a Treasury.
}
will only pick the House objects from the array is wrong. You will get every object from the array. House *h in structures tells the compiler that array is full of House objects.
You should change it to
for (id h in structures){
// Simplified to only show where the error occurs.
if ([h respondsToSelector:#selector(setOwnership:)]){
h.ownership = [self ReturnID];
}
}

iOS: add new cell to tableview from another view

I was wondering what is the best way to go about adding a new cell to a tableview in iOS. Let's say I have a firstviewcontroller and a secondviewcontroller. On the firstviewcontroller I have a tableview already populated with some data, I also have a navigation bar with an add button on the top. Tapping the add button will present a new view and then I want to pass data from that secondviewcontroller to firstviewcontroller and populate my tableview with it.
Thanks,
Sam
You secondViewController should create a delegate protocol. Your firstViewController should then be assigned as its delegate.
Once secondViewController saves the data it calls a method that your firstViewController should implement
A good exemple here:
How do I create delegates in Objective-C?
To get you started: secondViewController.h
#protocol secondViewControllerDelegate;
#interface secondViewController : UIViewController{
id<secondViewControllerDelegate> __unsafe_unretained delegate;
}
#property (nonatomic, unsafe_unretained) id<secondViewControllerDelegate> delegate;
#end
#protocol secondViewControllerDelegate <NSObject>
- (void)dataSaved;
#end
You can add a new class with tableView data source. initiate it with nesessary data (from both View controllers. use delegate to cooperate them) and after anu data chaging call [tableView setDataSource:]:
// DataSourceAtoZ.h
#import <Foundation/Foundation.h>
#import "MallsViewController.h"
#interface DataSourceCategory : NSObject <UITableViewDataSource> {
NSMutableArray *data;
UITableView *tableView;
}
#property (nonatomic, retain) NSMutableArray *data;
- (id)initWithData:(NSMutableArray *)d;
#end
then, anywhere in your code, compose data you wish to be in tableView and set dataSource:
NSMutableArray *dt = [[NSMutableArray alloc] init];
for (int i = 0; i < [categories count]; i++) {
NSMutableArray *names = [[NSMutableArray alloc] init];
[names addObject:[[categories objectAtIndex:i] objectAtIndex:0]];
for (int j = 1; j < [[categories objectAtIndex:i] count]; j++) {
NSRange match = [[[categories objectAtIndex:i] objectAtIndex:j] rangeOfString:[params objectAtIndex:0]];
if (match.length != 0) {
[names addObject:[[categories objectAtIndex:i] objectAtIndex:j]];
}
}
[dt addObject:names];
[names release];
}
dsCategory = [[DataSourceCategory alloc] init];
dsCategory = [dsCategory initWithData:dt];
[dt release];
You should create your arrays in the App delegate and then call them and change them however you want from there..
MyAppDelegate *appDelegate = (MyAppDelegate*)[[UIApplication sharedApplication] delegate];
once you have this line you can connect between two classes and call any methods on the delegate for example:
[appDelegate populateMyArray];
you don't add "new cells" like you described it, you use the same cells and populate them with different data.

Pass parameter when initializing table

Okay, I'm totally stumped here.
This works in CouponListViewController.m:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.couponList = [CouponDatabase database].couponList;
self.title = #"Coupon List";
}
And this works in CouponDetailViewController.m:
- (void)viewWillAppear:(BOOL)animated {
CouponDetails *details = [[CouponDatabase database] couponDetails:_uniqueId];
if (details != nil) {
[_merchantNameLabel setText:details.merchantName];
[_longDealLine1Label setText:details.longDealLine1];
//....blah...blah//
}
}
But when I change the CouponDatabase.h from this (which works with the above):
#class CouponDetails;
#interface CouponDatabase : NSObject {
sqlite3 *_database;
}
+ (CouponDatabase *)database;
- (NSArray *)couponList;
- (CouponDetails *)couponDetails:(int) uniqueId;
...to this (which works if I manually set the value of 'selectedCategory' inside the method):
#class CouponList;
#class CouponDetails;
#interface CouponDatabase : NSObject {
sqlite3 *_database;
}
+ (CouponDatabase *)database;
- (CouponList *)couponList:(int) selectedCategory;
- (CouponDetails *)couponDetails:(int) uniqueId;
and then change CouponListViewController.m to this:
1 - (void)viewWillAppear:(BOOL)animated {
2 [super viewWillAppear:animated];
3 self.couponList = [[CouponDatabase database] couponList:_selectedCategory];
4 self.title = #"Coupon List";
5 }
I get this error on line 3 above:
warning: incompatible Objective-C types 'struct CouponList *',
expected 'struct NSArray *' when passing argument 1 of 'setCouponList:'
from distinct Objective-C type
Question: What is the proper formatting of the 'self.couponlist' line so that I can pass an integer to the CouponDatabase for use in the couponList method?
EDIT: I'm aware that couponDetails is now a class instead of an array - I just don't know know how to format the line to initialize the table data.
I hope this makes sense - any help on this would be very greatly appreciated.
Thanks in advance!
Adding CouponListViewController.h:
#import <UIKit/UIKit.h>
#class CouponDetailsViewController;
#interface CouponListViewController : UITableViewController {
NSArray *_couponList;
CouponDetailsViewController *_couponDetails;
int _selectedCategory;
}
#property (nonatomic, retain) NSArray *couponList;
#property (nonatomic, retain) CouponDetailsViewController *couponDetails;
#property(nonatomic, assign) int selectedCategory;
#end
Try changing your CouponListViewController.h to this:
#import <UIKit/UIKit.h>
#class CouponDetailsViewController;
#interface CouponListViewController : UITableViewController {
CouponList *_couponList;
CouponDetailsViewController *_couponDetails;
int _selectedCategory;
}
#property (nonatomic, retain) CouponList *couponList;
#property (nonatomic, retain) CouponDetailsViewController *couponDetails;
#property(nonatomic, assign) int selectedCategory;
#end
Oops I put my response in my own original post and should have put it here:
Edit: Okay, I made changes to CouponListViewController.h as recommended by Robert, plus added #class CouponList; as follows:
#import <UIKit/UIKit.h>
#class CouponList;
#class CouponDetailsViewController;
#interface CouponListViewController : UITableViewController {
CouponList *_couponList;
CouponDetailsViewController *_couponDetails;
int _selectedCategory;
}
#property (nonatomic, retain) CouponList *couponList;
#property (nonatomic, retain) CouponDetailsViewController *couponDetails;
#property(nonatomic, assign) int selectedCategory;
#end
I'm still getting errors in CouponListViewController.m:
#import "CouponListViewController.h"
#import "CouponDatabase.h"
#import "CouponList.h"
#import "CouponDetailsViewController.h"
#implementation CouponListViewController
#synthesize couponList = _couponList;
#synthesize couponDetails = _couponDetails;
#synthesize selectedCategory = _selectedCategory;
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.couponList = [CouponDatabase database].couponList; // <--- ERROR 1
self.title = #"Coupon List";
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [_couponList count]; // <--- WARNINGS 1 AND 2
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (self.couponDetails == nil) {
self.couponDetails = [[[CouponDetailsViewController alloc] initWithNibName:#"CouponDetailsViewController" bundle:nil] autorelease];
}
CouponList *info = [_couponList objectAtIndex:indexPath.row]; // <--- WARNING 3
NSLog(#"%#", info.uniqueId);
_couponDetails.uniqueId = info.uniqueId;
[self.navigationController pushViewController:_couponDetails animated:YES];
}
ERROR 1: request for member 'couponList' in something not a structure or union
WARNING 1: 'CouponList' may not respond to '-count'
WARNING 2: return makes integer from pointer without a cast
WARNING 3: 'CouponList' may not respond to '-objectAtIndex:'
In you original code for CouponDatabase, you are changing the definition:
- (NSArray *)couponList;
for this one:
- (CouponList *)couponList:(int) selectedCategory;
Nevertheless, you use that return value as datasource for a list view controller, so . Here you have a mismatch you should fix. How to fix it depends on the semantics of your application. What are your trying to do with - (CouponList *)couponList:(int) selectedCategory;? What does really return this selector? What is the interface CouponList? Possibly you should change the line:
self.couponList = [[CouponDatabase database] couponList:_selectedCategory];
so that it returns an NSArray build from a CouponList. But I am not sure of the semantics of your objects, so this might not be the case.

NSMutableArray not pass value to CellForRowAtIndexPath?

I can put value into array and here is my code and prob.
Search.h
#interface SearchKeyword : UIViewController {
UITableView * newsTable;
UILabel * waitLabel;
UIActivityIndicatorView *activityIndicator;
UIView * backView;
NSMutableArray *jsonKanji;
}
#property (nonatomic, retain) IBOutlet UITableView * newsTable;
#property (nonatomic, retain) IBOutlet UILabel * waitLabel;
#property (nonatomic, retain) IBOutlet UIActivityIndicatorView * activityIndicator;
#property (nonatomic, retain) IBOutlet UIView * backView;
- (UITableViewCell *) getCellContentView:(NSString *)cellIdentifier;
#end
and here is Search.m
- (void)viewDidAppear:(BOOL)animated{
...
jsonKanji = [NSMutableArray arrayWithArray:(NSArray *)[jsonDict valueForKey:#"kanji_name"]];
...
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"jsonkanji 0 %#",[jsonKanji objectAtIndex:0]);
return [jsonKanji count];
}
Here is result "jsonkanji 0 Japan" that correct and If I change objAtindex=1 It show "jsonkanji 1 England" that's correct too.
But when I go to this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"jsonkanji 0 %#",[jsonKanji objectAtIndex:1]);
...
return cell;
}
It's crash !! plase help me explain what happen ? And it show only "EXC_BAD_ACCESS" #main.m
You have a memory management issue. [NSMutableArray arrayWithArray:] gives you an autoreleased object, as per Apple's memory management guidelines.
In your first test, you're checking the value at some point before the object is dealloc'd. By the time the delegate call from the table view has arrived the object has been dealloc'd, and the memory no longer exists.
You need to make sure to retain the array when you create it (and release it when you are finished with it).
You can do this explicitly:
- (void)viewDidAppear:(BOOL)animated{
...
jsonKanji = [[NSMutableArray arrayWithArray:(NSArray *)[jsonDict valueForKey:#"kanji_name"]] retain];
...
}
Or create a property and assign the value using the property, which will handle the retain itself:
(interface)
#interface SearchKeyword : UIViewController {
....
#property (nonatomic, retain) INSMutableArray *jsonKanji;
...
#end
(implementation)
- (void)viewDidAppear:(BOOL)animated{
...
self.jsonKanji = [NSMutableArray arrayWithArray:(NSArray *)[jsonDict valueForKey:#"kanji_name"]];
...
}
NSMutableArray arrayWithArray: is autoreleased. You need to retain it.
You need to retain the NSMutable array, try creating a property for the array.
Add the following to your .h file
#property (nonatomic, retain) NSMutableArray *jsonKanji;
Then #synthesize the jsonKanji in the .m file.
And change the loading of the array to:
- (void)viewDidAppear:(BOOL)animated{
...
self.jsonKanji = [NSMutableArray arrayWithArray:(NSArray *)[jsonDict valueForKey:#"kanji_name"]];
...
}