populating NSMutableArray not working - ios

Hi I have an instance variable NSMutable Array.
I declare it as such
#property (nonatomic, assign) NSMutableArray *list;
In viewDidLoad I instantiate it.
self.list = [NSMutableArray array];
I then make a string consisting of the text of text fields and add it to the array.
NSString * lines = [NSString stringWithFormat:#"%#,%#,%#,%#,%#", [self.crabText text], [self.trawlText text], [self.trapText text], [self.vesselText text], [self.lengthText text]];
[self.list addObject:lines];
This is apart of a function which will keep on adding new values of the text fields into the array.
I display the contents of the array with
int i;
int count;
for (i = 0, count = [self.list count]; i < count; i = i + 1)
{
NSString *element = [self.list objectAtIndex:i];
NSLog(#"The element at index %d in the array is: %#", i, element); // just replace the %# by %d
}
However, the app crashes when I try to print the contents of the array and I get
EXC_BAD_ACCESS_CODE
Any ideas?
Thanks!

Replace your declaration like this :
#property (nonatomic, strong) NSMutableArray *list; // strong and not assign
Initialize your array in your viewDidLoad :
self.list = [NSMutableArray array];
and add one by one your string :
[self.list addObject:self.crabText.text];
[self.list addObject:self.trawlText.text];
....
Next, modify your for loop :
for (int i = 0, i < self.list.count, i++)
{
NSLog(#"The element at index %d in the array is: %#", i, [self.list objectAtIndex:i]);
}

Another way to do this would be to declare the array this way in your header file
#interface yourViewController : UIViewController
{
NSMutableArray* list;
}
#end
Then in the ViewDidLoad
list = [[NSMutableArray alloc] init];
Everything else can be done just as Jordan said. Though I'm not sure if there is a difference in performance between either implementation.

Related

iOS - JSONModel with dynamic key

I am calling a web service which returns dictionary to render the graph. Dictionary structure is
{"1":0,"2":0,"8":0,"9":2,"10":3,"11":0,"12":0}
The problem is keys are dynamic values like 1,2,3 etc which indicates month. Is it possible to represent this in JsonModel?
See you cant create properties at run time as per response structure. But we can smartly use pre-defined things and achieve this. Do following steps:
Create one model class. So your MyCustomModel.h file will look like this
#import <Foundation/Foundation.h>
#interface MyCustomModel : NSObject
#property (nonatomic, retain) NSString * myCustomKey;
#property (nonatomic, retain) NSString * myCustomValue;
#end
This will be your MyCustomModel.m file
#import "MyCustomModel.h"
#implementation MyCustomModel
#synthesize myCustomKey, myCustomValue;
-(id)init {
self = [super init];
myCustomKey = #"";
myCustomValue = #"";
return self;
}
#end
Now lets suppose {"1":0,"2":0,"8":0,"9":2,"10":3,"11":0,"12":0} is NSDictionary and lets say its name is dictionaryResponse
Now do this stuffs:
NSArray *responseKeys = [[NSArray alloc]init];
responseKeys = [dictionaryResponse allKeys];
So your responseKeys will have all keys of response like ["1","2","8","9","10","11","12",]
Now you can iterate loop and create NSMutableArray of model objects as
NSMutableArray *arrayMonthList = [[NSMutableArray alloc]init];
for (int i = 0; i < responseKeys.count; i++) {
MyCustomModel *myModelObject = [[MyCustomModel alloc]init];
myModelObject.myCustomKey = [NSString stringWithFormat:#"%#",[responseKeys objectAtIndex:i]];
myModelObject.myCustomValue = [dictionaryResponse valueForKey:[NSString stringWithFormat:#"%#",[responseKeys objectAtIndex:i]]];
[arrayMonthList addObject:myModelObject];
}
Now arrayMonthList will consist of objects of type MyCustomModel
So you can use it and parse it. Even you can use it to show on UITableView. Following code is written to print values of model properties, you can customise at your expected level.
for (int i = 0; i < arrayMonthList.count; i++) {
MyCustomModel *myModelObject = [arrayMonthList objectAtIndex:i];
NSLog(#"Month is %# and its value is %#",myModelObject.myCustomKey,myModelObject.myCustomValue);
}

Alternative of ArrayList in iOS?

I have parsed a JSON that resulted in array of elements. I wish to store it in a an array just like we would add elements dynamically to arraylist and access it later. What is the alternative of ArrayList in case of iOS for adding elements dynamically and retrieving it later. Is there any other unique options available in iOS for storing and retrieving elements dynamically?
Data1:
Reference number: 1241
InvoiceNumber: 1421241
InvoiceDate: 06-FEB-16
Data2:
Reference number: 3241
InvoiceNumber: 12421
InvoiceDate: 06-FEB-16
Above are the two data with unique elements that I got by parsing a json.
In class A , Im adding the following code to store the nsmutablearray in nsuserdefaults,
for (NSUInteger i = 0; i < savecount; i++) {
NSMutableArray *newArray = [[NSMutableArray alloc] init];
[myArrays addObject:newArray];
[newArray addObject:shipmentReferenceNumber];
[[NSUserDefaults standardUserDefaults] setObject:newArray forKey:#"shipmentReferenceNumber "];
}
In class B, Im trying to access it by using the following code but it returns null
NSString *referenceNumber = [[NSUserDefaults standardUserDefaults] stringForKey:#"referenceNumber"];
In objC and swift, An ArrayList is a NSMutableArray
A hash map like functionality (store key value pairs. keys are unique) is offered by NSDictionary
To used Hash Map with NSArray. Used following code.
In Class A while Storing:
NSMutableArray* arrayList = [[NSMutableArray alloc] init];
for (int i=0; i<savecount; i++) {
NSDictionary* innerDict = [NSDictionary dictionaryWithObjectsAndKeys:your_referenceNo,#"referenceNo",your_InvoiceNumber,#"invoiceNumber",your_InvoiceDate,#"invoiceDate", nil];
[arrayList addObject:innerDict];
}
NSData *encodedObject = [NSKeyedArchiver archivedDataWithRootObject:arrayList];
[[NSUserDefaults standardUserDefaults] setObject:encodedObject forKey:#"data"];
In Class B while retraving:
NSData* data = [[NSUserDefaults standardUserDefaults] objectForKey:#"data"];
NSMutableArray* arrayList = [NSKeyedUnarchiver unarchiveObjectWithData:data];
NSLog(#"Reference No : %#",arrayList[0][#"referenceNo"]);
Edit: to dynamic access into arraylist
for(int i=0; i<[arrayList count];i++){
NSLog(#"Reference No : %#",arrayList[i][#"referenceNo"]);
}
Thanks
NSMutableArray can be used if the array is editable, else an NSArray.
Forgive me if I misunderstand what you are trying to achieve, but I would consider creating a Data model object:
#interface Data : NSObject
#property (nonatomic) NSInteger referenceNumber;
#property (nonatomic) NSInteger invoiceNumber;
#property (strong, nonatomic) NSString *invoiceDate;
#end
You could then create an array of data objects:
#property (strong, nonatomic) NSMutableArray <Data *> *dataArray;
Here a data struct, which dynamically increased and gets by index, basically, it is a normal linked list class, with a dynamic array inside to provide getting data by index, it duplicates the space, but you may delete the linked list after updating the array, see the code:
struct LinkedNode
{
long data;
LinkedNode* next;
};
class LinkedList
{
public:
LinkedList();
~LinkedList();
LinkedNode* head;
long Count;
long * Data;
void add(long data);
void update();
//long get(long index);
};
LinkedList::LinkedList(){
this->Count = 0;
this->head = NULL;
}
LinkedList::~LinkedList(){
LinkedNode * temp;
while(head){
temp= this->head ;
head = head->next;
delete temp;
}
if (Data)
delete [] Data; Data=NULL;
}
void LinkedList::add (long data){
LinkedNode * node = new LinkedNode();
node->data = data;
node->next = this->head;
this->head = node;
this->Count++;}
void LinkedList::update(){
this->Data= new long[this->Count];
long i = 0;
LinkedNode * node =this->head;
while(node){
this->Data[i]=node->data;
node = node->next;
i++;
}
}
If you use this, please refer to my work https://www.liebertpub.com/doi/10.1089/big.2018.0064

NSMutableArray with multiple properties [closed]

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 have a rather large NSMutableArray with class files. The array has multiple properties like so:
[Element elementsName:#"Lithium" elementsNumber:#"3"],
[Element elementsName:#"Beryllium" elementsNumber:#"4"],
[Element elementsName:#"Boron" elementsNumber:#"5"],
[Element elementsName:#"Carbon" elementsNumber:#"6"],
[Element elementsName:#"Nitrogen" elementsNumber:#"7"],
[Element elementsName:#"Oxygen" elementsNumber:#"8"],
[Element elementsName:#"Fluorine" elementsNumber:#"9"],
[Element elementsName:#"Neon" elementsNumber:#"10"],
I need to be able to access the elementsName and the elementsNumber separately.
Would anybody know how to do this, and is it possible? Thanks! (More code below!)
Element.h (class for the array)
#interface Element : NSObject
{
NSString *name;
NSString *number;
}
#property(nonatomic, copy)NSString *name;
#property(nonatomic, copy)NSString *number;
+(id)elementsName:(NSString *)name elementsNumber:(NSString *)number;
and Element.m
#import "Element.h"
#implementation Element;
#synthesize number;
#synthesize name;
+(id)elementsName:(NSString *)name elementsNumber:(NSString *)number
{
Element *newElement = [[self alloc] init];
newElement.name = name;
newElement.number = number;
return newElement;
}
#end
You could try something like this:
for(int i = 0; i<elementArray.count; i++)
{
NSString *name = ((Element*)[elementArray objectAtIndex:i]).name;
NSString *number = ((Element*)[elementArray objectAtIndex:i]).number;
}
Is this what you are looking for? :
// returns an array of all numbers
NSArray *numbers = [elementArray valueForKey:#"number"];
// returns an array of all names
NSArray *names = [elementArray valueForKey:#"name"];
This is called KVC (Key-Value Coding) and uses strings to access an object's property. This example goes through all of the elements in the array and asks for its number or name property, then returns the result as an array.
This could also be achieved with a for-loop. I am mainly including this to give you an idea of what is happening:
NSMutableArray *names = [NSMutableArray array];
NSMutableArray *numbers = [NSMutableArray array];
for (Element *e in elementsArray) {
[names addObject:e.name];
[numbers addObject:e.number];
}
Obviously this would work as well, but why not use valueForKey: when it is designed for this?
You can use NSDictionary instead.
NSArray *arrOfDic=#[#{#"elementsName":#"Lithium",#"elementsNumber":#"3"},
#{#"elementsName":#"Beryllium",#"elementsNumber":#"4"},
#{#"elementsName":#"Boron",#"elementsNumber":#"5"},
#{#"elementsName":#"Carbon",#"elementsNumber":#"6"},
#{#"elementsName":#"Nitrogen",#"elementsNumber":#"7"}];
NSLog(#"dic is %#",arrOfDic);
Get your elements and their number as
NSLog(#"FirstObject is Element = %# Element No = %#",arrOfDic[0][#"elementsName"],arrOfDic[0][#"elementsNumber"]);
NSLog(#"SecondObject is Element = %# Element No = %#",arrOfDic[1][#"elementsName"],arrOfDic[1][#"elementsNumber"]);
And whats wrong with your file it is working fine.
NSMutableArray *mArray=[[NSMutableArray alloc] init];
[mArray addObject:[Element elementsName:#"Lithium" elementsNumber:#"3"]];
[mArray addObject:[Element elementsName:#"Beryllium" elementsNumber:#"5"]];
[mArray addObject:[Element elementsName:#"Boron" elementsNumber:#"6"]];
Element *element=(Element*)[mArray objectAtIndex:0];
NSLog(#"My first element is name = %# ,number = %#",element.name,element.number);
output---
My first element is name = Lithium ,number = 3

ios - convert NSArray to NSDictionary

i want to convert an nsarray to nsdictionary i'm using to
- (NSDictionary *) indexKeyedDictionaryFromArray:(NSArray *)array
{
id objectInstance;
NSUInteger indexKey = 0;
NSMutableDictionary *mutableDictionary = [[NSMutableDictionary alloc] init];
for (objectInstance in array)
[mutableDictionary setObject:objectInstance forKey:[NSNumber numberWithUnsignedInt:indexKey++]];
return (NSDictionary *)[mutableDictionary autorelease];
}
output result is:
{
0 = {
Event = "";
ID = 1; };
3 = {
Event = "";
ID = 77; };
2 = {
Event = "";
ID = 23; };
1 = {
Event = "";
ID = 45; };
7 = {
Event = "";
ID = 10; };
5 = {
Event = "";
ID = 26; };
6 = {
Event = "";
ID = 27;
};
8 = {
Event = "";
ID = 28;
};
}
After convert to nsdictionary, the order of nsdictionary isn't true to the original order, i want to display the same order in nsarray, i don't know how? can you help me?
NSDictionary does not have an order. Sort the keys and use them to access the entries.
If I understand correctly from your responses to #ACB and #Zaph in the comments, you want to do the following:
Maintain a collection mapping integer keys to object values which is ordered by the keys.
If I'm understanding correctly, an array won't be good enough for your purposes because the integer keys in an array allow for no "holes". You, however, need to allow for holes: in the output in your question, the key-value pair for 4 is missing. For this reason, a dictionary is appealing to you.
Unfortunately, a dictionary will not allow you to maintain an ordering on the key-value pairs it contains, as #Zaph points out. You say, however, you just want to display the values in the dictionary ordered by the keys in a UITableView. Presumably, it is unimportant the order in which the dictionary is serialized to disk (using writeToFile:atomically:) so long as the contents of the dictionary are displayed in the correct order in the table view.
A dictionary can be used for this purpose as follows. First, we'll need a class PFXKeyValuePair;
#interface PFXKeyValuePair : NSObject
#property (nonatomic) id<NSCopying> key;
#property (nonatomic) id value;
+ (PFXKeyValuePair *)pairWithValue:(id)value forKey:(id<NSCopying>)key;
+ (NSArray *)pairsWithValues:(NSArray *)values forKeys:(NSArray *)keys;
#end
#implementation PFXKeyValuePair
+ (PFXKeyValuePair *)pairWithValue:(id)value forKey:(id<NSCopying>)key
{
PFXKeyValuePair *pair = [[PFXKeyValuePair alloc] init];
pair.value = value;
pair.key = key;
return pair;
}
+ (NSArray *)pairsWithValues:(NSArray *)values forKeys:(NSArray *)keys
{
NSAssert(values.count == keys.count, #"The array of values must be the same size as the array of keys.");
NSUInteger count = values.count;
NSMutableArray *mutableRes = [NSMutableArray array];
for (NSUInteger index = 0; index < count; index++) {
PFXKeyValuePair *pair = [PFXKeyValuePair pairWithValue:values[index] forKey:keys[index]];
[mutableRes addObject:pair];
}
return [mutableRes copy];
}
#end
Second, we'll need a category method on NSDictionary:
#interface NSDictionary (PFXAdditions)
- (NSArray *)pfx_keyValuePairsSortedByKeyUsingComparator:(NSComparator)comparator;
#end
#implementation NSDictionary (PFXAdditions)
- (NSArray *)pfx_keyValuePairsSortedByKeyUsingComparator:(NSComparator)comparator
{
NSArray *sortedKeys = [self.allKeys sortedArrayUsingComparator:comparator];
NSArray *sortedValues = [self objectsForKeys:sortedKeys notFoundMarker:[NSNull null]];
return [PFXKeyValuePair pairsWithValues:sortedValues forKeys:sortedKeys];
}
#end
Note: In the above, PFX and pfx are placeholders. You ought to replace them with prefixes appropriate to your project.
We can then use this category method when to populate our UITableView. Let's say we have a property
#property (nonatomic) NSDictionary *events;
And let's assume that the table view has only one section in which these events will be shown.
Then we can implement –tableView:numberOfRowsInSection: in our UITableViewController subclass as follows:
– (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.events.count;
}
And within our implementation of –tableView:numberOfRowsInSection: we can determine the appropriate entry in the dictionary to use as follows:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//...
NSArray *pairs = [self.events pfx_keyValuePairsSortedByKeyUsingComparator:^(id obj1, id obj2) {
NSNumber *key1 = (NSNumber *)obj1;
NSNumber *key2 = (NSNumber *)obj2;
return [key1 compare:key2];
}];
NSUInteger index = [indexPath indexAtPosition:1];
PFXKeyValuePair *pair = pairs[index];
/*
At this point, pair.value will be a dictionary as in your output above
holding a value for the key #"Event" and a value for the key #"ID".
*/
//...
}
This could be made faster by making pairs a property and only computing it when necessary (for example, by only computing pairs just prior to reloading the table's data).
Note: Using this approach, the dictionary will still not be serialized to disk (when calling -writeToDisk:atomically:) "in order" and your output will still look the same as in your question. However, this does not matter: when the data is displayed to the user in the table view, the data will be ordered as you're hoping.
This is example one of the exmple get the emplyee list NSMutableArray and create NSMutableDictionary.......
NSMutableArray *emloyees = [[NSMutableArray alloc]initWithObjects:#"saman",#"Ruchira",#"Rukshan",#"ishan",#"Harsha",#"Ghihan",#"Lakmali",#"Dasuni", nil];
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
for (NSString *word in emloyees) {
NSString *firstLetter = [[word substringToIndex:1] uppercaseString];
letterList = [dict objectForKey:firstLetter];
if (!letterList) {
letterList = [NSMutableArray array];
[dict setObject:letterList forKey:firstLetter];
}
[letterList addObject:word];}NSLog(#"dic %#",dict);

How to replace an object in an NSMutableArray at a given index with a new object

I have an NSMutableArray object (retained, synthesized as all) that is initiated just fine and I can easily add objects to it using the addObject: method. But if I want to replace an object at a certain index with a new one in that NSMutableArray, it doesn't work.
For example:
ClassA.h:
#interface ClassA : NSObject {
NSMutableArray *list;
}
#property (nonatomic, copy, readwrite) NSMutableArray *list;
#end
ClassA.m:
#import "ClassA.h"
#implementation ClassA
#synthesize list;
- (id)init
{
[super init];
NSMutableArray *localList = [[NSMutableArray alloc] init];
self.list = localList;
[localList release];
//Add initial data
[list addObject:#"Hello "];
[list addObject:#"World"];
}
// Custom set accessor to ensure the new list is mutable
- (void)setList:(NSMutableArray *)newList
{
if (list != newList)
{
[list release];
list = [newList mutableCopy];
}
}
-(void)updateTitle:(NSString *)newTitle:(NSString *)theIndex
{
int i = [theIndex intValue]-1;
[self.list replaceObjectAtIndex:i withObject:newTitle];
NSLog((NSString *)[self.list objectAtIndex:i]); // gives the correct output
}
However, the change remains true only inside the method. from any other method, the
NSLog((NSString *)[self.list objectAtIndex:i]);
gives the same old value.
How can I actually get the old object replaced with the new one at a specific index so that the change can be noticed from within any other method as well.
I even modified the method like this, but the result is the same:
-(void)updateTitle:(NSString *)newTitle:(NSString *)theIndex
{
int i = [theIndex intValue]-1;
NSMutableArray *localList = [[NSMutableArray alloc] init];
localList = [localList mutableCopy];
for(int j = 0; j < [list count]; j++)
{
if(j == i)
{
[localList addObject:newTitle];
NSLog(#"j == 1");
NSLog([NSString stringWithFormat:#"%d", j]);
}
else
{
[localList addObject:(NSString *)[self.list objectAtIndex:j]];
}
}
[self.list release];
//self.list = [localList mutableCopy];
[self setList:localList];
[localList release];
}
Please help out guys :)
This does the trick:
[myMutableArray replaceObjectAtIndex:index withObject:newObject];
OK, there are a few bits of confusion here.
You don't need to take a mutableCopy of a newly created NSMutableArray to make it mutable. It's already mutable -- the clue is in the name. You only need to do that in the setter if you want the property to have copy semantics (which you've set, and may have good reason for, of course). But you certainly wouldn't need to do it as shown in your updated updateTitle code, and doing so leaks localList.
Also, you're mixing together property access via self.list and direct use of list in the same method. This is not invalid, but it's bad practice, because it means whatever other stuff the accessor methods do is being randomly bypassed. It's common for properties like this to do everything through self except in the accessors themselves, or in dealloc, and possibly in init (opinions seem to differ on this), where you would access the ivar directly.
Also, never call [self.list release] -- the property accessor doesn't give its caller ownership. Doing this will end in tears, mark my words.
None of this answers the real question, which is why is your change disappearing. The original updateTitle code does not explain this as far as I can see -- it should work. So I suspect that somewhere else you are calling self.list = theOriginalList and hence undoing your change.
Update:
Just for the sake of argument, I'm going to post what I think the code you posted is probably meant to look like. I've preserved your use of a string to pass the index to updateTitle, but I'd like to point out that doing it this way is wrong. It's a number, you should pass it as such. Even if the number comes from a text field or something, that's the caller's concern; the class interface should specify a number. Similarly the apparent change from 1-based to 0-based indexing. Please do not do this sort of thing implicitly, it is a recipe for weeping and gnashing of teeth.
ClassA.h:
#import <Cocoa/Cocoa.h>
#interface ClassA : NSObject
{
NSMutableArray* list;
}
- (void) setList:(NSMutableArray*)newList;
- (void) updateTitle:(NSString*)newTitle forIndex:(NSString*)theIndex;
#property (nonatomic, copy, readwrite) NSMutableArray* list;
#end
ClassA.m:
#import "ClassA.h"
#implementation ClassA
#synthesize list;
- (id) init
{
if ( self = [super init] )
{
list = [[NSMutableArray alloc] init];
[list addObject:#"Hello "];
[list addObject:#"World"];
}
return self;
}
- (void) setList:(NSMutableArray*) newList
{
if ( list != newList )
{
[list release];
list = [newList mutableCopy];
}
}
- (void) updateTitle:(NSString*)newTitle forIndex:(NSString*)theIndex
{
int i = [theIndex intValue] - 1;
[self.list replaceObjectAtIndex:i withObject:newTitle];
}
- (void) dealloc
{
[list release];
[super dealloc];
}
#end
This cleans up various issues, but note that updateTitle is mostly the same. If you drop all this in and the change still doesn't survive, you are definitely resetting list somewhere.
A more straight answer would be:
self.list[i] = newTitle;
This just works like
[self.list replaceObjectAtIndex:i withObject:newTitle];
Look at this line:
#property (nonatomic, copy, readwrite) NSMutableArray *list;
The copy means that whenever you access self.list, you don't get the "_list" instance variable of your object, but a copy of that list. If you write [self.list replaceObjectAtIndex... ] you replace an object in that copy of your list; the original _list is unchanged. Just use
#property (nonatomic, strong, readwrite) NSMutableArray *list;
And to avoid confusion, remove the "list" instance variable and the #synthesize statement, then use _list to access the instance variable.
For Swift you could try:
//if you have indexPath
self.readArray.removeAtIndex((indexPath?.row)!)
self.readArray.insert(tempDict, atIndex: (indexPath?.row)!)
//tempDict is NSDictionary object.
Finally Got Some Perfect Code,
let DuplicateArray: NSArray = array
let DuplicateMutableArray: NSMutableArray = []
DuplicateMutableArray.addObjectsFromArray(DuplicateArray as [AnyObject])
var dic = (DuplicateMutableArray[0] as! [NSObject : AnyObject])
dic["is_married"] = "false"
DuplicateMutableArray[self.SelectedIndexPath] = dic
array = []
array = (DuplicateMutableArray.copy() as? NSArray)!
//Output Will Be Like
array = [
{
"name": "Kavin",
"Age": 25,
"is_married": "false"
},
{
"name": "Kumar",
"Age": 25,
"is_married": "false"
}
]

Resources