I'm trying to simply add objects to a mutable array but they WILL NOT insert. I'm not getting errors or anything and I can't figure out whats going on.
In my main delegate file I split an array into 4 separate strings like so.
NSArray *split=[currentParsedCharacterData componentsSeparatedByString:#"|"];
NSLog([split objectAtIndex:3]);
NSString *date=[split objectAtIndex:0];
NSString *venue=[split objectAtIndex:1];
NSString *event=[split objectAtIndex:2];
NSString *city=[split objectAtIndex:3];
I've traced out the string values and they are definitely there.
Up next I try to add these string values to mutable arrays
[self.promoTabOptionEvents.dates addObject:date];
[self.promoTabOptionEvents.venues addObject:venue];
[self.promoTabOptionEvents.event addObject:event];
[self.promoTabOptionEvents.city addObject:city];
When I check the arrays in the debugger they are empty. What am I doing wrong?
promoTabOptionEvents class looks like this
import
#interface PromoTabOptionEvents : UIViewController {
NSString *event_headline;
NSMutableArray *dates;
NSMutableArray *venues;
NSMutableArray *event;
NSMutableArray *city;
}
#property(nonatomic,retain)NSString *event_headline;
#property(nonatomic,retain)NSMutableArray *dates;
#property(nonatomic,retain)NSMutableArray *venues;
#property(nonatomic,retain)NSMutableArray *event;
#property(nonatomic,retain)NSMutableArray *city;
-(void)applyLabels;
-(id)initWithTabBar;
#end
#import "PromoTabOptionEvents.h"
#implementation PromoTabOptionEvents
#synthesize event_headline;
#synthesize dates;
#synthesize venues;
#synthesize event;
#synthesize city;
-(id) initWithTabBar {
if ([self init]) {
//this is the label on the tab button itself
//self.title = #"Tab1";
//use whatever image you want and add it to your project
self.tabBarItem.image = [UIImage imageNamed:#"events.png"];
// set the long name shown in the navigation bar
self.navigationItem.title=#"Events";
CGRect bgframe;
bgframe.size.width=320; bgframe.size.height=460;
bgframe.origin.x=0; bgframe.origin.y=0;
UIImage* bgimage = [UIImage imageNamed:#"eventsbig.png"];
UIImageView *imagebgview = [[UIImageView alloc] initWithImage: bgimage];
imagebgview.frame=bgframe;
imagebgview.contentMode=UIViewContentModeScaleAspectFit;
self.view.backgroundColor=[UIColor whiteColor];
[self.view addSubview:imagebgview];
}
return self;
}
Can you add the code where you initialize your NSMutableArray instances? I think you might have forgotten to initialise the arrays and your addObject calls are being swallowed up with no effect.
Are you instantiating the properties anywhere, and if so, have you debugged through to verify that is the case? Otherwise you may be sending messages to nil, which will have no effect. Alternatively, you may be doing the array creation after this call, which would make it look like they're not added.
Related
I have this piece of code below and I'm trying to add Objects(String elements) to an array, problem is that every time I'm out its adding's method, it goes to nil, it doesn't retain the objects.
I know I'm doing wrong, even that I already tried lot of combinations and variations, even with my own constructor _MyArray etc etc, same result... it works, but not further...
Could you help me please?
#interface ArraysModel()
#property (nonatomic, retain) NSMutableArray *MyArray;
#end
#implementation ArraysModel
#synthesize MyArray;
-(void)AddObjectToTheList:(NSString *)object {
if(!MyArray) MyArray = [[NSMutableArray alloc] init];
[MyArray addObject:object];
NSLog(#"%#",self.MyArray);
NSLog(#"Object added %u",[self.MyArray count]);
}
-(NSMutableArray *)ObjectList {
return self.MyArray;
NSLog(#"%#",self.MyArray);
NSLog(#"Object added %u",[self.MyArray count]);
}
#end
The header is like this:
#interface ArraysModel : NSObject
-(void)AddObjectToTheList:(NSString *)object;
And here is my call from my ViewController:
- (IBAction)AddToTheList {
ArraysModel *MyObjectToAdd = [[ArraysModel alloc] init];
[MyObjectToAdd AddObjectToTheList:TextArea.text];
[self.view endEditing:YES];
Well, there's your problem -- you're alloc init'ing a new instance of ArraysModel, and therefore a new array with every call. You need to create a strong reference to your instance, and check for whether it exits, and only init if it doesn't.
In the .h:
#property (strong, nonatomic) ArraysModel *myObjectToAdd;
in the .m:
-(IBAction)AddToTheList {
if (! self.myObjectToAdd) {
self.myObjectToAdd = [[ArraysModel alloc] init];
}
[self.myObjectToAdd AddObjectToTheList:TextArea.text];
[self.view endEditing:YES]
}
The first few programs I wrote in ObjC worked but were a cluttered mess so this time I wanted to do it right and employ MVC. All of the pieces work and have been tested and things were going great until I tried to copy an NSMutableArray from the model through the VC to the view. The exact same format and code was used and works fine in another aspect of the program but this particular view uses drawRect and breaks if I don't retain the array. When I do it causes a leak. To isolate the problem and create a workaround I ended up loading the array directly from the pList. It looks like this:
#interface HWView : UIView <UIGestureRecognizerDelegate>
{
NSMutableArray *drawStates;
}
#property (nonatomic, retain) NSMutableArray *drawStates;
in the .m
#implementation HWView
#synthesize drawStates;
- (void)awakeFromNib
{
[self HWVReset];
}
-(void)HWVReset
{
NSLog(#"HWVReset:");
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *plistPath = [documentsDirectorystringByAppendingPathComponent: #"PLIST_drawState.plist"];
self.drawStates = [[NSMutableArray arrayWithContentsOfFile:plistPath]retain];
NSLog(#"drawStates:%#",self.drawStates);
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect
{
//draw code
}
- (void)dealloc
{
[self.drawStates release];
[super dealloc];
}
So this runs but it leaks. I remove the retain from: "self.drawStates = [[NSMutableArray arrayWithContentsOfFile:plistPath]retain];" and it crashes. Any help is appreciated.
Of course : [NSArray array] is an autoreleased object. So you'll be calling a deallocated object. Read about Autorelease in Apple's docs.
**Note: I have updated the code based off of aroth's suggestions - however it is still crashing. The code in the below post is the updated code.
I am trying to create an iPhone app based off of the table-view XCode template (XCode 4). The table view gets populated with the correct data in the proper order - however when I go to scroll through the table the app crashes (sometimes I can scroll through 5 or 10 more cells, sometimes it freezes right away). The table view is being fed from 'Artist' objects within an NSArray which is an IVAR of another 'iPodLibraryParser' object. I believe the problem is that the 'iPodLibraryParser' object is being released prematurely - but I don't understand why.
I have created an iPodLibraryParser object with the following header file:
#import <Foundation/Foundation.h>
#import <MediaPlayer/MediaPlayer.h>
#import <CoreLocation/CoreLocation.h>
#import "ArtistClass.h"
#interface iPodLibraryParser : NSObject {
//Location stuff
CLLocationManager *locationManager;
IBOutlet UITextField *latitudeTextField;
IBOutlet UITextField *longitudeTextField;
IBOutlet UILabel *latitudeLabel;
IBOutlet UILabel *longitudeLabel;
//Music Library Stuff
NSString *currentArtist;
NSString *currentAlbum;
NSMutableArray *artistArray;
NSMutableArray *sortedArtistArray;
}
#property (nonatomic, retain) NSMutableArray *sortedArtistArray;
-(void)parseiPodLibrary;
-(id) initializeiPodLibraryParser;
#end
The relevant code in the .m file of this Class:
#implementation iPodLibraryParser
#synthesize sortedArtistArray;
-(id) initializeiPodLibraryParser{
[super init];
sortedArtistArray = [[NSMutableArray alloc] initWithObjects:nil];
return self;
}
-(void)parseiPodLibrary{
.....
NSArray *sortingArray = [[NSArray alloc] initWithObjects:artistTrackCountSorter,nil];
NSArray *tempSortedArray = [artistArray sortedArrayUsingDescriptors:sortingArray];
[sortedArtistArray removeAllObjects];
[sortedArtistArray addObjectsFromArray:tempSortedArray];
}
Artist object header:
#import <UIKit/UIKit.h>
#import "iPodLibraryParser.h"
#interface ArtistClass : NSObject {
NSString *artistName;
int numberOfTracks;
id artistClassViewController;
}
-(id) initializeArtistObjectWithDocument:(id)myDocument withArtist:(NSString*) artist;
#property (nonatomic, retain) NSString *artistName;
#property (nonatomic, assign) int numberOfTracks;
#end
Table View Controller (called RootViewController from the template being used)
Header:
#import <UIKit/UIKit.h>
#import "iPodLibraryParser.h"
#import "ArtistClass.h"
#interface RootViewController : UITableViewController {
iPodLibraryParser *iPodLibrary;
}
#property (nonatomic, retain) iPodLibraryParser *iPodLibrary;
#end
Relevant code
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSLog(#"In viewDidAppear");
iPodLibrary = [[iPodLibraryParser alloc] initializeiPodLibraryParser];
[iPodLibrary parseiPodLibrary];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"there are %i artists in the array", [[iPodLibrary sortedArtistArray] count]);
return [[iPodLibrary sortedArtistArray] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"in tableView blah");
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell.
NSLog(#"getting row: %i",indexPath.row);
cell.textLabel.text = [[[iPodLibrary sortedArtistArray] objectAtIndex:indexPath.row] artistName];
return cell;
}
The error is at this line:
cell.textLabel.text = [[[iPodLibrary sortedArtistArray] objectAtIndex:indexPath.row] artistName];
I tried creating an array with Artist objects that I created within the RootViewController - and that works perfectly (can scroll the entire table with no crashes)
Thanks again!
--Edit:
It is interesting to note that I get different errors at different times:
Most of the times it's just EXC_BAD_ACCESS at the line:
cell.textLabel.text = [[[iPodLibrary sortedArtistArray] objectAtIndex:indexPath.row] artistName];
Sometimes it's:
-[UIAutoRotatingWindow isEqualToString:]: unrecognized selector sent to instance 0x1baa80
And another had to do with an unrecognized RGB Selector (very strange).
You problem is when you do this:
sortedArtistArray = [artistArray sortedArrayUsingDescriptors:sortingArray];
The sortedArrayUsingDescriptors method is returning an autoreleased object, so you shouldn't be surprised when it gets released on you without warning.
Moreover, because your init does:
sortedArtistArray = [[NSArray alloc] init];
...and because you don't release it before you assign to it, your code is leaking NSArray instances. I would suggest the following revisions:
Make sortedArtistArray an NSMutableArray*, like:
NSMutableArray* sortedArtistArray;
Don't overwrite the array reference in parseiPodLibrary. Instead just copy the sorted dataset into the mutable array, like:
-(void)parseiPodLibrary{
//.....
NSArray* temp = [artistArray sortedArrayUsingDescriptors:sortingArray];
[sortedArtistArray removeAllObjects];
[sortedArtistArray addObjectsFromArray:temp];
}
Don't call [iPodLibrary retain]; in viewDidAppear. You've already called alloc/init on it, so there is no need to retain it again.
Ensure that you call [iPodLibrary release]; in viewWillDisappear, and [sortedArtistArray release]; in dealloc so that you don't leak memory.
I think it's much more likely that your iPodLibrary variable is over-released than that it's the array. You should troubleshoot by splitting your code into a few lines and seeing where it fails:
NSArray *artistArray = [iPodLibrary sortedArtistArray];
Artist *artist = [artistArray objectAtIndex:indexPath.row];
NSString *name = [artist artistName];
cell.textLabel.text = name;
Is it possible that your implementation of initializeiPodLibraryParser returns an autoreleased object? It shouldn't, as that violates the convention. But it would make sense that that would lead to this problem.
When you call this:
iPodLibrary = [[iPodLibraryParser alloc] initializeiPodLibraryParser];
you're directly assigning the iPodLibrary ivar, so its mutator isn't called and it doesn't matter that the property is marked as retain. If you think it's being implicitly retained, it's likely you're over-releasing it somewhere else. I find you'll understand your own memory management if you use this style to assign properties:
iPodLibraryParser *parser = [[iPodLibraryParser alloc] initializeiPodLibraryParser]; // retain count should be 1 if not autoreleased
[self setIpodLibrary:parser]; // retain count is now 2
[parser release]; // retain count is now 1, will go to zero when you release it in dealloc or viewDidUnload
Finally, I'd move your iPodLibrary initialization from viewDidAppear to viewDidLoad:. That's where you should be initializing your view. And you should be cleaning up anything you initialize there in viewDidUnload, which will be called in a low memory situation.
I'm trying to cache some images in my view controller using NSDictionary but I'm not having much luck.
for starters my .h looks like this
...
NSDictionary *images;
}
#property (nonatomic, retain) NSDictionary *images;
and in my .m I synth the property and attempt to add the image as follows:
[self.images setValue:img forKey:#"happy"];
and later I attempt to grab the image by key
UIImage *image = [self.images objectForKey:#"happy"];
if (!image) {
NSLog(#"not cached");
}else {
NSLog(#"had cached img %#", image);
}
Yet each time I NSLog the dictionary it's null. If I #synthesize the property should I be ready to go out of the box? or did I not add this to the dictionary correctly?
Thank you in advance
Synthesizing doesn't instantiate the variable so you still need to alloc+init it at some point.
But if you want to add objects to a dictionary after creating it, you need to use NSMutableDictionary instead.
Then alloc+init it in viewDidLoad using something like:
self.images = [[[NSMutableDictionary alloc] initWithCapacity:10] autorelease];
Then to set a value, use setObject:forKey: (not setValue:forKey:):
[images setObject:img forKey:#"happy"];
Remember to release the dictionary in dealloc.
I am semi-new to Objective-c and confused with why my NSMutableDictionary is not retaining information. I am declaring my variable in the header file:
#interface view_searchResults : UIViewController <UITableViewDataSource, UITableViewDelegate> {
NSMutableDictionary *imageDicationary;
}
#property (nonatomic, retain) NSMutableDictionary *imageDictionary;
Then in my .m file, I have the following:
#synthesize imageDictionary;
-(UIImage *)getImageForURL:(NSURL*)url {
UIImage*image;
image = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];
[imageDictionary setObject:image forKey:#"test"];
if([imageDictionary objectForKey:#"test"]){
NSLog(#"Exists");
}
}
There is obviously other code to support this, but I can confirm that a URL is being passed, and the file is downloading correctly elsewhere. Also, I can confirm that this function is being executed, and I am not referring to the NSMutableDictionary anywhere else in the document.
Thanks!
Where do you create your NSMutable dictionary? If this really is all the code you have you need to create the dictionary:
#implementation view_searchResults
- (id) init;{
self = [super init];
if(self) {
imageDicationary = [NSMutableDictionary alloc] init]; // should also be released in dealloc.
}
return self;
}
If this is the error then the reason you are not causing a crash is because in objective-C it is valid to send a message to the nil object - it just does nothing.
You havent told us whether the "Exists" NSLog is executed, you also are NOT returning the image.
In other words, I fail to see your problem
Has imageDictionary been initialized? (alloc/init?)