I have a NSMutabelArray and I want to do some additions inside of it. I do this by calling a functions with then create a subarray with the items where the calculations have to be done on.
- (NSDecimalNumber *)calculate:(NSMutableArray *)arrayToCalculate {
while ([arrayToCalculate containsObject:(#"+")]) {
NSUInteger signeLocation = [arrayToCalculate indexOfObject:(#"+")];
[arrayToCalculate replaceObjectAtIndex:(signeLocation-1)
withObject:([[arrayToCalculate objectAtIndex:(signeLocation-1)]
decimalNumberByAdding:[arrayToCalculate objectAtIndex:(signeLocation+1)]])];
[arrayToCalculate removeObjectsAtIndexes:
[NSIndexSet indexSetWithIndexesInRange:NSMakeRange((signeLocation), 2)]];
}
return [arrayToCalculate lastObject];
}
I initialised the arrayToCalculate by:
NSMutableArray *subArray =
[inputArray subarrayWithRange:(rangeOfCalculationItems)];
Every time I run this code it crashes. I am pretty sure it is bc I used subarray on an NSMutableArray and initialised it as NSMutableArray even when the message gives me back a NSArray, but I don't know how I could fix it or it is even the problem.
I copied your method and tested it like this:
NSArray *items = #[
[[NSDecimalNumber alloc] initWithString:#"1"],
#"+",
[[NSDecimalNumber alloc] initWithString:#"2"]
];
NSLog(#"%g", [self calculate: [items mutableCopy]].floatValue);
The code works and the printed result was 3. Your issue must be somewhere else. Are you sure your array is in fact mutable? Note [items mutableCopy].
Related
i am trying to show selected cell checkmark when user is offline,but the array is not adding another array object, kindly help me
1.appDelegate.SelectedIDArray saving selected cell
2.buildingObject.selectedIDString saving checked cell index coma separated
//first i am removing all objects from array
[appDelegate.SelectedIDArray removeAllObjects];
//then i am adding string values in array(e.g 3,2,7)
NSMutableArray *tempArray = (NSMutableArray*)[buildingObject.selectedIDString componentsSeparatedByString:#","];
//now adding tempArray array objects in appDelegate.SelectedIDArray
[appDelegate.SelectedIDArray addObjectsFromArray:tempArray];
//now showing count of added object in appDelegate.SelectedIDArray
txtID.text=[NSString stringWithFormat:#"%zd of 23 selected",appDelegate.SelectedIDArray.count];
by saying offline, you mean app is terminated, then if you didn't save your array in NSUserDefaults it is nil already. then you should initialize it. if this is not the case another problem may be with appDelegate:
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
NSString *vals = #"1,2,3,4,5,6,7,8";
NSMutableArray *tempArray = [[vals componentsSeparatedByString:#","] mutableCopy];
if (!appDelegate.SelectedIDArray) {
appDelegate.SelectedIDArray = [NSMutableArray new];
}
else
{
[appDelegate.SelectedIDArray removeAllObjects];
}
[appDelegate.SelectedIDArray addObjectsFromArray:tempArray];
NSLog(#"%#", appDelegate.SelectedIDArray);
I've took sample test case similar to your code:
NSString *str1 = #"1,2,3,4,5,6,7,8,9";
NSMutableArray *tempArray = (NSMutableArray*)[str1 componentsSeparatedByString:#","];
NSMutableArray *arr = [NSMutableArray array];
[arr addObjectsFromArray:tempArray];
NSLog(#"%#",arr);
Its working fine for me. Make sure appDelegate.SelectedIDArray is NSMutableArray. Or if you want fresh array simply use
appDelegate.SelectedIDArray = [NSMutableArray arraywitharray:tempArr];
Hope this helps.
I hope you did not forget to alloc appDelegate.SelectedIDArray.
Hello buddy please try this
NSArray *tempArray = [buildingObject.selectedIDString componentsSeparatedByString:#","];
[appDelegate setSelectedIDArray:[tempArray mutableCopy]];
if it didnot work then possibly one of your array is empty.Please check
use it, it will fix if you are using the non arc
appDelegate.SelectedIDArray = [tempArray retain];
I have a very strange behaviour with NSArray.
Firstly, i parsed an XML file and return a valid NSArray with NSDictionary inside:
NSArray *arrayOfDict = [parser parseWithXMLFile:filename];
In debugger it's fully valid. Then, i want to proccess all dictionaries in this array:
NSMutableArray* arrayOfProducts = [[NSMutableArray alloc] init];
for (NSDictionary* dict in arrayOfDict) {
Product* product = [[Product alloc] initWithName:dict[#"name"]
type:dict[#"type"]
imageName:dict[#"image"]
description:dict[#"description"]];
[arrayOfProducts addObject:product];
[product release];
}
And in this loop is a problem: a dict variable has value nil. And i don't know what to do with this. In debugger i evaluate value of arrayOfDict[someIndex] and get a right value, but in the programm itself it doesn't work.
May be it's the problem with MRR, i don't feel myself confidenly while using MRR and there is a mistake of using it.
P.S. I know that using MRR is stupid today, but in this project i must use it.
I'm trying to rewrite one element from self.tableData to another.
my NSMutableArray:
self.tableData = [[NSMutableArray alloc] initWithObjects:
[[Cell alloc] initWithName:#"dawdw" andImage:#"dwddw" andDescription:#"dawdw" andTypes:#"dawwd dawwd" andforWho:#"dwaadw"],
[[Cell alloc] initWithName:#"Kabanos" andImage:#"spodwwdwdrt.jpg" andDescription:#"dwdw" andTypes:#"dwdw dww" andforWho:#"dawwd"],
[[Cell alloc] initWithName:#"dwwd" andImage:#"dwwd" andDescription:#"dwwd" andTypes:#"wdwd daww" andforWho:#"dadawwa"],nil];
NSMutableArray *newarray;
[newarray addObject:self.tableData[0]];
But it's not working, maybe it's a newbie question but i have never before worked with arrays with many objects inside.
With self.tableData[0] i men rewrite object
[[Cell alloc] initWithName:#"dawdw" andImage:#"dwddw" andDescription:#"dawdw" andTypes:#"dawwd dawwd" andforWho:#"dwaadw"],
NSMutableArray *newarray;
[newarray addObject:self.tableData[0]];
The problem with the code above is that you haven't created an array for newArray to point to, so the value of newArray is nil. Do this instead:
NSMutableArray *newarray = [NSMutableArray array];
[newarray addObject:self.tableData[0]];
Now newArray will point to a valid mutable array to which you can add objects.
Also, realize that even with the fixed code, newArray[0] will point to the very same object that you've stored in self.tableData[0], not a copy. If you want it to point to a different object that contains similar data, you should either make a copy of the object or instantiate a new one, e.g.:
[newarray addObject:[self.tableData[0] copy]];
or:
[newarray addObject:[[Cell alloc] initWithName:#"dawdw" andImage:#"dwddw" andDescription:#"dawdw" andTypes:#"dawwd dawwd" andforWho:#"dwaadw"]];
You need to init new array. You can do it like so:
NSMutableArray *newarray = [NSMutableArray array];
The problem here is you didn't initialize newarray. You need to do
newarray = [NSMutableArray array];
But also note that adding self.tableData[0] to it is different from adding another alloc'ed and init'ed Cell to it because the former increases the reference count on self.tableData[0], while the latter creates a new Cell object.
This also means that if you make a new Cell object and add it to the mutable array, and later on modified that object in the mutable array, it wouldn't change the cell in the first array. But if you did it the first way, it would.
While trying to set a single key/value pair in NSMutableDictionary of NSMutableArray like:
[[self.items objectAtIndex:i] setValue:#"value" forKey:#"key"];
self.items is NSMutableArray and it have a list of NSMutableDictionaries
Instead of setting to that single object, it set it to all dictionaries in the list.
I have used this method before. But I don't know what is happening in this case.
I know NSArray have setValue:#"value" forKey:#"key method, but in this case I am using NSMutableArray
Here is a bit more block of code to help clarify my situation:
-(void)setItem:(id)sender
{
for (CellView *cell in self.CollectionView.visibleCells)
{
NSIndexPath *indexPath = [self.CollectionView indexPathForCell:cell];
int i = (indexPath.section * (mainItems.count)/3+ indexPath.row);
if (((UIButton *)sender).tag == i)
{
[[self.items objectAtIndex:i] setValue:#"value" forKey:#"key"];
}
}
}
Call setObject:forKey:, not setValue:forKey:. There is a difference.
Note that NSMutableArray extends NSArray so NSMutableArray has all of the methods of NSArray.
I also recommend you split your line up as well as use modern syntax:
NSMutableDictionary *dict = self.items[i];
dict[#"key"] = #"value";
NSMutableArray is a subclass of NSArray so all the NSArray methods are still there in NSMutatbleArray. You could try pulling it out and putting it back in to figure things out then reassemble your code after...
NSMutableDictionary *d = [self.items objectAtIndex:i];
[d setValue:#"value" forKey:#"key"];
[self.items setObject: d atIndexedSubscript: i];
This is a little more explicit which will allow you to debug it easier (not getting unexpected nils back, etc.).
Ok I got the issue.
I am working on a large pre-existing code. And I come to notice that The MutableDictionary was defined globally and the same object was being added to the MutableArray. So basically all the pointers in the MUtableArray where pointing to a single object.
I'm almost there understanding simple reference counting / memory management in Objective-C, however I'm having a difficult time with the following code. I'm releasing mutableDict (commented in the code below) and it's causing detrimental behavior in my code. If I let the memory leak, it works as expected, but that's clearly not the answer here. ;-) Would any of you more experienced folks be kind enough to point me in the right direction as how I can re-write any of this method to better handle my memory footprint? Mainly with how I'm managing NSMutableDictionary *mutableDict, as that is the big culprit here. I'd like to understand the problem, and not just copy/paste code -- so some comments/feedback is ideal. Thanks all.
- (NSArray *)createArrayWithDictionaries:(NSString *)xmlDocument
withXPath:(NSString *)XPathStr {
NSError *theError = nil;
NSMutableArray *mutableArray = [[[NSMutableArray alloc] init] autorelease];
//NSMutableDictionary *mutableDict = [[NSMutableDictionary alloc] init];
CXMLDocument *theXMLDocument = [[[CXMLDocument alloc] initWithXMLString:xmlDocument options:0 error:&theError] retain];
NSArray *nodes = [theXMLDocument nodesForXPath:XPathStr error:&theError];
int i, j, cnt = [nodes count];
for(i=0; i < cnt; i++) {
CXMLElement *xmlElement = [nodes objectAtIndex:i];
if(nil != xmlElement) {
NSArray *attributes = [NSArray array];
attributes = [xmlElement attributes];
int attrCnt = [attributes count];
NSMutableDictionary *mutableDict = [[NSMutableDictionary alloc] init];
for(j = 0; j < attrCnt; j++) {
if([[[attributes objectAtIndex:j] name] isKindOfClass:[NSString class]])
[mutableDict setValue:[[attributes objectAtIndex:j] stringValue] forKey:[[attributes objectAtIndex:j] name]];
else
continue;
}
if(nil != mutableDict) {
[mutableArray addObject:mutableDict];
}
[mutableDict release]; // This is causing bad things to happen.
}
}
return (NSArray *)mutableArray;
}
Here's an equivalent rewrite of your code:
- (NSArray *)attributeDictionaries:(NSString *)xmlDocument withXPath:(NSString *)XPathStr {
NSError *theError = nil;
NSMutableArray *dictionaries = [NSMutableArray array];
CXMLDocument *theXMLDocument = [[CXMLDocument alloc] initWithXMLString:xmlDocument options:0 error:&theError];
NSArray *nodes = [theXMLDocument nodesForXPath:XPathStr error:&theError];
for (CXMLElement *xmlElement in nodes) {
NSArray *attributes = [xmlElement attributes];
NSMutableDictionary *attributeDictionary = [NSMutableDictionary dictionary];
for (CXMLNode *attribute in attributes) {
[attributeDictionary setObject:[attribute stringValue] forKey:[attribute name]];
}
[dictionaries addObject:attributeDictionary];
}
[theXMLDocument release];
return attributeDictionaries;
}
Notice I only did reference counting on theXMLDocument. That's because the arrays and dictionaries live beyond the scope of this method. The array and dictionary class methods create autoreleased instances of NSArray and NSMutableDictionary objects. If the caller doesn't explicitly retain them, they'll be automatically released on the next go-round of the application's event loop.
I also removed code that was never going to be executed. The CXMLNode name method says it returns a string, so that test will always be true.
If mutableDict is nil, you have bigger problems. It's better that it throws an exception than silently fail, so I did away with that test, too.
I also used the relatively new for enumeration syntax, which does away with your counter variables.
I renamed some variables and the method to be a little bit more Cocoa-ish. Cocoa is different from most languages in that it's generally considered incorrect to use a verb like "create" unless you specifically want to make the caller responsible for releasing whatever object you return.
You didn't do anything with theError. You should either check it and report the error, or else pass in nil if you're not going to check it. There's no sense in making the app build an error object you're not going to use.
I hope this helps get you pointed in the right direction.
Well, releasing mutableDict really shouldn't be causing any problems because the line above it (adding mutableDict to mutableArray) will retain it automatically. While I'm not sure what exactly is going wrong with your code (you didn't specify what "bad things" means), there's a few general things I would suggest:
Don't autorelease mutableArray right away. Let it be a regular alloc/init statement and autorelease it when you return it ("return [mutableArray autorelease];").
theXMLDocument is leaking, be sure to release that before returning. Also, you do not need to retain it like you are. alloc/init does the job by starting the object retain count at 1, retaining it again just ensures it leaks forever. Get rid of the retain and release it before returning and it won't leak.
Just a tip: be sure that you retain the return value of this method when using it elsewhere - the result has been autoreleased as isn't guaranteed to be around when you need it unless you explicitly retain/release it somewhere.
Otherwise, this code should work. If it still doesn't, one other thing I would try is maybe doing [mutableArray addObject:[mutableDict copy]] to ensure that mutableDict causes you no problems when it is released.
In Memory Management Programming Guide under the topic Returning Objects from Methods (scroll down a bit), there are a few simple examples on how to return objects from a method with the correct memory managment.