IOS: NSMutableArray in Viewdidload - xcode

in my project I use a NSmutablearray that I fill with UIImageView in .m (viewDidLoad)
arrayView = [[NSMutableArray alloc] initWithObjects: image1, image2, image3, nil];
but in method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
when I write
int i = 1;
[[arrayView objectAtIndex:i] setImage:image];
there is an exception that say that my array is empty...why?

Please post the rest of viewDidLoad. I want to see how image1 is initialized. The line:
arrayView = [[NSMutableArray alloc] initWithObjects: image1, image2, image3, nil];
will return an empty array if image1 is nil. You should also protect your app from crashing by not making assumptions about the data source. You shouldn't crash if the array is empty, just display an empty tableView.
[EDIT]
I just read the last comment you made in the other answer. Sounds like your imageViews are created in IB. Make sure they are connected to the image1 etc outlets in IB.

Try this instead:
if (i < [arrayView count]) {
UIImageView *imageView = [arrayView objectAtIndex:i];
imageView.image = image;
}
Separating accessing the array element (by assigning it to an actual UIImageView object) and then assigning the new image may be helpful. I've seen cases where if you stack up too many operations things get confused, especially if you are dealing with objects of different types that may or may not have the selectors you're using.
Why your array is turning up empty is another issue. Initializing it in viewDidLoad seems right. You may need to add some "protection" (as above) in your table methods to avoid accessing an empty array. Then in method like viewWillAppear:, call reloadData.

Related

NSTableView - how can I identify the name of the image in an NSTableCellView?

I have a NSTableCellView that has a simple NSTextField and an NSImageCell.
NSTableCellView *cell = [tableView makeViewWithIdentifier:#"List" owner:self];
cell.textField.stringValue = name;
cell.imageView.image = [NSImage imageNamed:#"image1.png"]; (or image 2,3, etc)
Later, when I select a row from the table, I'd like to be able to see the name of the image. If I preload the image from IB, I can use:
NSTableColumn *column = [self.tableView tableColumnWithIdentifier:#"List"];
NSCell *cell = [column dataCellForRow:row];
NSLog(#"TableView image:%#",cell.image.name);
This shows the IB Name - e.g. NSEveryWhere
But when I load the images at run time, the same statement results in (null).
Any help would be appreciated. Please note that this is for OS/X - however, for future use, I would appreciate iOS ideas as well. Thanks
i think you should use cell.imageView.image.name rather than logging cell.image.name

How to save integer from Singleton in an NSUserDefault to use after app is relaunched in Xcode 5?

I have a Singleton that keeps track of my "score" over all my ViewControllers, and that works great. But I want to save my "score" from my Singleton in an NSUserDefault so I can use it after the app has been relaunched. My state preservation works for everything, but keeping the current score. My Singleton looses its data when the app is closed and I understand NSUserDefault saves the data between launches. I save my "score" from my Singleton to "integer" in my NSUserDefault. I then try to display an image that is named 0.png, 1.png, 2.png and so on until 10.png. But this image is displayed as 0.png every time.
(I really hope my question isn't stupid. I have read tutorials and tried different things for a week, and this is my first question here.)
Please show me where my code goes wrong.
viewcontroller.m
//Save Singleton score to NSUserDefault integer
[super viewDidLoad];
optionsshared = [Singleton sharedSingletonManager];
integer = optionsshared.score;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setInteger:integer forKey:#"integer"];
[defaults synchronize];
// Set Image
ScoreImg.image = [UIImage imageNamed:[NSString stringWithFormat:#"%d.png", integer]];
This code works:
//Set Singleton to number from NSUserDefault in case app was terminated
optionsshared = [Singleton sharedSingletonManager];
NSUserDefaults *getObj = [NSUserDefaults standardUserDefaults];
int Number = [((NSNumber*)[getObj objectForKey:#"stars"])intValue];
optionsshared.score = Number;
[super viewDidLoad];
//Set image from number in NSUserDefaults
ScoreImg.image = [UIImage imageNamed:[NSString stringWithFormat:#"%d.png", Number]];
}

Read image name from plist syntax problem?

I'm trying to read a reference to an image file out of a plist and make the image display in a detail view. although I can do this for my table view layout, I'm having trouble doing this with my DetailViewController nib file. I'm hoping someone can help me fix the problem and explain to me where I'm going wrong. What follows with the code is my explanation of what I THINK I'm doing. If you could explain to me what I'm doing wrong as much as show me what I should be doing, I'd really appreciate it. I'm trying to learn as much as trying to make things work.
I think the problem resides in two places. The first is my didSelectRowAtIndexPath method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//Get the dictionary of the selected data source.
NSDictionary *dictionary = [[[self.localSites objectAtIndex:indexPath.section]objectForKey:#"rowData"] objectAtIndex:indexPath.row];
TableDetailViewController *controller = [[TableDetailViewController alloc] initWithNibName:#"TableDetailViewController" bundle:[NSBundle mainBundle]];
controller.title = [dictionary objectForKey:#"Location"];
controller.dText = [dictionary objectForKey:#"details"];
// THIS IS WHERE THE PROBLEM IS
NSString *tiny = [dictionary objectForKey:#"thumb"];
controller.mainImage = [UIImage imageNamed:tiny];
[self.navigationController pushViewController:controller animated:YES];
[controller release];
}
In the code above marked //THIS IS WHERE I THINK THE PROBLEM IS, What I'm trying to do is grab the reference to the image contained in string in the plist and use the reference to get the image. This approach works fine in my cellForRowAtIndexPath method where I use it to populate the left hand side of the table with thumbnail images referred to from my plist.
In the above code mainImage refers to a string I've tried to connect to a UIImageView outlet in my TableDetailViewController.xib through my TableDetailViewController.m file as below. This is where I think Problem number two is:
- (void)viewWillAppear:(BOOL)animated
{
[super viewDidLoad];
//This Bit says that the text contained in UITextView blurb is the string dText, which is used in my didSelectRowAtIndex method
blurb.text = dText;
//This is where I try to do the same thing by saying that UIImageView topImage is the NSString mainImage which I use in my didSelectRowAtIndex method
topImage.image = mainImage;
}
My Logic was that topImage is a UIImageView and mainImage is the string containing the image view which in my didSelectRowAtIndex method I pass the value of the key 'thumb' contained in my plist file.
However the above throws up warnings. Can anyone help?
Thanks for taking the time to read.
Ok, I managed to work this out. My mistake was to declare the pointer mainImage as a NSString instead of as a UIImage. I did this because in the .plist I am using the name of the image is contained within a string. I realised though that as I change this string for the .png file of the same name in my didSelectRowAtIndexPath method, by the time I'm passing it to mainImage it is no longer a string I'm passing, it's an image. Sorted! An easy mistake for a newb like me to make. Thought I should post as I'm sure I wont be the only one who makes this mistake.

componentsJoinedByString gives me EXC_BAD_ACCESS

I have an NSMutableArray i am trying to convert into a string.
Declaring my NSMutableArray...
NSMutableArray *listData;
And later inside a method...
NSString *foo = [listData componentsJoinedByString:#"|"];
NSLog(#"%#",foo);
It seems no matter what i try i keep getting EXC_BAD_ACCESS.
To make sure each element in my array was an NSString i also tried this...
NSMutableArray *mArray = [[NSMutableArray alloc] init];
for (id ln in listData) {
NSString *boo = [NSString stringWithFormat: #"%#",ln];
[mArray addObject:boo];
}
NSString *foo = [mArray componentsJoinedByString:#"|"];
NSLog(#"%#",foo);
I can manipulate my NSMutableArray by adding/deleting objects in the same method or other methods inside my class. But when i try "componentsJoinedByString" the error pops up. Does anyone have any advice or another way i can combine this array into a single NSString?
In the code you've given, there will never be an NSMutableArray for listData. At some point in your code, you'll need to create one, and presumably populate it.
Edit
Okay, so you may get into memory management problems here, so let's be a bit clearer:
You're synthesizing getters and setters for the instance variable, so it's good practice to use those to access it, they'll take care of retain and releasing appropriately.
To set listData you can simply use
self.listData = [listManage getList:[[NSUserDefaults standardUserDefaults] stringForKey:#"list_name"] list:#"LIST"];
or
[self setListData:[listManage getList:[[NSUserDefaults standardUserDefaults] stringForKey:#"list_name"] list:#"LIST"]];
if you prefer.

NSArray to Core Data items

I have an method that reads an xml file and stores the xml nodes at a certain XPath-path in an NSArray called *nodes. What I want to do is take each one of the items in the array and add it to a core data entity called Category with the attribute of "name".
I have tried a number of different ways of creating the entity but I'm not sure about the correct way to do this effectively. This is the code used to create the NSArray, any ideas on how to implement this? (ignore the NSError, I will fix this in the final version)
- (IBAction)readCategories:(id)sender
{
NSString *xmlString = [resultView string];
NSData *xmlData = [xmlString dataUsingEncoding: NSASCIIStringEncoding];
NSXMLDocument *xmlDoc = [[NSXMLDocument alloc] initWithData:xmlData options:nil error:nil];
//XPath
NSError *err=nil;
NSArray *nodes = [xmlDoc nodesForXPath:#"//member[name='description']/value/string" error:&err];
}
EDIT - My loop code
NSArray *nodes = [xmlDoc nodesForXPath:#"//member[name='description']/value/string" error:&err];
int arrayCount = [nodes count];
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSXMLElement *categoryEl;
NSString *new = [catArrayController newObject];
int i;
for (i = 0; i < arrayCount; i++)
{
[categoryEl = [nodes objectAtIndex:i]];
[new setValue:[categoryEl stringValue] forKey:#"name"];
[catArrayController addObject:new];
}
[pool release];
Here's how I'd write it:
for (NSXMLElement *categoryElement in nodes) {
NSManagedObject *newObject = [catArrayController newObject];
[newObject setValue:[categoryElement stringValue] forKey:#"name"];
[catArrayController addObject:newObject];
[newObject release];
}
First, I'm using the Objective-C 2.0 for-each syntax. This is simpler than using index variables. I eliminated i and arrayCount.
Next, I took out your NSAutoreleasePool. None of the objects in the loop are autoreleased, so it had no effect. (The newObject method returns a retained object which is, by convention, what methods with the word new in their name do) This is also why I release newObject after adding it to the array controller. Since I'm not going to be using it any more in this method, I need to release it.
Also, you had defined new (which I renamed newObject) as an NSString. Core Data objects are always either an instance of NSManagedObject or a subclass of NSManagedObject.
Your line [categoryEl = [nodes objectAtIndex:i]] won't compile. That's because the bracket syntax is used to send a message to an object. This is an assignment statement, so the bracket syntax is not needed here. (This line is also not necessary any more because of I've changed the loop to use the for-each syntax) But, for future reference, categoryEl = [nodes objectAtIndex:i]; would have worked.
What part are you having trouble with? There shouldn't be much more to it than looping through the array, creating a new managed object for each entry, and setting the correct attributes. You can create the managed object with NSEntityDescription's -insertNewObjectForEntityForName:inManagedObjectContext: method.

Resources