Default list in Objective C? - objective-c

I want to store data at run time, I can have a linked list and add at runtime, however as I am new to IOS and objective C, do we have any default list in which we can add our datas, (Datas are two stings and an integer).

Cocoa provides NSArray and NSMutableArray, a pair of ordered containers similar to Java's ArrayList and C#'s List. You can add values to NSMutableArray, and it will grow as you add more elements; NSArray is read-only.

You can use .plist files to store your data.
Read more 'Loading data from .plist files', 'How to use plist in iphone?' or google it like 'load data from .plist'. However you can create NSArray or something like this at run time. If you want dive deeper you must read ObjC Collections Programming Topics

Make a class for your data with default properties and make sure it inherits NSObject then use NSMUtableArray to add/remove elements to the list.
// in the .h file of your object
#interface MyObject : NSObject {
NSString* strAttribute1;
// add more attributes as you want
}
#property (nonatomic, retain) NSString* strAttribute1;
#end
// then in the .m file
// do not forget the #import ""
#implement MyObject
#synthesize strAttribute1;
// override the dealloc to release the retained objects
#end
then in your code where you want to make a list of this object
NSMutableArray* myArray = [[NSMutableArray alloc] init];
// add elements and iterate through them
// do not forgot to free the memory if you are not using ARC
[myArray release];

You can use NSArray or NSMutableArray or NSDictionary or NSMutableDictionary depending on your needs.
NSArray:
NSArray *myArray;
NSDate *aDate = [NSDate distantFuture];
NSValue *aValue = [NSNumber numberWithInt:5];
NSString *aString = #"a string";
myArray = [NSArray arrayWithObjects:aDate, aValue, aString, nil];
NSMutableArray:
NSMutableArray *myArray = [[NSMutableArray alloc] init];
NSDate *aDate = [NSDate distantFuture];
NSValue *aValue = [NSNumber numberWithInt:5];
NSString *aString = #"a string";
[myArray addObject:aDate];
[myArray addObject:aValue];
[myArray addObject:aString];
NSDictionary:
NSDictionary * myDict = [NSDictionary dictionaryWithObjects:aDate, aValue, aString forKeys:firstDate, firstValue, firstString];
NSMutableDictionary:
NSString *aString = #"a string";
NSDate *aDate = [NSDate distantFuture];
NSValue *aValue = [NSNumber numberWithInt:5];
myDict = [[NSMutableDictionary alloc] init];
[myDict setObject:aString forKey:firstString];
[myDict setObject:aDate forKey:firstDate];
[myDict setObject:aValue forKey:firstValue];

Related

Subdividng an Array of Core data objects by attribute

I have an array of core data objects that have a time(date) attribute.
What I want to do is place all the core data objects that have the same time into separate arrays and then create an array of those arrays. If no other object has the same time then that object will be in an array by itself.
i.e If the array of core data objects had 3 objects with time 08:00 and 1 object with time attribute 09:00 then I want to create one array with the first 3 objects(time 08:00) and a separate array with the last object (time 09:00). Then I want to create an array of those arrays which should be easy enough. Start: [8,8,8,9] Finish: [[8,8,8][9]]
I am struggling most with how to iterate through my original array and pull out all the objects with the same time and then put those objects in their own array.
One of many ways to do this is using a NSDictionary object where the time is a key and the corresponding object is an array of core data objects that have this time. The core data objects are iterated once.
NSArray *data = core data objects
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
for (ManagedObjectClass *object in data) {
NSDate *time = object.time;
// convert time to time without date
NSMutableArray *array = dictionary[time];
if (!array) {
array = [NSMutableArray array];
dictionary[time] = array;
}
[array addObject:object];
}
NSArray *array = dictionary.allValues;
Another way to do this if the time doesn't need conversion: sort the core data objects by time, iterate the objects, start a new subarray when the time changes and add the object to the subarray.
NSArray *data = core data objects
NSArray *sortedData = [data sortedArrayUsingDescriptors:#[[NSSortDescriptor sortDescriptorWithKey:#"time" ascending:YES]]];
NSMutableArray *array = [NSMutableArray array];
NSMutableArray *subarray = nil;
NSDate *prevTime = nil;
for (ManagedObjectClass *object in sortedData) {
NSDate *time = object.time;
if (![time isEqualToDate:prevTime]) {
subarray = [NSMutableArray array];
[array addObject:subarray];
}
[subarray addObject:object];
prevTime = time;
}
You can do some thing like this:
Add a transient property in your coredata object.
Eliminate the minutes and seconds from your date in transient property.
Get distinct objects based on your transient property.
Filter objects from your main array and add them in a separate array.
Finally add them in final array.
Implementation can be like this:
MyObject *myObject1 = [[MyObject alloc] initWithDate:[NSDate dateWithTimeIntervalSinceNow:10*60]];
MyObject *myObject2 = [[MyObject alloc] initWithDate:[NSDate dateWithTimeIntervalSinceNow:10*60]];
MyObject *myObject3 = [[MyObject alloc] initWithDate:[NSDate dateWithTimeIntervalSinceNow:180*60]];
MyObject *myObject4 = [[MyObject alloc] initWithDate:[NSDate dateWithTimeIntervalSinceNow:120*60]];
MyObject *myObject5 = [[MyObject alloc] initWithDate:[NSDate dateWithTimeIntervalSinceNow:120*60]];
NSMutableArray *myObjects = [NSMutableArray arrayWithObjects:myObject1,myObject2,myObject3,myObject4,myObject5, nil];
NSArray *distinctObjects = [myObjects valueForKeyPath:#"#distinctUnionOfObjects.transientDate"];
NSMutableArray *finalArray = [NSMutableArray array];
for(NSDate *aDate in distinctObjects) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"transientDate == %#", aDate];
NSArray *filteredArray = [myObjects filteredArrayUsingPredicate:predicate];
[finalArray addObject:filteredArray];
}
NSLog(#"distintobjects: %#", finalArray);
Here is how MyObject looks like:
#import <Foundation/Foundation.h>
#interface MyObject : NSObject
{
}
#property(nonatomic, strong) NSDate *myDate;
#property(nonatomic, strong) NSDate *transientDate;
- (id)initWithDate:(NSDate *)aDate;
#end
#import "MyObject.h"
#implementation MyObject
- (id)initWithDate:(NSDate *)aDate {
self = [super init];
self.myDate = aDate;
return self;
}
- (NSDate *)transientDate {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd-MM-yyyy HH"];
return [dateFormatter dateFromString:[dateFormatter stringFromDate:self.myDate]];
}
- (NSString *)description
{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd-MM-yyyy HH:mm"];
return [NSString stringWithFormat:#"transientDate: %#", [dateFormatter stringFromDate:self.transientDate]];
}
#end
Here is the final output:

Sort NSMutableArray Of multiple Objects without keys

I have a NSMutableArray of objects, below is the struct:
//object at index i
locations {
NSString* address;
NSString* state;
NSNumber* distance;
}
I have 10000 object like the above structure in the NSMutableArray.
How do order this array so that the locations are in order by the NSNumber distance?
I tried this:
lowToHigh = [NSSortDescriptor sortDescriptorWithKey:#"distance" ascending:YES];
[locationArray sortUsingDescriptors:[NSArray arrayWithObject:lowToHigh]];
is using the sortDescriptorWithKey:#"distance" wrong? since distance isn't actually a key, it NSNumber* distance.
edit in my header #property (strong, nonatomic)NSNumber* _distance; and then #synthesize _distance = distance; in my methods file but this is in locationObjects.* object class. Then I import this in my current class I am doing this sorting. Is that an issue?
How I import is locationObjects* locObj = [[locationObjects alloc] init];
This is what I use:
NSSortDescriptor *lowToHigh = [[NSSortDescriptor alloc] initWithKey:#"distance"
ascending:YES];
NSArray *mySortDescriptors = [NSArray arrayWithObject:lowToHigh];
NSArray *sortedArray = [locationArray sortedArrayUsingDescriptors:mySortDescriptors];

NSArray filled with bool

I am trying to create an NSArray of bool values. How many I do this please?
NSArray *array = [[NSArray alloc] init];
array[0] = YES;
this does not work for me.
Thanks
NSArrays are not c-arrays. You cant access the values of an NSArray with array[foo];
But you can use c type arrays inside objective-C without problems.
The Objective-C approach would be:
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:[NSNumber numberWithBool:YES]];
//or
[array addObject:#(NO)];
...
BOOL b = [[array objectAtIndex:0] boolValue];
....
[array release];
EDIT: New versions of clang, the now standard compiler for objective-c, understand Object subscripting. When you use a new version of clang you will be able to use array[0] = #YES
Seems like you've confused c array with objc NSArray. NSArray is more like a list in Java, into which you can add objects, but not values like NSInteger, BOOL, double etc. If you wish to store such values in an NSArray, you first need to create a mutable array:
NSMutableArray* array = [[NSMutableArray alloc] init];
And then add proper object to it (in this case we'll use NSNumber to store your BOOL value):
[array addObject:[NSNumber numberWithBool:yourBoolValue]];
And that's pretty much it! If you wish to access the bool value, just call:
BOOL yourBoolValue = [[array objectAtIndex:0] boolValue];
Cheers,
Pawel
Use [NSNumber numberWithBool: YES] to get an object you can put in the collection.

How to deal with booleans in NSMutableArrays?

Can someone tell me why my application crashes here ?
and why it does not crash when i replace the YES objects with NSString values ?
all i want to do is to store boolean data into array and to modify these data later,
can someone please tell me how to do this ?
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableArray* arr = [[NSMutableArray alloc] initWithObjects:YES, YES, YES, YES, nil];
NSLog([arr objectAtIndex:1]);
}
YES and NO are BOOLs, which is not an Objective-C class. Foundation containers can only store Objective-C objects.
You need to wrap them in an NSNumber, like:
NSNumber* yesObj = [NSNumber numberWithBool:YES];
NSMutableArray* arr = [[NSMutableArray alloc] initWithObjects:
yesObj, yesObj, yesObj, yesObj, nil];
NSLog(#"%d", [[arr objectAtIndex:1] boolValue]);
The reason why it accepts NSString is because an NSString is a kind of Objective-C class.

How add data from NSMutableString into NSArray?

is it an possible to add a value from an NSMutableString into an NSArray? Whats the snippet?
Actually, Mike is wrong. If you want to instantiate an NSArray with a single NSMutableString object, you can do the following:
NSMutableString *myString; //Assuming your string is here
NSArray *array = [NSArray arrayWithObject:myString];
There is no arrayWithElements in NSArray (see NSArray documentation)
If you want to instantiate an NSArray with a single NSMutableString object, you can do the following:
NSString *myString; //Assuming your string is here
NSArray *array = [NSArray arrayWithObjects:myString,nil];
Note that NSArray will be immutable - that is, you can't add or remove objects to it after you've made it. If you want the array to be mutable, you'll have to create an NSMutableArray. To use an NSMutableArray in this fashion, you can do the following:
NSString *myString; //Assuming your string is here
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:myString];
NSArray is immutable, so you cannot add values to it. You should use NSMutableArray in order to do that with the addObject: method.
NSMutableString *str = ...
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:str];
// You must use NSMutableArray to add Object to array
NSMutableArray *tableCellNames;
// arrayWithCapacity is a required parameter to define limit of your object.
tableCellNames = [NSMutableArray arrayWithCapacity:total_rows];
[tableCellNames addObject:title];
NSLog(#"Array table cell %#",tableCellNames);
//Thanks VKJ
An elegant solution would be this:
NSMutableString *str; //your string here
NSArray *newArray = #[str];
Using the new notation, it's a piece of cake.