how to fetch data from NSMutableArray ObjectAtIndex from integer value? [closed] - iphone

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I want to fetch data from my NSMutableArray, I am doing this
-(void)ViewDidLoad{
A_array = [[NSMutableArray alloc] init];
A_array = [NSMutableArray arrayWithObjects:#"4",#"6",#"2",#"3",#"0",#"5",#"1",#"2",#"4",#"1",#"0",#"2",#"4",#"2",#"0",#"3",nil]
var_Count_Answer_A = 0; // int
}
-(void)method_Second {
NSLog(#"%#",[A_array objectAtIndex:var_Count_Answer_A]); // This line is crashing if I click button again. First time line works fine but if we click button again and var_Count_Answer = 2 then it will crash.
NSString *str1 = [[NSString alloc]initWithFormat:#"%#",[A_array objectAtIndex:var_Count_Answer_A]]; // If I comment on NSLOG then this line will crash
A = [str1 integerValue];
NSLog(#"A is %d",A);
var_Count_Answer_A ++;
}
if I try this NSLog(#"%#",[A_array objectAtIndex:5]); // works fine
NSLog(#"%#",[A_array objectAtIndex:var_Count_Answer_A]); // var_Count_Answer_A =5; and crash
Any Idea or Suggestions would be highly appreciated.

Your code hurt my eyes
There are certain coding standards to be followed while writing code in Objective-C. Every language got one. They make code readable and understandable. You can refer to Cocoa Coding Guidelines and help yourself writing better looking code.
Explain Properly
Without the error message before crash no one can help you. Next time when you post about a crash, also explain the error message you got.
Was it a EXEC_BAD_ACCESS? If so it is the awesome garbage collector sweeping your array object away. Anyway your code sores my eyes and I am taking the privilege refactoring the code. Maybe it will help you.
A little bit of refactoring
NSArray *aArray;
- (void)viewDidLoad
{
[super viewDidLoad];
aArray = #[#"1", #"2", #"3", #"4"];
// or use[[NSArray alloc]initWithObjects:#"1", #"2", #"3", #"4", #"5"];
//Why do you need a mutable array while initializing it static?
}
- (void)methodSecond
{
static int counter = 0;
if (aArray) {
if (counter<aArray.count) {
NSLog(#"A is %u",[[aArray objectAtIndex:counter++]integerValue]);
} else {
counter = 0;
[self methodSecond];
}
}
}
Understand what you are doing
So a detail explanation of what I guess your problem is:
You're using [NSArray initWithObjects:] this creates an autoreleased object, and we got no control over its life time. And they get released if they are not referenced immediately after creating, which is probably whats happening your case. In my experience, mutable autoreleased object always sources bad access problems. So it is better to have the object alloc and inited, ie.. [[NSArray alloc]initWithObjects:] and I observe you are not adding/removing array members in run-time. There is no purpose of having a MutableArray.
In your code, you're creating two objects. The first array object is allocated and immediately dereferenced in the next line. Which is probably a mistake.
If you want to know more about auto-released objects. Read this.

Use
A_array = [[NSMutableArray alloc] initWithObjects:#"4",#"6",#"2",#"3",#"0",#"5",#"1",#"2",#"4",#"1",#"0",#"2",#"4",#"2",#"0",#"3",nil];
Instead you used.
A_array = [[NSMutableArray alloc] init];
A_array = [NSMutableArray arrayWithObjects:#"4",#"6",#"2",#"3",#"0",#"5",#"1",#"2",#"4",#"1",#"0",#"2",#"4",#"2",#"0",#"3",nil];
As I review Your Project is ARC disable try this Working fine for me.
ViewControler.h
#interface MasterViewController : UIViewController
{
NSMutableArray *A_array;
int var_Count_Answer_A;
}
ViewControler.m
-(void)viewDidLoad {
[super viewDidLoad];
A_array = [[NSMutableArray alloc] initWithObjects:#"4",#"6",#"2",#"3",#"0",#"5",#"1",#"2",#"4",#"1",#"0",#"2",#"4",#"2",#"0",#"3",nil];
var_Count_Answer_A = 0;
var_Count_Answer_A = 0; // int
}
-(IBAction)method_Second:(id)sender {
NSLog(#"%#",[A_array objectAtIndex:var_Count_Answer_A]);
NSString *str1 = [[NSString alloc]initWithFormat:#"%#",[A_array objectAtIndex:var_Count_Answer_A]]; // If I comment on NSLOG then this line will crash
int A = [str1 integerValue];
NSLog(#"A is %d",A);
var_Count_Answer_A++;
}
But As Everyone know at last there must be occur this exception.
NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 16 beyond bounds [0 .. 15]'
As trying to access array index object that does not exist.
And if you still have some error then First Enable NSZombie in your project Follow this.
-> "Product" menu, select "Edit Scheme", go to the "YourAp.app" stage in the left panel, and the "Arguments" tab on the right. You can then add NSZombieEnabled to the "Environment Variables" section and set the value to YES.
And Now Share your Crash Log.

in your code you are usimng two different varaibles once check thosetwo.
var_Count_Answer and var_Count_Answer_A

This error occurs because you are using an auto-released object.
When you call like:
A_array = [NSMutableArray arrayWithObjects:#"4",#"6",#"2",#"3",#"0",#"5",#"1",#"2",#"4",#"1",#"0",#"2",#"4",#"2",#"0",#"3",nil]
The A_array is an autoreleased object, you can't say when it'll be released. That is why this error occurs.
Solution:
Declare a property for the array like:
#property (nonatomic, strong) NSMutableArray *A_array;
Then modify your methods like:
-(void)ViewDidLoad
{
_A_array = [NSMutableArray arrayWithObjects:#"4",#"6",#"2",#"3",#"0",#"5",#"1",#"2",#"4",#"1",#"0",#"2",#"4",#"2",#"0",#"3",nil]
var_Count_Answer_A = 0; // int
}
-(void)method_Second
{
NSLog(#"%#",[_A_array objectAtIndex:var_Count_Answer_A])
NSString *str1 = [[NSString alloc]initWithFormat:#"%#",[_A_array objectAtIndex:var_Count_Answer_A]];
A = [str1 integerValue];
NSLog(#"A is %d",A);
var_Count_Answer_A ++;
}

Related

NSMutableDictionary EXC_BAD_ACCESS

I know there are many questions about this topic but non of them work for me because mine is a little weird.
First of all I create a static singleton class. and declare a variable of NSMutableDictionary
static NSMutableDictionary* mydic
#implementation mySingleton
-(mySingleton*)getInstance
{
static mySingleton *sharedInstance;
#synchronized(self)
{
if(!sharedInstance)
{
sharedInstance = [[mySingleton alloc] init];
mydic = [[NSMutableDictionary alloc] initWithCapacity:1];
}
return sharedInstance;
}
}
-(NSMutableDictionary*)getDictionary
{
return myDic;
}
then I call this NSMutableDictionary from another class like the below.
NSMutableDictionary* singletonDictionary = [[mySingleton getInstance] getDictionary];
MyOtherClass* myclass = [singletonDictionary objectForKey:key];// Key is NSString
// Here I can see whole the values I added to myClass for that key
NSArray *checkKey = [singletonDictionary allKeys];
for(int i = 0; i < [singletonDictionary count]; i++)
{
NSLog(#"%#",[checkKey objectAtIndex:i]);// here I can see my key is there
}
[singletonDictionary removeObjectForKey:key];// here it crashes EXC_BAD_ACCESS
I am gonna get crazy about this problem. If someone has an idea please share it with me.
EDIT :
MyOtherClass * myinstance = [[MyOtherClass alloc] init];
// Fill up the instance with the desired variable here
// Forexample
// myinstance.name = [NSString stringWithFormat:#"myInstanceName"];
.
.
.
[[[mySingleton getInstance] getDictionary] setObject:myinstance forKey:key]// key is an NSString*
[myinstance release];
Thanks for help.
Omer Faruk KURT
So many problems, where to start...?
At least, it seems your getInstance method is not returning anything; it should probably return mySingleton. This could explain your EXEC_BAD_ACCESS, as singletonDictionary is probably nil as things stand.
Your singleton instantiation is wrong too - you need to check if the singleton has already been created, and return it if it has. Otherwise you can reallocate singletons, which is absurd.
Static references are poor design here, better to subclass and declare members in the header file.
This might fix your problems, but you're clearly jumping in at the deep end and you're going to encounter more trouble. I think you need to find good examples of code in texts or online and study those. If you do that pretty soon you'll learn the ropes.
The NSMutableDictionary retains objects added to the dictionary. When the objects are removed they are released. As a result, removing an object from the dictionary accesses the object. If you have previously released the object and it is dealloc'ed, then this can cause an exception to be raised. If you examine the state of the object prior to removing from the dictionary you will likely see that it has already been released and dealloced.

Preventing to alloc the same array more than once

A beginner's problem: I have a method which puts data into a MutableArray. Potentially, this method can be called more than once and I am a bit concerned that it will leak memory as I am allocating the array every time it gets called:
indexContent = [[NSMutableArray alloc] init];
int numberOfEntries = [noteBookContent count]/3;
for (int k=0; k < numberOfEntries; k++) {
IndexItem *newItem = [[IndexItem alloc] init];
newItem.itemTitle = [noteBookContent objectAtIndex:(k*3)];
newItem.itemPage = k;
if (![[noteBookContent objectAtIndex:(k*3)] isEqualToString:#""]) {
[indexContent addObject:newItem];
}
[newItem release];
}
What will actually happen if indexContent = [[NSMutableArray alloc] init]; is called more than once? If it's bad, how can I prevent this? Should I call this, for instance, in the viewDidLoad? But how would I go about it if I try to do 'lazy-loading', i.e. only allocate indexContent if I really need it? Is there a way to check if it has already been allocated?
I am sorry if all of this is obvious, but I am struggling with this. Perhaps it's a basic concept which I haven't fully grasped yet. Thanks!
EDIT:
I have
#property (nonatomic, retain) NSMutableArray *indexContent;
in my header
If you call your function more then once you will leak memory due to the fact that you are not releasing already allocated memory from the previouse call. Simple check would be like this:
if(indexContent)
[indexContent release]
Read memory management docs from apple the will help you a lot.
if (indexContent == nil) indexContent = [NSMutableArray new]; // i screwed up logic first time. derp.
Make sure that when you release indexContent you set it to nil;
[indexContent release];
indexContent = nil;
(Unless it is the dealloc method, but probably still a good idea there)
Note that this assumes you want to re-use and potentially further fill the existing array. If not, you could removeAllObjects or you could release the existing and create anew.
Or, if an #property, you can:
self.indexContent = [NSMutableArray array]; // not +new!!
Or, in that method:
[indexContent release];
indexContent = [NSMutableArray new];
Surround code with a check for nil, if it is nil then allocate the array
//check if it has been allocated
if(indexContent == nil)
{
indexContent = [[NSMutableArray alloc] init];
int numberOfEntries = [noteBookContent count]/3;
for (int k=0; k < numberOfEntries; k++) {
IndexItem *newItem = [[IndexItem alloc] init];
newItem.itemTitle = [noteBookContent objectAtIndex:(k*3)];
newItem.itemPage = k;
if (![[noteBookContent objectAtIndex:(k*3)] isEqualToString:#""]) {
[indexContent addObject:newItem];
}
[newItem release];
}
}
It depends. Is indexContent declared as a retain #property? If so, the runtime will take care of releasing the previous array. If not, and you don't explicitly release it, then yes, it'll leak.
You should also make sure you are releasing indexContext in your dealloc method.
EDIT: As #bbum mentioned, you'll have to use dot notation. self.indexContent = <whatever>; My bad for overlooking this.

iPhone - Problems with releasing memory - memory leaks

I'm having the code as below.
- (void)viewDidLoad
{
NSArray* myarr = [self createArray];
for (NSString* str in myarr)
{
NSLog(#"%#",str);
}
[myarr release];
}
-(NSArray*)createArray
{
NSArray* arr1 = [[NSArray alloc] initWithObjects:#"APPLE",#"MAC",#"IPHONE",nil];
return arr1;
}
When I "Build & Analyze", its showing two leaks. One at [myarr release] saying, incorrect decrement of the reference count of an object that is owned at this point. and Other at return arr1, saying, Potential leak of an object allocated on line 152 and stored into arr1.
From my above code, the method "createArray" is returning a pointer and I'm releasing it as well. Is my way of coding right or wrong?
From my above code, the method "createArray" is returning a pointer and I'm releasing it as well. Is my way of coding right or wrong?
that depends on how you look at it.
1) the ref counting looks ok
2) the static analyzer flags objc methods based on names, in some cases. so the issue will likely vanish if you rename createArray to newArray, or something named new*. so it expects a convention (the ones used by Apple) to be followed.
therefore, it's the message that's bit shallow, it doesn't really analyze the program, but bases its findings/results on convention -- and not an actual evident issue which a human can read.
If you're just using the array in your viewDidLoad method, then you don't need to alloc an array in there at all. You can just use an autoreleased array returned as 7KV7 suggested. You can return an autoreleased array in your -(void)createArray as well without alloc'ing an object. Here is an example.
- (void)viewDidLoad
{
NSArray* myarr = [self createArray];
for (NSString* str in myarr)
{
NSLog(#"%#",str);
}
}
-(NSArray*)createArray
{
return [NSArray arrayWithObjects:#"APPLE",#"MAC",#"IPHONE",nil];
}
If you don't have to alloc an object to use it, it makes for less, and cleaner code, IMO.
Try this
- (void)viewDidLoad
{
NSArray* myarr = [[NSArray alloc] initWithArray:[self createArray]];
for (NSString* str in myarr)
{
NSLog(#"%#",str);
}
[myarr release];
}
-(NSArray*)createArray
{
NSArray* arr1 = [[NSArray alloc] initWithObjects:#"APPLE",#"MAC",#"IPHONE",nil];
return [arr1 auotrelease];
}
The problem with your code is that
You do not allocate myarr using alloc or new so you do not take ownership of the object. Hence the issue in release.
You allocate arr1 so you take ownership of the object and you return arr1. Hence you do not release it. That is the reason for the leak.

NSDictionary functionality question

So I am trying to save arrays into an NSDictionary on the fly. Let me show you the code and explain what is going on.
for (int x= 0; x <[appDelegate.people count]; x++) {
Person *aPerson = [[Person alloc] init];
aPerson = [appDelegate.people objectAtIndex:x];
if ([appDelegate.groupedBusiness objectForKey:aPerson.business_name] == nil) {
NSMutableArray *newBusiness = [[NSMutableArray alloc] init];
//if the business does not exist in the dict, add the person to the business and add it to dict.
[newBusiness addObject:aPerson];
[appDelegate.groupedBusiness setObject:newBusiness forKey:aPerson.business_name];
[newBusiness release];
newBusiness = nil;
//NSLog(#"%#", appDelegate.groupedBusiness);
} else {
NSMutableArray *existingBusiness= [appDelegate.groupedBusiness objectForKey:aPerson.business_name];
[existingBusiness addObject:aPerson];
//THIS IS THE LINE I AM NOT SURE ABOUT!!!
[appDelegate.groupedBusiness setObject:existingBusiness forKey:aPerson.business_name];
[existingBusiness release];
existingBusiness = nil;
//NSLog(#"%#", appDelegate.groupedBusiness);
}
}
Alright, so the appDelegate has an array of "People" that has a whole bunch of attributes about a person. I am trying to set up a dictionary to sort them by their business names. I am doing this by creating an array and saving it in the dictionary with the business_name as the key. Each iteration of the loop I check to see if the key exists, if it does, pull out the existing array, add the person you are checking, and resave it to the dictionary. However, this does not appear to be happening. Is there some exotic behavior in the NSDictionary class that would prevent that? I have poured over the class web page and can't find anything. Sorry if this is a noobie question, I am still trying to understand the objective-c classes. Thanks!
Why do you release existingBusiness? You are not creating an object, just taking the pointer from an array. When you invoke release, retainCount became 0 and object deallocs.
Just remove the following two lines:
[existingBusiness release];
existingBusiness = nil;
and everything should work fine.
You're way overcomplicating this, not to mention leaking a couple things.
for (Person *aPerson in appDelegate.people) {
NSMutableArray *business = [appDelegate.groupedBusiness objectForKey:aPerson.business_name];
if (!business) {
business = [NSMutableArray array];
[appDelegate.groupedBusiness setObject:business forKey:aPerson.business_name];
}
[business addObject:aPerson];
}
Not an answer, but some coding style issues.
Use fast iteration if you don't need the index:
for (Person *aPerson in appDelegate.people) {
Use convenience constructors; it makes your code more readable (remember to remove the "release" at the end):
NSMutableArray *newBusiness = [NSMutableArray arrayWithObject:aPerson];
Avoid duplicate logic where possible:
NSMutableArray * business = [appDelegate.groupedBusiness objectForKey:aPerson.business_name;
if (!business) {
business = [NSMutableArray array];
}
[business addObject:aPerson];
[appDelegate.groupedBusiness setObject:business forKey:aPerson.business_name];
The "setObject:existingBusiness" call does changes nothing apart from wasting CPU cycles, but in the case above, it makes the code somewhat more readable.
[appDelegate.groupedBusiness setObject:existingBusiness forKey:aPerson.business_name];
[existingBusiness release];
existingBusiness = nil;
This should all be removed. existingBusiness is already in the dict, and it's a mutable object - when you're adding a person to it, this will be reflected in the dictionary as well as it's the same object you're dealing with. Apart from that you have a couple of memory leaks as Daniel points out.

Why Instruments report a leak?

I am developing an iphone app. Instruments reported a leaked object ServiceTypes. Below is the relevant code. Does anyone have any ideas? Thanks a lot for your help.
ServiceTypes *serviceTypes = [[ServiceTypes alloc] init];
if ([userConnection getServiceTypes:serviceTypes]) {
if ([serviceTypes.types length] > 0) {
NSArray *array = [[NSArray alloc] initWithArray:[serviceTypes.types componentsSeparatedByString: SERVICE_TYPE_DELIMITOR]];
serviceRequestTypes = [[NSMutableArray alloc] initWithArray:array];
[array release];
}
}
[[self typesTableView] reloadData];
[serviceTypes release];
It doesn't look like serviceTypes is being leaked. From the code you posted, serviceTypes is always released at the end of the method, and it doesn't appear to be retained anywhere in your sample. My question is: what happens inside getServiceTypes:. Does that method retain the serviceTypes parameter?
One more thing. If serviceRequestTypes is an instance variable (and it looks like it is), then you may be leaking memory by reassigning it without releasing the existing serviceRequestTypes object first. You should either rewrite serviceRequestTypes to be a property and use a synthesized accessor or make sure to release it every time before assigning. If its current value is nil, no big deal; the release message will simply be ignored. For example:
[serviceRequestTypes release];
serviceRequestTypes = [[NSMutableArray alloc] initWithArray:[serviceTypes.types componentsSeparatedByString:SERVICE_TYPE_DELIMITER]];