NSArray "out of scope" - objective-c

.h
#property (nonatomic, retain) NSArray *m_plistData;
.m
#synthesize m_plistData;
- (void)viewDidLoad
{
NSArray *array = [[NSArray alloc]initWithObjects:#"0",#"1",#"2",#"3",#"4",#"5",#"6",#"7",#"8",#"9",#"10",#"11",#"12",#"13",#"14", nil];
m_plistData = array;
NSArray *nn = m_plistData;
[super viewDidLoad];
}
I use breakpoint and found array is normal,but m_plistData has no values,shows "out of scope",I can't understand why nn can get normal values

array is a local reference variable. It just lasts until viewDidLoad method. Now,
m_plistData = array;
The above statement doesn't make a deep copy. It is just a shallow copy.
- (void)viewDidLoad
{
NSArray *array = [[NSArray alloc]initWithObjects:#"0",#"1",#"2",#"3",#"4",#"5",#"6",#"7",#"8",#"9",#"10",#"11",#"12",#"13",#"14", nil];
m_plistData = array;
NSArray *nn = m_plistData;
[super viewDidLoad];
} // Both the array, nn references cease to exist after this point.
// So having references to it leads to run-time exception if used else where.
If your objective is have elements in m_plistData, directly do -
m_plistData = [[NSArray alloc]initWithObjects:#"0",#"1",#"2",#"3",#"4",#"5",#"6",#"7",#"8",#"9",#"10",#"11",#"12",#"13",#"14", nil];

Try something like:
m_plistData = [array copy];

Do it like this as you have a NSAarray:
if(array)
{
m_plistData = [NSArray arrayWithArray:array];
}

Related

While (not) loop freezes app

My while loop doesn't seem to work. When loading this view, the app freezes.
When I delete the part of code, containing the while loop, the app won't freeze.
What I'm searching for is a piece of code that will cause that the same array is not chosen twice.
#interface ThirdViewController ()
#end
#implementation ThirdViewController
...
NSString * Answer = #"";
NSArray * RAMArray;
...
- (void)NewQuestion
{
NSString * PlistString = [[NSBundle mainBundle] pathForResource:#"Questions" ofType:#"plist"];
NSMutableArray * PlistArray = [[NSMutableArray alloc]initWithContentsOfFile:PlistString];
NSArray *PlistRandom = [PlistArray objectAtIndex: random()%[PlistArray count]];
while (![PlistRandom isEqual: RAMArray])
{
NSArray *PlistRandom = [PlistArray objectAtIndex: random()%[PlistArray count]];
}
RAMArray = PlistRandom;
...
}
- (void)Check:(NSString*)Choise
{
...
if ([Choise isEqualToString: Answer])
{
...
[self NewQuestion];
}
}
- (IBAction)AnsButA:(id)sender
{
UIButton *ResultButton = (UIButton *)sender;
NSString *Click = ResultButton.currentTitle;
[self Check:Click];
}
My guess is that because you re-declare PlistRandom within the while loop, the inner-declared variable may be out of scope at the point the while conditionis evaluated. Your problem I think is a scoping issue, just change the loop to this and see if that works:
while (![PlistRandom isEqual: RAMArray])
{
PlistRandom = [PlistArray objectAtIndex: random()%[PlistArray count]];
}

ObjC: constructing a mutable dictionary in a loop

I feel like I have read many (simple) examples that do exactly what I am trying to do. I just cannot seem to get this to work. I need a second eye on my code, and I don't have anyone around, so pardon me if this seems very simple... The code compiles without a problem. Thank you!
#implementation Engine
- (id) initWithInventory: (NSString *) path {
if (self = [super init]) {
NSString *contents = [NSString stringWithContentsOfFile:#"ingredientList.csv" encoding:NSASCIIStringEncoding error:nil];
NSLog(#"%#",contents); // This yields the contents of the file appropriately
NSArray *lines = [contents componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
NSRange ingredientRange = {0,96}; // This is done because I want to omit the last element of the array... the 97th is an empty string caused by the end of file newline character. I know it's bad coding...
NSEnumerator *enumerator = [[lines subarrayWithRange:ingredientRange] objectEnumerator];
NSString *curString;
NSArray *ingredientElements;
NSRange activeEffectRange = {1,4}; // Element 0 will be the key, elements 1-4 are the array to be stored.
while (curString = [enumerator nextObject]) {
ingredientElements = [curString componentsSeparatedByString:#","];
Ingredient *theIngredient = [[Ingredient alloc] initWithName:[ingredientElements objectAtIndex:0] andActiveEffects:[ingredientElements subarrayWithRange:activeEffectRange]];
NSLog(#"%#",[theIngredient ingredientName]);
NSLog(#"%#",[theIngredient activeEffects]); //These both print out correctly.
NSString *theName = [theIngredient ingredientName];
[allIngredients setObject:theIngredient forKey:theName];
NSLog(#"%#",[allIngredients objectForKey:[theIngredient ingredientName]]); // ***This yields (null)***
}
}
return self;
}
EDIT: I should add, that allIngredients is an instance variable of the class being initiated, so it is defined properly as an NSMutableDictionary:
#interface Engine : NSObject {
NSMutableDictionary *allIngredients;
}
- (id) initWithInventory: (NSString *) path;
#end
Where are you creating allIngredients? You've declared it, but you haven't allocated it before you use it.
allIngredients = [[NSMutableDictionary alloc] init]

issue adding NSMutablearray to other NSMutablearray? [duplicate]

This question already has answers here:
Cannot add items to an NSMutableArray ivar
(4 answers)
Closed 8 years ago.
I'm trying to add NSMutableArray to other NSMutableArray, a mutable array set as instance ivar, but I allways got the array arrayPlayoff empty. Other thing that I have detected, is that when debugging in the attached method, local variables are not shown in the debugger variables section, even selecting "local" option.
-(void)loadGamesPlayoffs{
NSMutableArray *eli1 = [[NSMutableArray alloc] init];
NSMutableArray *eli2 =[[NSMutableArray alloc] init];
NSMutableArray *eli3 = [[NSMutableArray alloc] init];
NSMutableArray *eli4 = [[NSMutableArray alloc] init];
for (NSDictionary *eliminatoria in copaReyArray){
int eli = [[eliminatoria valueForKey:#"eliminatoria"]integerValue];
NSLog(#"eli %d", eli);
if (eli==1){
[eli1 addObject:eliminatoria];
} else if (eli==2){
[eli2 addObject:eliminatoria];
}else if (eli==3){
[eli3 addObject:eliminatoria];
} else if (eli==4){
[eli4 addObject:eliminatoria];
}
}
[arrayPlayOff addObject:eli1];
[arrayPlayOff addObject:eli2];
[arrayPlayOff addObject:eli3];
[arrayPlayOff addObject:eli4];
}
many thanks
If arrayPlayOff is an Instance Variable you could use properties, your .h should look something like this:
#import <UIKit/UIKit.h>
#interface YourClassViewController : UIViewController{
NSMutableArray *arrayPlayOff;
//Some other variables
}
#property (nonatomic, retain) NSMutableArray *arrayPlayOff;
//Some other methods
#end
Then in your .m file you could use:
#implementation YourClassViewController
#synthesize arrayPlayOff;
- (NSMutableArray *)arrayPlayOff{
if(!arrayPlayOff){
arrayPlayOff = [[NSMutableArray alloc] init];
}
return arrayPlayOff;
}
//Your other methods
//Overwrite the dealloc function so you don't have any memory leaks
- (void)dealloc{
[arrayPlayOff release];
[super dealloc];
}
#end
Now you could access your variable as
self.arrayPlayOff
and this way you can be 100% sure that your variable is always initialized.
Your method could look like this (Also you should release your other NSMutableArrays since you are not using after adding them to the arrayPlayOff array):
-(void)loadGamesPlayoffs{
NSMutableArray *eli1 = [[NSMutableArray alloc] init];
NSMutableArray *eli2 =[[NSMutableArray alloc] init];
NSMutableArray *eli3 = [[NSMutableArray alloc] init];
NSMutableArray *eli4 = [[NSMutableArray alloc] init];
for (NSDictionary *eliminatoria in copaReyArray){
int eli = [[eliminatoria valueForKey:#"eliminatoria"]integerValue];
NSLog(#"eli %d", eli);
if (eli==1){
[eli1 addObject:eliminatoria];
} else if (eli==2){
[eli2 addObject:eliminatoria];
}else if (eli==3){
[eli3 addObject:eliminatoria];
} else if (eli==4){
[eli4 addObject:eliminatoria];
}
}
[self.arrayPlayOff addObject:eli1];
[self.arrayPlayOff addObject:eli2];
[self.arrayPlayOff addObject:eli3];
[self.arrayPlayOff addObject:eli4];
//Releasing the NSMutableArrays
[eli1 release];
[eli2 release];
[eli3 release];
[eli4 release];
}

Get & Edit NSMutableArray from different class file

I am trying to access and change a array from a different class file. When using a NSLog, I get a result of (null). Below is my code:
RootViewController.h
NSMutableArray *listOfItems;
#property (nonatomic, retain) NSMutableArray *listOfItems;
RootViewController.m
#synthesize listOfItems;
listOfItems = [[NSMutableArray alloc] init];
[listOfItems addObject:#"One"];
[listOfItems addObject:#"Two"];
[listOfItems addObject:#"Three"];
SecondViewController.m
RootViewController *test = [[RootViewController alloc] init];
NSLog(#"Results: %#", test.listOfItems);
I get the following results in my console: Results: (null)
Thanks in advance,
Coulton
P.S. Obviously I have left out a bunch of code. I just tried to make it easier to read. If you need to see anything else, I would be more than happy to post more. Just ask
EDIT #1:
I am getting hundreds of NSLog Messages that look something like this:
*** __NSAutoreleaseNoPool(): Object 0x4e39020 of class __NSArrayI autoreleased with no pool in place - just leaking
And here's my init code:
- (id) init {
//NSLog(#"%#", theUserID);
// Set up database connection
NSString *myDB = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"database.db"];
database = [[Sqlite alloc] init];
[database open:myDB];
//Initialize the array.
listOfItems = [[NSMutableArray alloc] init];
// Add to array to display in the tableView
NSArray *listOfItemsTwo = [database executeQuery:#"SELECT * FROM albums"];
for (NSDictionary *rowone in listOfItemsTwo) {
NSString *getName = [rowone valueForKey:#"name"];
if (getName != NULL) {
[listOfItems addObject:getName];
[getName release];
}
}
return self;
}
I guess you reversed RootViewController.m and RootViewController.h snippets right?
Are you sure that the
listOfItems = [[NSMutableArray alloc] init];
gets called? Maybe you can put a breakpoint there.
EDIT: Order of RootViewController.m and RootViewController.h has been fixed in the question. It's not clear from the question where the above line is in the code. That's a important piece of information.
EDIT2: Example of init method.
#implementation RootViewController
- (id) init
{
listOfItems = [[NSMutableArray alloc] init];
[listOfItems addObject:#"One"];
return self;
}
#end

Storing Sorted Arrays Causing EXC_BAD_ACCESS Error

Given a basic key/value array, I'm wanting to store two sorted arrays based on the original array: one array will be sorted by name, and the other by age.
The arrays seem to be sorting correctly when I output them to the log; however, when I try to access them elsewhere in the code, I'm receiving a EXC_BAD_ACCESS error.
Here's what I have so far:
// MyController.h
#interface MyController : UIViewController {
NSMutableArray *originalArray;
NSMutableArray *nameArray;
NSMutableArray *ageArray;
}
#property (nonatomic, retain) NSMutableArray *originalArray;
#property (nonatomic, retain) NSMutableArray *nameArray;
#property (nonatomic, retain) NSMutableArray *ageArray;
-(void)someRandomMethod;
#end
// MyController.m
#import "MyController.h"
#implementation MyController
#synthesize originalArray;
#synthesize nameArray;
#synthesize ageArray;
-(void)viewDidLoad {
// originalArray = (
// {
// "name" = "Sally";
// "age" = 18;
// },
// {
// "name" = "Chad";
// "age" = 26;
// },
// {
// "name" = "Carla";
// "age" = 24;
// },
// )
// sort by name
NSSortDescriptor *sortByNameDescriptor;
sortByNameDescriptor = [[[NSSortDescriptor alloc]
initWithKey:#"name"
ascending:NO] autorelease];
NSArray *sortByNameDescriptors = [NSArray arrayWithObject:sortByNameDescriptor];
nameArray = [originalArray sortedArrayUsingDescriptors:sortByNameDescriptors];
// sort by age
NSSortDescriptor *sortByAgeDescriptor;
sortByAgeDescriptor = [[[NSSortDescriptor alloc]
initWithKey:#"age"
ascending:NO] autorelease];
NSArray *sortAgeDescriptors = [NSArray arrayWithObject:sortByAgeDescriptor];
ageArray = [originalArray sortedArrayUsingDescriptors:sortByAgeDescriptors];
[super viewDidLoad];
}
-(void)someRandomMethod {
// whenever I try to access the sorted arrays, I receive the EXC_BAD_ACCESS error
[[nameArray objectAtIndex:0] valueForKey:#"name"];
[[ageArray objectAtIndex:0] valueForKey:#"age"];
}
-(void)viewDidUnload {
self.originalArray = nil;
self.nameArray = nil;
self.ageArray = nil;
[super viewDidUnload];
}
- (void)dealloc {
[originalArray release];
[nameArray release];
[ageArray release];
[super dealloc];
}
#end
Any ideas?
UPDATE: Thanks to #robin, by changing the code above to the code below, everything works great:
// sort by name
NSSortDescriptor *sortByNameDescriptor;
sortByNameDescriptor = [[[NSSortDescriptor alloc]
initWithKey:#"name"
ascending:NO] autorelease];
NSArray *sortByNameDescriptors = [NSArray arrayWithObject:sortByNameDescriptor];
nameArray = [[NSMutableArray alloc] initWithArray:[originalArray sortedArrayUsingDescriptors:sortByNameDescriptors]];
// sort by age
NSSortDescriptor *sortByAgeDescriptor;
sortByAgeDescriptor = [[[NSSortDescriptor alloc]
initWithKey:#"age"
ascending:NO] autorelease];
NSArray *sortAgeDescriptors = [NSArray arrayWithObject:sortByAgeDescriptor];
ageArray = [[NSMutableArray alloc] initWithArray:[originalArray sortedArrayUsingDescriptors:sortByAgeDescriptors]];
I dont think you know about this or not but when ever you create an object like string or array or dictionary, with init methods then the retain count gets incremented by 1
and if you create them like this
NSArray *anarray = [NSArray arrayWithArray:temp];
this will create an autorelease objects that will be released automatically after sometime.
So my advice don't use this type of code if you want to use the objects in more than 1 function. Always use init methods first to get the work done.
and if you are sure that the objects are not needed for the rest of the program than release them using release methode.