NSMutableDictionary not retaining values - objective-c

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?)

Related

NSLog returning null instead of string

NSLog is returning the output 'Null" instead of a string that I would have expected. I suspect that this is a problem with private instance variables and such, but since I am not familiar with Object-oriented programming I cannot determine the cause.
//The viewDidLoad method in MainGameDisplay.m:
- (void)viewDidLoad
{
[super viewDidLoad];
Engine *engine = [[Engine alloc] init];
[engine setPlayerName: viewController];
}
The string is entered by a UITextField, the property being
//ViewController.h
#property (strong, nonatomic) IBOutlet UITextField *PlayerNameTextView;
The method works fine and returns the correct string if [engine setPlayerName: self] is placed into ViewController, but anywhere outside the location that *PlayerNameTextView is causes this problem.
//Engine.m
#implementation Engine
{
ViewController *firstPage;
}
NSString *Player;
-(void) setPlayerName: (ViewController *) name
{
Player = [[name PlayerNameTextView] text];
NSLog(#"%#", Player);
}
NSLog return type is void as you can see in it's documentation. There is no reason to expect any return value for a call to it, since it does not return anything.
Make sure that 'name' is properly initialized. Try putting an assert(name != nil) right before the NSLog. Or better yet, set a breakpoint at the NSLog and inspect the variables.
Another suggestion: Why not make the method -(void) setPlayerName:(NSString*)name? This is more straightforward than passing around pointers to view controllers, and would be easier to debug.

NSMutableArray as instance variable alway null

After many hours wasted, I officially turn to the experts for help!
My problem lies with using a NSMutableArray as an instance variable, and trying to both add objects and return the array in a method in my class. I am obviously doing something fundamentally wrong and would be grateful for help...I have already tried all the suggestions from other similar questions on stackoverflow, read apples documentation, and basically all combinations of trial and error coding I can think of. The mutable array just alway returns (null). I've even tried creating properties for them, but still the array returns (null) and then I also am running into memory management problems due to the retain while setting the property, and the init in the init method for the class.
Here is what I am trying to do:
1) Loop through a series of UISwitches and if they are 'switched on', add a string to the NSMutableArray
2) Assign this mutable array to another array in another method
Any help much appreciated,
Andy
And for some code...
fruitsViewController.h
#import <UIKit/UIKit.h>
#interface fruitsViewController : UIViewController
{
NSMutableArray *fruitsArr;
UISwitch *appleSwitch;
UISwitch *orangeSwitch;
}
#property (nonatomic,retain) NSMutableArray *fruitsArr; // ADDED ON EDIT
#property (nonatomic,retain) IBOutlet UISwitch *appleSwitch;
#property (nonatomic,retain) IBOutlet UISwitch *orangeSwitch;
- (IBAction)submitButtonPressed:(id)sender;
#end
fruitsViewController.m
#import "fruitsViewController.h"
#implementation fruitsViewController
#synthesize fruitsArr; // ADDED ON EDIT
#synthesize appleSwitch, orangeSwitch;
/* COMMENTED OUT ON EDIT
-(id)init
{
if (self = [super init]) {
// Allocate memory and initialize the fruits mutable array
fruitsArr = [[NSMutableArray alloc] init];
}
return self;
}
*/
// VIEW DID LOAD ADDED ON EDIT
- (void)viewDidLoad
{
self.fruitsArr = [[NSMutableArray alloc] init];
}
- (void)viewDidUnload
{
self.fruitsArr = nil;
self.appleSwitch = nil;
self.orangeSwitch = nil;
}
- (void)dealloc
{
[fruitsArr release];
[appleSwitch release];
[orangeSwitch release];
[super dealloc];
}
- (IBAction)submitButtonPressed:(id)sender
{
if ([self.appleSwitch isOn]) {
[self.fruitsArr addObject:#"Apple"; // 'self.' ADDED ON EDIT
}
if ([self.orangeSwitch isOn]) {
[self.fruitsArr addObject:#"Orange"; // 'self.' ADDED ON EDIT
}
NSLog(#"%#",self.fruitsArr); // Why is this returning (null) even if the switches are on?!
[fruitsArr addObject:#"Hello World";
NSLog(#"%#",self.fruitsArr); // Even trying to add an object outside the if statement returns (null)
}
#end
It seems like your init function is never called. If you're initializing this view controller from a NIB, you need to use initWithCoder. If not, just declare your fruitsArr in viewDidLoad.
Use view did load instead of init...
- (void)viewDidLoad
{
fruitsArr = [[NSMutableArray alloc] init];
}
Change that init for viewDidLoad and see what happens
Is your init method ever being called (in complicationsViewController). Add a NSLog to check this, you might be calling initWithNib: maybe.
At viewDidUnload you should remove self.fruitsArr = nil;, or, if you want to keep it, then initialize the fruitsArr in viewDidLoad (and remove it from init).
because fruitsArr don't be init.
you should do this first:
fruitsArr = [[NSMutableArray alloc] init];
so, I think you don't run - (id)init before you use fruitsArr.

Crash on NSMutableDictionary's setObject function

Here is my code:
NSLog(#"dictionaryPlayers=%#,%d",[dictionaryPlayers description],dictionaryPlayers.count);
[dictionaryPlayers setObject:#"test" forKey:#"test2"];
dictionaryPlayers is inited in this class's init function:
-(id)init{
...
dictionaryPlayers = [[NSMutableDictionary dictionaryWithCapacity:10]retain];
...
}
The program crashed:
Thread 1:Program received signal: "SIGABRT".
And in console:
2011-12-27 17:01:21.744 [25454:207] dictionaryPlayers={
},0
2011-12-27 17:01:21.745 [25454:207] -[__NSCFConstantString tick]: unrecognized selector sent to instance 0x199bcc
With the NSLog outputs, i think dictionaryPlayers is well inited. So I don't know why crashed...
The object on which you call tick: is not longer in memory and causes this crash. Try to see why this object is released.
It seems that this is not a local case, so did you make sure to synthesize it at the top? And declared it correctly in the header? Examples:
In header:
#property (nonatomic, strong) NSMutableDictionary *dictionaryPlayers;
in class:
#synthesize dictionaryPlayers = _dictionaryPlayers;
I removed
dictionaryPlayers = [NSMutableDictionary dictionaryWithCapacity:10];
from init(), and added
dictionaryPlayers = [[NSMutableDictionary alloc] init];
above my log statement. Still crash....
Then I removed
[dicTest setValue:#"Test" forKey:#"testKey"];
So there's only 2 lines left:
dictionaryPlayers = [[NSMutableDictionary alloc] init];
NSLog(#"dictionaryPlayers=%#,%d",[dictionaryPlayers description],dictionaryPlayers.count);
It didn't crash. So, it seems the setValue line really is the problem.
You don't need to call retain on the object in your init statement. Also just for giggles try:
dictionaryPlayers = [[NSMutableDictionary alloc] init];
instead of
dictionaryPlayers = [NSMutableDictionary dictionaryWithCapacity:10];
And do this right above your log statement (take it out of the init).
If this works, put a log in your init method and make sure that is being called before your method that adds KV's to the dictionary
I cannot reproduce this behavior. Here is my code:
ViewController.h:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property(nonatomic, retain) NSMutableDictionary *dictionaryPlayers;
#property (retain, nonatomic) IBOutlet UITextView *logTextView;
- (IBAction)logButtonPressed:(id)sender;
#end
ViewController.m:
#import "ViewController.h"
#implementation ViewController
#synthesize dictionaryPlayers;
#synthesize logTextView;
#pragma mark - My Methods
- (IBAction)logButtonPressed:(id)sender {
logTextView.text = [NSString stringWithFormat:#"%#,%d",[dictionaryPlayers description],[dictionaryPlayers count]];
NSLog(#"dictionaryPlayers=%#,%d",[dictionaryPlayers description],[dictionaryPlayers count]);
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
dictionaryPlayers = [[NSMutableDictionary alloc] init];
[dictionaryPlayers setValue:#"Test" forKey:#"testKey"];
NSLog(#"dictionaryPlayers=%#,%d",[dictionaryPlayers description],[dictionaryPlayers count]);
}
No issues. If you are doing things this way, you cannot have problems. Here are the steps I would take to troubleshoot further:
Do a project search for playersDictionary and make sure there isn't something else touching that object.
Try cleaning the project
Create a new project with this structure and see what happens

NSArray will not initialize in my MVC view

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.

Having trouble adding objects to NSMutableArray in Objective C

I am using the iPhone SDK and have an issue doing something simple. I am trying to add an NSNumber object to an NSMutableArray instance variable. I tried adding NSNumber card to NSMutableArray viewedCardsArray, however without breaking, it does not get added to the array. Here is the code.
/////////////////////////////////////////////////////
// Inside the header file Class.h
#interface MyViewController : UIViewController {
NSMutableArray *viewedCardsArray;
//snip ...
}
#property (nonatomic, retain) NSMutableArray *viewedCardsArray;
#end
/////////////////////////////////////////////////////
// Inside the methods file Class.m
#import "StudyViewController.h"
#implementation StudyViewController
#synthesize viewedCardsArray
//snip ...
- (IBAction)doShowCard {
//snip ...
NSNumber *cardIdObject = [[NSNumber alloc] initWithInt:(int)[self.currentCard cardId]];
[viewedCardsArray addObject: cardIdObject];
[cardIdObject release];
}
So this code executes, and does not seem to leak (according to the Leaks performance tool). However when stepping through the code, at no point does CardIdObject appear in viewedCardsArray.
Looking through SO, I know these basic questions are pretty common to ObjC newbies (like me) so apologies in advance!
Have you initialized your viewedCardsArray? If not you need to somewhere - this is usually done in the init method for your class:
- (id)init
{
self = [super init];
if(self) {
viewedCardsArray = [[NSMutableArray alloc] init];
}
return self;
}
Then it is released in the dealloc method:
- (void)dealloc
{
[viewedCardsArray release];
[super dealloc];
}
Perspx has outlined one way of initializing the array. However, you can also use the class methods provided by NSArray:
self. viewedCardsArray = [NSMutableArray array];
This can go in init or elsewhere.
Note: The object will be autoreleased.