Alternative of ArrayList in iOS? - 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

Related

NSArray is not saving in NSUserDefaults [duplicate]

This question already has answers here:
How to store custom objects in NSUserDefaults
(7 answers)
Closed 9 years ago.
I am making a high score manager.
I load and save as follows:
-(void)load
{
NSMutableArray* scores = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:HIGH_SCORE_KEY]];
if(scores == nil)
{
highscores = [NSMutableArray array];
}
else
{
highscores = scores;
}
}
-(void)save
{
[[NSUserDefaults standardUserDefaults] setObject:highscores forKey:HIGH_SCORE_KEY];
}
I am storing HighScore objects:
#import <Foundation/Foundation.h>
#interface HighScore : NSObject
{
int score;
NSString* name;
}
-(int)score;
-(NSString*)name;
-(id)init;
-(id)initWithName:(NSString*)playerName andScore:(int)playerScore;
-(BOOL)isEqual:(id)object;
-(BOOL)isLessThan:(id)object;
#end
There is nothing particularly complex about this class. However, when I load, the load does not return nil but returns an empty array, indicating to me that serializing probably failed for some reason.
Any ideas?
Thanks
NSUserDefaults always returns immutable objects, even if the original object was mutable. It's in the documentation for objectForKey:
The returned object is immutable, even if the value you originally set was mutable.
You will need to create a copy of the returned object before you modify it, using [NSMutableArray arrayWithArray:]
Probably also best to use the arrayForKey method of NSUserDefaults if you're retrieving an array. Docs here: http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/Reference/Reference.html
You can only store objects in NSUserDefaults. So you have to convert the array to an NSArray. However, NSArrays also only store objects, so you need to store the long values encapsulated in an NSNumber object:
//saving
NSUserDefaults *standardDefaults = [NSUserDefaults standardUserDefaults];
NSMutableArray *arrayObj = [[NSMutableArray alloc] init];
long *arr;
arr = new long [10];
for(int i = 0 ; i<10 ; i++) {
[arrayObj addObject:[NSNumber numberWithLong:arr[i]]];
}
[standardDefaults setObject:arrayObj forKey:#"longArray"];
[arrayObj release];
//reading
NSUserDefaults *standardDefaults = [NSUserDefaults standardUserDefaults];
NSArray *arrayObj = [standardDefaults objectForKey:#"longArray"];
long *arr;
arr = new long [10];
for(int i = 0 ; i<10 ; i++) {
arr[i] = [(NSNumber*)[arrayObj objectAtIndex:i] longValue];
}

populating NSMutableArray not working

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.

Append NSStrings and NSNumber to NSMutableArrays and make NSMutable dictionary

I'm getting data from SQL server in following variables in one class:
#property(retain,nonatomic) NSString* trainingName;
#property(retain,nonatomic) NSNumber* trainingCount;
In other class,I want to append this value in NSMutableArray and finally make a dictonary.I'm doing this as following:
-(void)getTrainingDetails
{
MyTestSp_GetTrainingCountsList *objReturnTrainings = [MyTestSp_GetTrainingCounts findAll];
NSMutableArray *trainingNames = [[NSMutableArray alloc]init];
NSMutableArray *trainingCounts = [[NSMutableArray alloc]init];
NSMutableDictionary *dictTrainings = [[NSMutableDictionary alloc]init];
if ([objReturnTrainings length] > 0)
{
for (MyTestSp_GetTrainingCounts *obj in objReturnTrainings)
{
// get the values and assign to NSMutable array
trainingNames = trainingName;
trainingCounts = trainingCount;
//Make the dictionary.
}
}
}
Is this the correct way of doing and how can I put this in dictionary?
Please help.
You appear to be trying to set your array directly to your number / string (which you aren't actually getting out of obj so your code shouldn't compile...). You also don't need the arrays to create the dictionary. You can just do:
for (MyTestSp_GetTrainingCounts *obj in objReturnTrainings)
{
dictTrainings[obj.trainingName] = obj.trainingCount;
}

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

Is it possible to add values with duplicate keys to NSDictionary?

I have something like this:
#interface Person : NSObject
{
NSString *fname;
NSString *lname;
}
NSString *keys = #"a","a","b","b","b"....";
for(NSString *key in keys)
{
Person *newPerson; //alloc new person
[myMutableDictionary setValue:newPerson forKey:key];
}
The above code will override the value with same key since NSDictionary doesn't allow duplicate keys. How can I do this?
I can do the above code by NSMutableArray, as in [array addObject:newPerson]; but it takes longer to fetch for (Key,value) as opposed to NSDictionary? My data is about 400,000 items, Any idea on how to do this efficiently? I need to load it once and do many fetches on it - No coreData, I tried it, its slow.
If you use an NSMutableArray as a key you can add multiple Person objects for the same key.
NSString *keys = #"a","a","b","b","b", ...;
for(NSString *key in keys)
{
Person *newPerson; //alloc new person
NSMutableArray *people;
if(!(people = [myMutableDictionary objectForKey:key]))
{
people = [NSMutableArray array];
[myMutableDictionary setValue:people forKey:key];
}
[people addObject:newPerson];
}

Resources