Obj C - Accessing custom class properties from and array of class objects - ios

I have a custom object class with some properties lets say.
#property (nonatomic,retain) NSString *Name;
#property (nonatomic,retain) NSString *ImgURL;
#property (nonatomic,retain) NSArray *Messages;
I then go through a loop and populate the data and add each instance to an array like this
for(NSDictionary *eachEntry in details)
{
ClientData *client;
client.Name = [eachEntry objectForKey:#"name" ];
client.ImgURL = [eachEntry objectForKey:#"img"];
client.Messages = [eachEntry objectForKey:#"message" ];
[_Data addObject:client];
}
now in a table i want to display some of this data in a list, how can i get access to each property by name not key or index.
so at the moment i have this in my cellForRowAtIndexPath
NSString *name = [[self.Data objectAtIndex:indexPath.row] objectForKey:#"name"];
obviously this doesn't work because i haven't set keys
and i don't want to do this
NSString *name = [[self.Data objectAtIndex:indexPath.row] objectAtIndex:1];
How can i access Client.Name etc

self.Data is an array of ClientData objects so you can just do:
NSString *Name = ((ClientData *)[self.Data objectAtIndex:indexPath.row]).Name;
or:
ClientData *clientData = self.Data[indexPath.row];
NSString *name = clientData.Name;

Key Value Coding (KVC). Replace objectForKey with valueForKey.

Related

How can I ensure value is in the custom class property at the NSMutableArray?

I create the custom class name with FileModel.
FileModel.h
#import <Foundation/Foundation.h>
#interface FileModel : NSObject
#property (nonatomic, copy) NSString *fileName;
#property (nonatomic, copy) NSString *fileType;
#property (nonatomic, strong) NSDate *editDate;
#property (nonatomic, assign) NSInteger fileSize;
#end
I want to compare the particular string with the fileName.
I create the sample like below .m
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *fileSampleName = [[NSArray alloc] initWithObjects:#"apple.png",#"banana.png",#"cherry.png",#"durian.png",#"grape.png",#"avocado.png", nil];
NSMutableArray *fileData = [NSMutableArray new];
FileModel *fileModel = nil;
for( NSInteger i = 0 ; i < fileSampleName.count ; i++){
fileModel = [FileModel new];
fileModel.fileName = [fileSampleName objectAtIndex:i];
fileModel.fileType = #"photo";
fileModel.fileSize = 0;
fileModel.editDate = [NSDate new];
[fileData addObject:fileModel];
}
// fileData's fileName containsObject #"grape" or not?
}
NSArray has containsObject method.
But How can I check the #"grape" is containsObject using fileData at the custom class property filename?
I known using for loop compare one by one.
Did they have other method to check like containsObject?
--- edit---
I try to using indexOfObjectPassingTest method , But the result always is 1.
BOOL result = [fileData indexOfObjectPassingTest:^ BOOL (id tr,NSUInteger index, BOOL *te){
FileModel *fileModel = (FileModel*)tr;
if([#"orange" isEqualToString: fileModel.fileName]){
*te = YES;
return YES;
}else{
return NO;
}}];
NSLog(#"result:%#",#(result)); // it always return 1
Why? thank you very much.
Take a look that NSArray class reference in Xcode. One method you could use is indexOfObjectPassingTest. There are number of related methods depending on your needs. All take a block that's used to test objects to see if they meet whatever criteria you want. In your case you'd test the fileName string.
So you'd pass in a closure that compared the fileName property of each object to your desired filename.

Getting NSmutableDictionary key from two mutable arrays

I have three mutable arrays
#interface PickeriviewAndTableViewController ()
//Create mutableArray for tableView
#property(strong,nonatomic)NSMutableArray *msgYear;
#property(strong,nonatomic)NSMutableArray *msgSeason;
#property(strong,nonatomic)NSMutableArray *msgCourse;
I want to add element to array msgCourse[ ] using the key generating from the first two arrays msgYear[ ] and msgSeason[ ].
Then I want to populate the msgCourse[] array using a button
- (IBAction)addCourse:(UIButton *)sender {
//To get value from pickerView, prepare for key and contents
NSInteger numRow=[picker selectedRowInComponent:kNumComponent];//0=1st,1=2nd,etc
NSInteger SeaRow=[picker selectedRowInComponent:kSeaComponent];//0=fall,1=spring,2=summer
NSInteger CourseRow=[picker selectedRowInComponent:kCourseComponent];
NSString *num=Number[numRow];
NSString *season=Season[SeaRow];
NSString *course=Course[CourseRow];
NSString *CourseToAdd=[[NSString alloc ]initWithFormat:#"%# ",course];
NSString *SeasonToAdd=[[NSString alloc ]initWithFormat:#"%# ",season];
NSString *YearToAdd=[[NSString alloc ]initWithFormat:#"%# ",num];
// Try to generate key from YearToAdd and SeasonToAdd and fill in content
NSMutableArray *keys = [[NSMutableArray alloc] init];
NSMutableDictionary *contents = [[NSMutableDictionary alloc] init];
NSString *keyFromYearAndSeason = #"Don't_know_what_to_do_here";
[contents setObject:[NSArray arrayWithObjects:#"Don't_know_how", nil] forKey:keyFromYearAndSeason];
[keys addObject:keyFromYearAndSeason];
[self setSectionKeys:keys];
[self setSectionContents:contents];
}
My question is: How to complete my code by replacing these "Don't know how" lines of code here please?
Update: To be more clear, key is generating from msgYear[ ] and msgSeason[ ] e.g. '2001 fall', dictionary is filled with course e.g. 'chemistry','math'.
The link to your other question helped provide context for what you are trying to achieve.
You don't need to create a dictionary or an array inside the addButtton method - you should have your dictionary as a property that is already initialised.
Then, in add button you retrieve the array associated with the key - if the value is nil then you create a new array and put the course in. If the value isn't nil simply add the course to the array.
#property (strong,nonatomic) NSMutableDictionary *tableEntries; // alloc/init this in viewDidLoad
- (IBAction)addCourse:(UIButton *)sender {
//To get value from pickerView, prepare for key and contents
NSInteger numRow=[picker selectedRowInComponent:kNumComponent];//0=1st,1=2nd,etc
NSInteger SeaRow=[picker selectedRowInComponent:kSeaComponent];//0=fall,1=spring,2=summer
NSInteger CourseRow=[picker selectedRowInComponent:kCourseComponent];
NSString *num=Number[numRow];
NSString *season=Season[SeaRow];
NSString *course=Course[CourseRow];
NSString *key=[NSString stringWithFormat:#"%# %#",num,season];
NSMutableArray *courses=self.tableEntries[key];
if (courses == nil) {
courses=[NSMutableArray new];
self.tableEntries[key]=courses;
}
[courses addObject:course];
}
NSDictionarys are unordered, so you need to give some thought to how you want to order the data in your table. You could use an array to hold the keys as in your original code and then sort this array.

Unable to store a NSMutableArray(each instance of array contains a custom object) in NSUserDefaults

It's a custom class:
#import <Foundation/Foundation.h>
#interface timeTable : NSObject
#property (nonatomic) int ID;
#property (nonatomic) NSString * type;
#property (nonatomic) NSString * time;
#property (nonatomic) NSString * busno;
#property (nonatomic) NSString * stops;
// nothing is done in it's .m file not even synthesise
// thats an other class
#import <Foundation/Foundation.h>
#import "timeTable.h"
#interface refreshDatabase : NSObject
#property (strong, nonatomic) NSMutableArray * arrayTimeTable;
#property (strong, nonatomic) timeTable * objectTimeTable;
// in it's .m file i am downloading a JSON formatted array using a
service then i am saving it to NsMutbaleArray
// downloading a json array which contains a rows of data
NSError * error;
NSArray * jsonArray = [NSJSONSerialization JSONObjectWithData:
[safeString dataUsingEncoding:NSUTF8StringEncoding]
options:NSJSONReadingAllowFragments error:&error];
NSLog(#"json Array %#", jsonArray);
// for getting an instance of array
NSDictionary * jsonElement;
for (int i=0; i<jsonArray.count ; i++)
{ // each row will be saved in an object of timetable class then that
// object will be saved to nsmutablearray
jsonElement = [jsonArray objectAtIndex:i];
objectTimeTable = [[timeTable alloc]init];
objectTimeTable.ID = [[jsonElement objectForKey:#"id"]intValue];
objectTimeTable.type = [jsonElement objectForKey:#"type"];
objectTimeTable.time = [jsonElement objectForKey:#"time"];
objectTimeTable.busno = [jsonElement objectForKey:#"busno"];
objectTimeTable.stops = [jsonElement objectForKey:#"stops"];
// adding an instance from JSON Array to our NSmutablearray
[arrayTimeTable addObject:objectTimeTable];
}//end of json Array FOR loop
// our array containnig all the objects will be saved using
//NSUserDefualts
// userDefaults is an object of NSUserDefaults
if(userDefaults)
{ // its not saving it to userdefaults
[userDefaults setObject:arrayToStore forKey:#"ArrayOfTimeTables"];
[userDefaults synchronize];
}
// retrieving the saved array from NSUSerDefaults and printing it
// using slog
timeTable *objPrint = [[timeTable alloc]init];
NSMutableArray *arrayLoader = [userDefaults arrayForKey:#"ArrayOfTimeTables"];
for (int i=0; i<arrayLoader.count ; i++)
{
objPrint = [arrayLoader objectAtIndex:i];
NSLog(#"outSide Printing For LOOP After Loading of tim # %d times havind id =%d type = %# time = %# busno = %# stops = %#",i,objPrint.ID,objPrint.type,objPrint.time,objPrint.busno,objPrint.stops);
}
Thanx a lot in helping me in advance.
Please tell me how to save that array which contains object of timetable class into nsUseDefaults and then how to load it back.
Please help me. I read a lot of similar question and answers, but don't know how to make them work for me.
Use NScoding to encode each of your custom object then add that custom object into an array then encode other and then add it to the array then save that array into NSUserDefaults
encoding and decoding of upper given question
is
the custom class .h file
#import <Foundation/Foundation.h>
#interface timeTable : NSObject<NSCoding>
#property (nonatomic) NSString * ID;
#property (nonatomic) NSString * type;
#property (nonatomic) NSString * time;
#property (nonatomic) NSString * busno;
#property (nonatomic) NSString * stops;
the custom class .m file
#import "timeTable.h"
#implementation timeTable
#synthesize ID;
#synthesize type;
#synthesize time;
#synthesize busno;
#synthesize stops;
-(void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.ID forKey:#"ID"];
[aCoder encodeObject:self.type forKey:#"type"];
[aCoder encodeObject:self.time forKey:#"time"];
[aCoder encodeObject:self.busno forKey:#"busno"];
[aCoder encodeObject:self.stops forKey:#"stops"];
}
-(id)initWithCoder:(NSCoder *)aDecoder
{
if((self = [super init])) {
//decode properties, other class vars
self.ID = [aDecoder decodeObjectForKey:#"ID"];
self.type = [aDecoder decodeObjectForKey:#"type"];
self.time = [aDecoder decodeObjectForKey:#"time"];
self.busno = [aDecoder decodeObjectForKey:#"busno"];
self.stops = [aDecoder decodeObjectForKey:#"stops"];
}
return self;
}
#end
where you encode each custom object one by one and adding it to the array then save that NSMutableArray or NSArray
into NSUserDefaults
encoding a custom object then adding it to array and saving it into user defaults
// encoding a custom object before saving it to array
NSData *encodeTimeTableObj = [NSKeyedArchiver
archivedDataWithRootObject:objectTimeTable];
addObject:encodeTimeTableObj];
//saving it to user Defaults
if(userDefaults)
{
[userDefaults setObject:arrayTimeTable
forKey:#"ArrayOfTimeTables"];
[userDefaults synchronize];
NSLog(#"saving to usedefaults");
}
retriving an array either mutable or non mutable then decoding each of its object
NSMutableArray *arrayLoader = [userDefaults
objectForKey:#"ArrayOfTimeTables"];
NSData * decode = [arrayLoader objectAtIndex:0];
  // in case of upper given custom class Time Table
timeTable *objPrint = [NSKeyedUnarchiver unarchiveObjectWithData:decode];
Use NSArray to get array from NSUSerDefaults as NSUSerDefaults return immuttable array.
If you need NSMutableArray, then convert this NSArray to NSMutableArray.
// retrieving the saved array from NSUSerDefaults and printing it
// using slog
timeTable *objPrint = [[timeTable alloc]init];
NSArray *arrayLoader = [userDefaults arrayForKey:#"ArrayOfTimeTables"];
for (int i=0; i

Remove Duplicate Objects From NSMutableArray object property? [duplicate]

This question already has answers here:
How to remove all objects with the same property value but one in NSMutableArray
(3 answers)
Closed 9 years ago.
I have one NSObject with properties as following
#property (nonatomic, retain) NSString * destinationid;
#property (nonatomic, retain) NSString * destinationname;
#property (nonatomic, retain) NSString * assetid;
#property (nonatomic, retain) NSString * assetname;
#property (nonatomic, retain) NSString * assetdescription;
Here, I save this in NSMutableArray.
The data which I get from server contains same DestinationName, but different other properties.
I want to check, if same name of Object is already added to NSMutableArray, don't add it again.
I tried to user innner loops but no use :(
Thanks
Here's one solution:
NSArray *originalArray = ... // original array of objects with duplicates
NSMutableArray *uniqueArray = [NSMutableArray array];
NSMutableSet *names = [NSMutableSet set];
for (id obj in originalArray) {
NSString *destinationName = [obj destinationname];
if (![names containsObject:destinationName]) {
[uniqueArray addObject:obj];
[names addObject:destinationName];
}
}
One way to do it is to create a new array that only contains the destination names from your other array, and check if the name from your server is contained there:
NSArray *names = [self.mut valueForKey:#"destinationname"];
if (![names containsObject:destName]) {
[self.mut addObject:newObjectFromServer];
}
mut is the name of my mutable array, and destName is the destination name in the object your getting from the server.
This function should do the job:
BOOL contains(id object, NSMutableArray *array)
{
for (id array in yourArray)
if ([object.destinationname isEqualToString:yourObject.destinationname])
return YES;
return NO;
}
Usage example:
if (!contains(object, array))
[array addObject:object];

Subtract an array of complex objects from another array of same kind of objects ios

I know that subtracting an NSArray from NSArray if it is a single basic object found here
But what i have is an object like this
#interface Set : NSObject
#property (nonatomic, strong) NSString *ItemId;
#property (nonatomic, strong) NSString *time;
#property (nonatomic, strong) NSString *Category_id;
#property (nonatomic, strong) NSString *List_id;
#property (nonatomic, strong) NSString *name;
#end
How can i delete an array having the set object from another array with the same?
It can be done by iterations that i knw.Is there some other way ?
EDIT: For clarity
I have Array A with 5 Set objects and I have 4 Set Objects in Array B
array A and Array B contain 3 set objects with common values..[Note : memory may be different] common
All I need is an Array C =Array A - Array B that has 2 objects in resulting array C
Thank You :)
You need to implement the - (NSUInteger)hash and - (BOOL)isEqual:(id)object method in Set class.
For eg:-
- (NSUInteger)hash {
return [self.ItemId hash];
}
- (BOOL)isEqual:(id)object
{
return ([object isKindOfClass:[self class]] &&
[[object ItemId] isEqual:_ItemId])
}
After that try this:
NSMutableSet *set1 = [NSMutableSet setWithArray:array1];
NSMutableSet *set2 = [NSMutableSet setWithArray:array2];
[set1 intersectSet:set2]; //this will give you only the obejcts that are in both sets
NSArray *commonItems = [set1 allObjects];
[mutableArray1 removeObjectsInArray:commonItems];//mutableArray1 is the mutable copy of array1
mutableArray1 will have all objects in the same order as earlier after removing common objects.
By using NSSet and NSPredicate we can meet your requirement.
Assessors *ass1 = [[Assessors alloc] init];
ass1.AssessorID = #"3";
Assessors *ass2 = [[Assessors alloc] init];
ass2.AssessorID = #"2";
Assessors *ass3 = [[Assessors alloc] init];
ass3.AssessorID = #"1";
Assessors *ass4 = [[Assessors alloc] init];
ass4.AssessorID = #"2";
NSSet *nsset1 = [NSSet setWithObjects:ass1, ass2, nil];
NSSet *nsset2 = [NSSet setWithObjects:ass3, ass4, nil];
// retrieve the IDs of the objects in nsset2
NSSet *nsset2_ids = [nsset2 valueForKey:#"AssessorID"];
// only keep the objects of nsset1 whose 'id' are not in nsset2_ids
NSSet *nsset1_minus_nsset2 = [nsset1 filteredSetUsingPredicate:[NSPredicate predicateWithFormat:#"NOT AssessorID IN %#",nsset2_ids]];
for(Assessors *a in nsset1_minus_nsset2)
NSLog(#"Unique ID : %#",a.AssessorID);
Here Assessors is my NSObject Class (Set in your case) and AssessorID is one property of that class.
Hope this can help.

Resources