I have a problem.
This is my code.
When i try to use the IBAction SavePosition the "arrayPosition" isn't update.
Else if i initialize the "arrayPosition" in "SavePosition" the value is stored in the array.
Why this anomaly?
#import <UIKit/UIKit.h>
#interface AccelerometroViewController : UIViewController <UIAccelerometerDelegate, UITextFieldDelegate, UIAlertViewDelegate>{
//.....
NSMutableArray *arrayPosizioni;
NSMutableArray *arrayPosizioniCorrenti;
NSString *nomePosizioneCorrente;
}
-(IBAction)salvaPosizione;
//...
#property (nonatomic, assign) NSMutableArray *arrayPosizioni;
#property (nonatomic, assign) NSMutableArray *arrayPosizioniCorrenti;
#property (nonatomic, assign) NSString *nomePosizioneCorrente;
#end
#import "AccelerometroViewController.h"
#import "Position.h"
#implementation AccelerometroViewController
float actualX;
float actualY;
float actualZ;
#synthesize arrayPosition;
#synthesize arrayCurrentPosition;
#synthesize nameCurrentPosition;
-(id)init {
self = [super init];
if (self != nil) {
arrayPosition = [[NSMutableArray alloc]init];
arrayCurrentPosition = [[NSMutableArray alloc]init];
nameCurrentPosition = [NSString stringWithFormat:#"noPosition"];
actualX = 0;
actualY = 0;
actualZ = 0;
}
return self;
}
-(void)updateTextView:(NSString*)nomePosizione
{
NSString *string = [NSString stringWithFormat:#"%#", nameCurrentPosition];
textEvent.text = [textEvent.text stringByAppendingString:#"\n"];
textEvent.text = [textEvent.text stringByAppendingString:string];
}
-(IBAction)savePosition{
Posizione *newPosition;
newPosition = [[Position alloc]init];
if([newPosition setValue:(NSString*)fieldNomePosizione.text:(float)actualX:(float)actualY:(float)actualZ]){
//setValue is a method of Position. I'm sure that this method is correct
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Salvataggio Posizione" message:#"Posizione salvata con successo" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:nil];
[alert show];
[alert release];
[arrayPosition addObject:newPosition];
}
else{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Salvataggio osizione" message:#"Errore nel salvataggio" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:nil];
[alert show];
[alert release];
}
}
Whats going on?
I bet you're creating your view controller inside a xib file?
If you set a breakpoint inside your init method on the line
arrayPosition = [[NSMutableArray alloc]init];
I bet it never runs. This means that when you get to the line
[arrayPosition addObject:newPosition];
arrayPosition is still nil so nothing happens.
How to fix it?
If you're initializing a UIViewController it's either called inside initWithNibName:bundle: if you've created it in code or in initWithCoder: if it's created inside a xib file.
You need to do something like this :
- (void) initialise {
arrayPosition = [[NSMutableArray alloc] init];
arrayCurrentPosition = [[NSMutableArray alloc] init];
nameCurrentPosition = #"noPosition";
actualX = 0;
actualY = 0;
actualZ = 0;
}
- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle {
if (self = [super initWithNibName:nibName bundle:bundle]) {
[self initialise];
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
if (self = [super initWithCoder:decoder]) {
[self initialise];
}
return self;
}
This will call initailise regardless of how the view controller is created.
This:
[newPosition setValue:(NSString*)fieldNomePosizione.text:(float)actualX:(float)actualY:(float)actualZ]
... is gibberish. I don't even see how it compiles. I assume its a typo. However, if the function does not return a boolean it will return a void pointer and always evaluate to false so the block is never called.
More generally, your problem is most likely that you are not using the self.propertyName notation to refer to your properties so they are not being retained. E.g.
[arrayPosition addObject:newPosition];
should be:
[self.arrayPosition addObject:newPosition];
... as should all other references to arrayPosition in the code.
Related
Actually I have parsed an XML and store URL's of images as an NSMutableArray object, but I want this array to be used in another ViewController (to give to UIImage in UIImageView to show Images at runtime), so I am trying to copy that Mutable array to myAppDelegate_iPhone's NSMutableArray. And I want to again copy that Appdelegate's array to my next or other ViewControllers NSMutableArray.
so can anyone help me out pleaseeeeee? Here is my code :-
code:-
#class FirstViewController;
#interface AppDelegate_iPhone : NSObject <UIApplicationDelegate> {
UIWindow *window;
FirstViewController *viewController;
NSMutableArray *logoArray;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) NSMutableArray *logoArray;
#end
#import "AppDelegate_iPhone.h"
#import "FirstViewController.h"
#import "ParsingViewController.h"
#implementation AppDelegate_iPhone
#synthesize window,logoArray;
#pragma mark -
#pragma mark Application lifecycle
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
viewController = [[FirstViewController alloc]initWithNibName:#"FirstViewController" bundle:nil];
viewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
NSURL *url = [[NSURL alloc] initWithString:#"http://litofinter.es.milfoil.arvixe.com/displayxml1.aspx"];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
//Initialize the delegate.
ParsingViewController *parser = [[ParsingViewController alloc] init];
//Set delegate
[xmlParser setDelegate:parser];
//Start parsing the XML file.
BOOL success = [xmlParser parse];
if(success)
NSLog(#"No Errors");
else
NSLog(#"Error Error Error!!!");
logoArray = [[NSMutableArray alloc]init];
[self.window addSubview:viewController.view];
[self.window makeKeyAndVisible];
return YES;
}
// dealloc done
#end
#class Litofinter,AppDelegate_iPhone;
#interface ParsingViewController : NSObject<NSXMLParserDelegate> {
NSString *myString;
NSMutableArray *myMutableArray;
Litofinter *obj;
NSString *currentElement;
AppDelegate_iPhone *appDelegate;
}
#import "ParsingViewController.h"
#import "Litofinter.h"
#import "AppDelegate_iPhone.h"
#implementation ParsingViewController
#synthesize myMutableArray, myString;
-(id)init{
if(self == [super init]){
myMutableArray = [[NSMutableArray alloc] init];
}
return self;
}
- (void)parserDidStartDocument:(NSXMLParser *)parser
{
//myMutableArray = [[NSMutableArray alloc]init];
}
// Parsing done here
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
appDelegate = (AppDelegate_iPhone *)[[UIApplication sharedApplication] delegate];
//UIApplication *app = [UIApplication sharedApplication];
//appDelegate=app.delegate;
appDelegate.logoArray = [[NSMutableArray alloc]initWithArray:myMutableArray];
NSLog(#"appDelegate.logoArray count %d",[appDelegate.logoArray count]);
for (Litofinter *lito in appDelegate.logoArray) {
NSLog(#"Array Elements :----- %#",lito.cLogo);
}
}
#end
#import <UIKit/UIKit.h>
#class AppDelegate_iPhone,Litofinter,ParsingViewController;
#interface FirstViewController : UIViewController {
NSMutableArray *array;
//Litofinter *lito;
NSString *logoString;
AppDelegate_iPhone *appDelegate;
ParsingViewController *obj;
}
#end
#import "FirstViewController.h"
#import "AppDelegate_iPhone.h"
#import "Litofinter.h"
#import "ParsingViewController.h"
#implementation FirstViewController
-(id)init{
if(self == [super init]){
obj = [[ParsingViewController alloc] init];
array = [[NSArray alloc] initWithArray: obj.myMutableArray];
}
return self;
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
int x=5,y=10;
appDelegate = (AppDelegate_iPhone *)[[UIApplication sharedApplication] delegate];
// UIApplication *app = [UIApplication sharedApplication];
// appDelegate=app.delegate;
NSLog(#"delegate Array ====== %d",[appDelegate.logoArray count]);
NSLog(#"New Array ====== %d",[obj.myMutableArray count]);
/*
array = [[NSMutableArray alloc]initWithArray:appDelegate.logoArray];
NSLog(#"array at 0 ===== %#",[array objectAtIndex:0]);
for (Litofinter *lito1 in obj.myMutableArray) {
NSLog(#"Array Elements in Lito1 are :------------- %#",lito1.cLogo);
}
for (Litofinter *lito2 in array) {
NSLog(#"Array Elements in Lito1 are :------------- %#",lito2.cLogo);
}
*/
for (Litofinter *lito in obj.myMutableArray) {
//for (int i=0; i<[appDelegate.logoArray count]; i++) {
// lito.cLogo = [array objectAtIndex:i];
NSLog(#"%#",lito.cLogo);
UIImage *imageFromUrl = [UIImage imageWithContentsOfFile:[NSURL fileURLWithPath:lito.cLogo]];
UIImageView *imgView = [[UIImageView alloc] initWithImage:imageFromUrl];
[imgView setFrame:CGRectMake(x, y, 196, 90)];
[self.view addSubview:imgView];
UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(onTapImage)];
[imgView addGestureRecognizer:tgr];
// [tgr release];
//Do the rest of your operations here, don't forget to release the UIImageView
x = x + 200;
}
}
-(void)onTapImage
{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Message from mAc" message:#"Trail" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Ok",nil];
[alert show];
}
- (void)dealloc {
[super dealloc];
}
#end
You can use this.
UIImage *imageFromUrl = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:lito.cLogo]]];
I'm coding a popup screen that will show up if a the value for mulValue in the settings is nil. Here is the code:
#import "FirstViewController.h"
#implementation FirstViewController
#synthesize myHelpfile = ivHelpfile; //UIAlertView
#synthesize myAboutfile = ivAboutfile; //UIAlertView
#synthesize myNoarea = ivNoarea; //UIAlertView
#synthesize myMap = ivMap; //UIImageView
#synthesize myAreapick = ivAreapick; //UIActionSheet
#synthesize myAdvancedmode = ivAdvancedmode; //NSString
#synthesize myAreaset = ivAreaset; //NSString
#synthesize myAreaarray = ivAreaarray; //NSArray
#synthesize appSettingsViewController, settingsViewController;
- (void)viewDidLoad {
[super viewDidLoad];
self.title = #"Wildlife";
NSString *area = [[NSUserDefaults standardUserDefaults] stringForKey:#"mulValue"];
[self setMyAreaset:area];
if ([self myAreaset] == nil) { //check if any region is selected. If not, push UIActionsheet
NSArray *array = [[NSArray alloc] initWithObjects: // creating array for different regions
[NSString stringWithString:#"Region 1"],
[NSString stringWithString:#"Region 2"],
[NSString stringWithString:#"Region 3"],
[NSString stringWithString:#"Region 4"],
[NSString stringWithString:#"Region 5"],
[NSString stringWithString:#"Region 6"],nil];
[self setMyAreaarray:array];
[array release], array = nil;
NSLog(#"Built areaselectArray");
NSLog(#"Values of areaselectArray are %#",[self myAreaarray]);
UIActionSheet *areaselect = [[UIActionSheet alloc] initWithTitle:#"Select your current area" //creation of popup Area Selection
delegate:self
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
[self setMyAreapick:areaselect];
[areaselect release], areaselect = nil;
int countarray = [[self myAreaarray] count];
for (int i = 0; i < countarray; i++) { //building list from array
[[self myAreapick] addButtonWithTitle:[[self myAreaarray] objectAtIndex:i]];
}
[[self myAreapick] addButtonWithTitle:#"Cancel"];
[self myAreapick].cancelButtonIndex = countarray;
[[self myAreapick] showInView:self.view];//show the general UIActionSheet instance
NSLog(#"Out of viewDidLoad");
}
else {
NSLog(#"Area is %#, no need for areaselectArray",area);
}
}
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger )buttonIndex
{
int countarray = [[self myAreaarray] count];
if (buttonIndex != countarray) { //cancel button is at countarray, so for anything that is not cancel, do:
NSString *area = [[self myAreaarray] objectAtIndex:(buttonIndex)];
[self setMyAreaset:area];
[[NSUserDefaults standardUserDefaults] setObject:[self myAreaset] forKey:#"mulValue"];
[[NSUserDefaults standardUserDefaults] synchronize]; //sync
NSLog(#"Released areaselectArray");
}
else {
}
}
And in my FirstViewController.h I have:
#interface FirstViewController : UIViewController <UIActionSheetDelegate, IASKSettingsDelegate, UIAlertViewDelegate> {
UIAlertView *ivHelpfile;
UIAlertView *ivAboutfile;
UIAlertView *ivNoarea;
UIActionSheet *ivAreapick;
UIImageView *ivMap;
NSString *ivAdvancedmode;
NSString *ivAreaset;
NSArray *ivAreaarray;
}
#property(nonatomic, retain) UIAlertView *myHelpfile;
#property(nonatomic, retain) UIAlertView *myAboutfile;
#property(nonatomic, retain) UIAlertView *myNoarea;
#property(nonatomic, retain) UIActionSheet *myAreapick;
#property(nonatomic, retain) UIImageView *myMap;
#property(nonatomic, copy) NSString *myAdvancedmode;
#property(nonatomic, copy) NSString *myAreaset;
#property(nonatomic, retain) NSArray *myAreaarray;
When I run my app in the simulator with Instruments running, I get a memory leak whenever I scroll the list of rows (as built by [self myAreaarray]) and release my finger. The weird thing is, it has not really done anything else at that point. The main view is loaded, but it would be strange that that would cause a memory leak based on scrolling through the list.
The leaks I get in Instruments are the following:
_NSCFType 48 bytes CoreGraphics CGTypeCreateInstanceWithAllocator
UIDeviceWhiteColor 16 bytes UIKit +[UIColor allocWithZone:]
When I scroll through the list again, more of those errors show up. It looks like I'm allocating something and not releasing it (while I'm scrolling the list?), but I can't find it at this point.
Any help would be appreciated!
I'm seeing it as well, even abstracting all your app code from it:
UIActionSheet *as = [[UIActionSheet alloc] initWithTitle:#"Test" delegate:nil cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
for (int i = 0; i < 100; i++) {
[as addButtonWithTitle:[NSString stringWithFormat:#"Button %i", i]];
}
as.cancelButtonIndex = 99;
as.destructiveButtonIndex = 0;
[as showInView:self.view];
[as release];
When running through Instruments memory leak profiler, each display of the action sheet yieds 6 UIDeviceWhiteColor leaks and 4 CGColor leaks. Looks to me like this is a bug in UIKit.
I am using a custom class to display some info on a table view.
The problem is that as long as I scroll the tableview memory is leaking...
I guess I have something wrong at my class.
Please have a look:
#interface Person : NSObject {
NSString *name;
NSString *surname;
NSString *address;
NSString *email;
}
#property (nonatomic, copy) NSString *name, *surname, *address, *email;
#implementation Person
#synthesize name, surname, address, email;
-(id)init {
[super init];
name = [[NSString alloc] init];
surname = [[NSString alloc] init];
address = [[NSString alloc] init];
email = [[NSString alloc] init];
return self;
}
- (void)dealloc
{
[name release];
[surname release];
[address release];
[email release];
[super dealloc];
}
#import "Person.h"
#interface Group : NSObject {
NSString *groupTitle;
NSMutableArray *persons;
}
#property (readwrite, copy) NSString *groupTitle;
- (void)addPerson:(Person *)person;
- (void)removeAll;
- (NSArray *)getPersons;
- (int)PersonsCount;
#end
#implementation Group
#synthesize groupTitle;
-(id)init {
[super init];
persons = [[NSMutableArray alloc] init];
return self;
}
-(void)addPerson:(Person *)person {
[persons addObject:person];
}
-(void)removeAll {
[persons removeAllObjects];
}
-(NSArray *) getPersons {
return [persons copy];
[persons release];
}
-(int)personsCount {
return [persons count];
}
-(void)dealloc {
[groupTitle release], groupTitle = nil;
[persons release], persons = nil;
[super dealloc];
}
#end
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
…….
Group *groupForRow = [[Group alloc] init];
Person *personForRow = [[Person alloc] init];
personForRow = [[groupForRow getPersons] objectAtIndex:indexPath.row];
_personName = personForRow.name;
_personSurname = personForRow.surname;
_personAddress = personForRow.address;
_personEmail = personForRow.email;
[groupForRow release], groupForRow = nil;
[personForRow release], personForRow = nil;
…..
return cell
Few corrections (read the comments):
#interface Person : NSObject {
NSString *name;
NSString *surname;
NSString *address;
NSString *email;
}
// copy is OK for strings...
#property (nonatomic, copy) NSString *name, *surname, *address, *email;
#end
#implementation Person
#synthesize name, surname, address, email;
- (id)init {
if (self = [super init]) {
// There is no need to allocate the strings
// In addition, once you write 'name = [[NSStrin alloc] init];' you don't use the property.
// If you do want to use the property setter then you should write 'self.name = #"some string";'
}
return self;
}
- (void)dealloc {
[name release];
[surname release];
[address release];
[email release];
[super dealloc];
}
#end
#import "Person.h"
#interface Group : NSObject {
NSString *groupTitle;
NSMutableArray *persons;
}
// Any special reason for "readwrite" instead of "nonatomic"?
#property (readwrite, copy) NSString *groupTitle;
// This property is more important than the string:
#property (nonatomic, retain) NSMutableArray *persons;
- (void)addPerson:(Person *)person;
- (void)removeAll;
- (NSArray *)getPersons;
- (int)PersonsCount;
#end
#implementation Group
#synthesize groupTitle, persons;
- (id)init {
if (self = [super init]) {
// Use the autoreleased array instance ([NSMutableArray array]) and set it to the property setter that will retain the object:
self.persons = [NSMutableArray array];
}
return self;
}
- (void)addPerson:(Person *)person {
// I prefer using properties (the "self." in the beginning) instead of the members directly...
[self.persons addObject:person];
}
- (void)removeAll {
[self.persons removeAllObjects];
}
// I think that this getter is unnecessary - use the property instead...
- (NSArray *) getPersons {
// There is no need to copy
return [persons copy];
// Don't you have a warning for this line? It is never executed
[persons release];
}
- (int)personsCount {
return [self.persons count];
}
- (void)dealloc {
[groupTitle release], groupTitle = nil;// The "groupTitle = nil" is unnecessary.
[persons release], persons = nil;// The "persons = nil" is unnecessary.
[super dealloc];
}
#end
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
…….
Group *groupForRow = [[Group alloc] init];// Do you REALLY have to allocate this object each "cellForRowAtIndexPath"??
Person *personForRow = [[Person alloc] init];// Get rid of the "= [[Person alloc] init]" - this is a leak (because of the next line)
personForRow = [[groupForRow getPersons] objectAtIndex:indexPath.row];// If you will use the property persons instead of the "getPersons" (that copies the array) then you will get rid of another leak
// What are these?
_personName = personForRow.name;
_personSurname = personForRow.surname;
_personAddress = personForRow.address;
_personEmail = personForRow.email;
// The " = nil" is unnecessary here...
[groupForRow release], groupForRow = nil;// If you won't allocate the group then you won't need this line...
[personForRow release], personForRow = nil;// NSZombie - you release object that you don't owe (do you have crashes, that you don't know why they are happen?)
…..
return cell;
}
There is a lot wrong here, please delve a little into objective-C to get a grasp of the use of #property and #synthesize to get correctly functioning getter/setter methods.
As for your memory leak when scrolling, it is caused by the allocs in cellForRowAtIndexPath which are not balanced by either a release or an autorelease.
This:
Group *groupForRow = [[[Group alloc] init] autorelease];
Person *personForRow = [[[Person alloc] init] autorelease];
should fix most of your leaks. Browse around on SO for more info.
I have a problem.
I try to initialize a variabile in a classViewController created inside a xib file.
I try with the code below but when i append a object to array, these array isn't initialized.
Can you help me?
thanks and sorry for my english.
#import <UIKit/UIKit.h>
#interface AccelerometroViewController : UIViewController <UIAccelerometerDelegate, UITextFieldDelegate, UIAlertViewDelegate>{
//.....
NSMutableArray *arrayPosizioni;
NSMutableArray *arrayPosizioniCorrenti;
NSString *nomePosizioneCorrente;
}
-(IBAction)salvaPosizione;
//...
#property (nonatomic, assign) NSMutableArray *arrayPosizioni;
#property (nonatomic, assign) NSMutableArray *arrayPosizioniCorrenti;
#property (nonatomic, assign) NSString *nomePosizioneCorrente;
#end
#import "AccelerometroViewController.h"
#import "Position.h"
#implementation AccelerometroViewController
float actualX;
float actualY;
float actualZ;
#synthesize arrayPosition;
#synthesize arrayCurrentPosition;
#synthesize nameCurrentPosition;
-(id)init {
self = [super init];
if (self != nil) {
arrayPosition = [[NSMutableArray alloc]init];
arrayCurrentPosition = [[NSMutableArray alloc]init];
nameCurrentPosition = [NSString stringWithFormat:#"noPosition"];
actualX = 0;
actualY = 0;
actualZ = 0;
}
return self;
}
-(void)updateTextView:(NSString*)nomePosizione
{
NSString *string = [NSString stringWithFormat:#"%#", nameCurrentPosition];
textEvent.text = [textEvent.text stringByAppendingString:#"\n"];
textEvent.text = [textEvent.text stringByAppendingString:string];
}
-(IBAction)savePosition{
Posizione *newPosition;
newPosition = [[Position alloc]init];
if([newPosition setValue:(NSString*)fieldNomePosizione.text:(float)actualX:(float)actualY:(float)actualZ]){
//setValue is a method of Position. I'm sure that this method is correct
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Salvataggio Posizione" message:#"Posizione salvata con successo" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:nil];
[alert show];
[alert release];
[arrayPosition addObject:newPosition];
}
else{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Salvataggio osizione" message:#"Errore nel salvataggio" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:nil];
[alert show];
[alert release];
}
}
- (void) initialise {
arrayPosition = [[NSMutableArray alloc] init];
arrayCurrentPosition = [[NSMutableArray alloc] init];
nameCurrentPosition = #"noPosition";
actualX = 0;
actualY = 0;
actualZ = 0;
}
- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle {
if (self = [super initWithNibName:nibName bundle:bundle]) {
[self initialise];
}
}
In addition to Felix's comment regarding the mis-naming, your properties are wrong too. Objects need to be retained or copied, not assigned (in most cases) so that you're certain their value won't go away. You need to have ownership of them. As such I would use the following:
#property (nonatomic, readwrite, retain) NSMutableArray *arrayPosition;
#property (nonatomic, readwrite, retain) NSMutableArray *arrayCurrentPosition;
#property (nonatomic, readwrite, copy) NSString *nameCurrentPosition;
Then, since you've retained something you're responsible for releasing it. As such you'll need a dealloc method to do that.
-(void)dealloc {
self.arrayPosition = nil;
self.arrayCurrentPosition = nil;
self.nameCurrentPosition = nil;
[super dealloc];
}
Afternoon all,
I tried to add a second data entity to the persistent store in the (locations) coredata tutorial code, and then access this in a new view. I think that I've followed the tutorial, and checked that I'm doing a clean build etc, but can't see what to change to prevent it crashing.
I'm afraid I'm at my wits end with this one, and can't seem to find the step that I've missed. I've pasted the header and code files below, please let me know if I need to share any more of the code. The crash seems to happen on the line:
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Album" inManagedObjectContext:[self managedObjectContext]];
There is one other line in the code that refers to galleryviewcontroller at the moment, and that's in the main application delegate:
galleryViewController.managedObjectContext = [self managedObjectContext];
GalleryViewController.h
#import <UIKit/UIKit.h>
#interface GalleryViewController : UIViewController {
NSManagedObjectContext *managedObjectContext;
int rowNumber;
IBOutlet UILabel *lblMessage;
UIBarButtonItem *addButton;
NSMutableArray *imagesArray;
}
#property (readwrite) int rowNumber;
#property (nonatomic,retain) UILabel *lblMessage;
#property (nonatomic,retain) NSMutableArray *imagesArray;
#property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
#property (nonatomic, retain) UIBarButtonItem *addButton;
-(void)updateRowNumber:(int)theIndex;
-(void)addImage;
#end
GalleryViewController.m
#import "RootViewController.h"
#import "LocationsAppDelegate.h"
#import "Album.h"
#import "GalleryViewController.h"
#import "Image.h"
#implementation GalleryViewController
#synthesize lblMessage,rowNumber,addButton,managedObjectContext;
#synthesize imagesArray;
/*
// The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
// Custom initialization
}
return self;
}
*/
-(void)updateRowNumber:(int)theIndex{
rowNumber=theIndex;
LocationsAppDelegate *mainDelegate =(LocationsAppDelegate *)[[UIApplication sharedApplication] delegate];
Album *anAlbum = [mainDelegate.albumsArray objectAtIndex:rowNumber];
lblMessage.text = anAlbum.uniqueAlbumIdentifier;
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(addImage)];
addButton.enabled = YES;
self.navigationItem.rightBarButtonItem = addButton;
/* Found this in another answer, adding it to the code didn't help.
if (managedObjectContext == nil) {
managedObjectContext = [[[UIApplication sharedApplication] delegate] managedObjectContext];
}
*/
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Album" inManagedObjectContext:[self managedObjectContext]];
[request setEntity:entity];
// Order the albums by creation date, most recent first.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"imagePath" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptor release];
[sortDescriptors release];
// Execute the fetch -- create a mutable copy of the result.
NSError *error = nil;
NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
if (mutableFetchResults == nil) {
// Handle the error.
}
[self setImagesArray:mutableFetchResults];
int a = 5;
int b = 10;
for( int i=0; i<[imagesArray count]; i++ )
{
if( a == 325 )
{
a = 5;
b += 70;
}
UIImageView *any = [[UIImageView alloc] initWithFrame:CGRectMake(a,b,70,60)];
any.image = [imagesArray objectAtIndex:i];
any.tag = i;
[self.view addSubview:any];
[any release];
a += 80;
}
}
-(void)addImage{
NSString *msg = [NSString stringWithFormat:#"%i",rowNumber];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Add image to" message:msg
delegate:self cancelButtonTitle:#"No" otherButtonTitles:#"Yes", nil];
[alert show];
[alert release];
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
[super viewDidUnload];
}
- (void)dealloc {
[lblMessage release];
[managedObjectContext release];
[super dealloc];
}
#end
It helps to post the error you are getting.
Have you tried the following:
Clean build of your project
Resetting the simulator to remove the older sqlite data file
If neither of those solve the issue then post the error you are getting as an update to your question.
update
The information I was looking for would be printing out in the console, while the debugger is an infinitely useful tool and I recommend learning it, in this case your issue would have been resolved by reviewing the console output of your application.