Hi i am new for ios and i am integrating my app with services and i am getting here trip creation TimeandDate values and storing that values one separate Array and also i am getting pickUpAdress values from services and storing them one separate arrayList
After storing in arrayList i am set date values at "Ascending" order in my tableList
after set "Ascending" when i display them in tableList both array-list data they are mismatching to one another please help me how can i resolve this problem how can i set my Adrress array values for matching to related DateandTimes
code:-
#import "ViewController.h"
#interface ViewController ()
{
NSSortDescriptor* sortOrder;
NSArray * ToBeReadyTimeArray1;
NSMutableArray * ToBeReadyTimeArray ,*finalToBeReadyTimeArray,*AdressArray;
UITableView * MaintableView;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
ToBeReadyTimeArray1 = [[NSArray alloc]init];
ToBeReadyTimeArray = [[NSMutableArray alloc]initWithObjects:#"02/17/2016",#"03/13/2016",#"04/18/2016",#"05/21/2016", nil];
finalToBeReadyTimeArray =[[NSMutableArray alloc]init];
AdressArray = [[NSMutableArray alloc]initWithObjects:#"Adress1",#"Adress2",#"Adress3",#"Adress4", nil];
//Arange Date formate At Assending order:-
sortOrder = [NSSortDescriptor sortDescriptorWithKey: #"self" ascending: YES];
ToBeReadyTimeArray1 = [ToBeReadyTimeArray sortedArrayUsingDescriptors: [NSArray arrayWithObject: sortOrder]];
for (NSString *dte in ToBeReadyTimeArray1){
NSDateFormatter *aDateFormatter = [[NSDateFormatter alloc] init];
[aDateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
[aDateFormatter setDateFormat:#"MM/dd/yyyy"];
NSDate * parsed = [aDateFormatter dateFromString:dte];
[aDateFormatter setDateFormat:#"dd MMM yyyy"];
NSString *aFormattedElapsedTime = [aDateFormatter stringFromDate:parsed];
NSLog(#"tobe Ready time %#",aFormattedElapsedTime);
[finalToBeReadyTimeArray addObject:aFormattedElapsedTime];
}
}
I presume you are trying to list pick up times / address with some sorted order. If that's so, i would have created a NSArray of Booking or Trip models which would contain the information as Address (NSString *) and PickUpTime (NSDate *) and then would have implemented a sorting method using the property as variable key.
In my case, I implemented an array of booking models which has pickUpTime and address.
#property (nonatomic, retain) NSNumber *pickUpTime; // Timestamp instead of NSDate ...
#property (nonatomic, retain) NSString *address;
I implemented a category method for NSArray. Please note that sort order enumerations are manually implemented.
+ (NSArray *)sortArray:(NSArray *)unSortedArray byOrder:(SortOrder)sortOrder usingVariableKey:(NSString *)variableKey {
NSArray *sortedArray = [NSArray array];
BOOL isAscendingOrder = NO;
if (sortOrder == SortOrderAscending) {
isAscendingOrder = YES;
}
if (unSortedArray) {
NSSortDescriptor *valueDescriptor = [[NSSortDescriptor alloc] initWithKey:variableKey ascending:isAscendingOrder];
NSArray *descriptors = [NSArray arrayWithObject:valueDescriptor];
sortedArray = [[unSortedArray sortedArrayUsingDescriptors:descriptors] mutableCopy];
}
return sortedArray;
}
Then, i invoked the following ...
// Here, resultMutableArray is a mutable array of booking models ...
NSArray *resultArray = [NSArray sortArray:[resultMutableArray copy] byOrder:SortOrderDescending usingVariableKey:#"pickUpTime"];
Related
I have an NSArray which contains custom objects like this:
NSArray *array = {
students,students
}
And student object in turns store values like :
student.name,
student.class,
student.admissionDate
student.school ..etc
Now I want an NSArray which contains all the student's detail sorted in based on their admissionDate.
I tried using NSSortDecriptor but it doesn't helped me.
EDIT
After some hard work I have successfully formed a NSMutable array of NSDictionary which Looks like:
for(Student *arr in array)
{
NSMutableDictionary *dict;
dict = [[NSMutableDictionary alloc]init];
[dict setObject:arr.stuName forKey:#"name"];
[dict setObject:arr.stuAdate forKey:#"date"];
[dict setObject:arr.stuClass forKey:#"class"];
[expenseArray addObject:dict];
}
Printing description of expenseArray:
<__NSArrayM 0x7fe703833f70>(
{
name = uuu;
Adate = "2015-10-10 10:56:03 +0000";
class = 1st;
},
{
name = abc;
Adate = "2015-10-07 11:10:00 +0000";
class = 3rd;
},
{
name = btw;
Adate = "2015-10-10 11:13:47 +0000";
class = 4th;
}
)
Now how can i sort based on date
The sort descriptor should work for you
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"admissionDate" ascending:YES];
NSArray *sortedStudents = [studentArray sortedArrayUsingDescriptors:#[sortDescriptor]];
Below is the working example
NSMutableArray *studentArray = [NSMutableArray new];
for (int i = 0; i < 8; i++) {
Student *student = [Student new];
unsigned int randomInterval = arc4random();
student.admissionDate = [NSDate dateWithTimeIntervalSinceNow:randomInterval];
[studentArray addObject:student];
}
for (Student *student in studentArray) {
NSLog(#"%#", student.admissionDate);
}
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"admissionDate" ascending:YES];
NSArray *sortedStudents = [studentArray sortedArrayUsingDescriptors:#[sortDescriptor]];
NSLog(#"\n\n * * * * * After Sorting * * * * * *\n\n");
for (Student *student in sortedStudents) {
NSLog(#"%#", student.admissionDate);
}
Logs
2024-02-11 23:47:47 +0000
2093-11-13 21:49:48 +0000
2042-04-06 23:53:28 +0000
2032-12-23 01:49:46 +0000
2102-12-28 23:08:06 +0000
2058-10-17 14:14:27 +0000
2142-02-01 07:19:34 +0000
2048-05-14 07:07:04 +0000
* * * * * After Sorting * * * * * *
2024-02-11 23:47:47 +0000
2032-12-23 01:49:46 +0000
2042-04-06 23:53:28 +0000
2048-05-14 07:07:04 +0000
2058-10-17 14:14:27 +0000
2093-11-13 21:49:48 +0000
2102-12-28 23:08:06 +0000
2142-02-01 07:19:34 +0000
A sort descriptor should work fine
NSSortDescriptor *admissionSort = [NSSortDescriptor sortDescriptorWithKey:#"Adate" ascending:NO];
NSArray *sortedArray = [array sortedArrayUsingDescriptors:#[admissionSort]];
will sort the array based on the admission date assuming that is actually a NSDate value.
Although NSSortDescription seems to be the best way to sort an array, here is alternative approach:
NSArray *studentsArray = #[someStudent1, someStudent2];
NSArray *sortedStudentsArray = [studentsArray sortedArrayUsingComparator:^NSComparisonResult(Student *student1, Student *student2) {
return [student1.admissionDate compare:student2.admissionDate];
}];
NSSortDescriptor works fine!
You should replace your mutable dictionary with Student class.
#interface Student : NSObject
#property NSString *name;
#property NSString *className;
#property NSString *schoolName;
#property NSDate *admissionDate;
#end
#implementation Student
#end
Uses of this class
Student *student1 = [[Student alloc] init];
student1.name = #"Name a";
student1.className = #"4th";
student1.schoolName = #"XYZ High school";
student1.admissionDate = [NSDate dateWithTimeIntervalSinceNow:60 * 60 * 24]; // 60 * 60 * 24 one day time interval in second
Student *student2 = [[Student alloc] init];
student2.name = #"Name b";
student2.className = #"5th";
student2.schoolName = #"XYZ High school";
student2.admissionDate = [NSDate date]; // current date
NSArray *array = [NSArray arrayWithObjects:student1,student2, nil];
NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:#"admissionDate" ascending:YES];
NSArray *sortedArray = [array sortedArrayUsingDescriptors:#[descriptor]];
for (Student *student in sortedArray) {
NSLog(#"admissionDate %#", student.admissionDate);
}
Please keep in mind that [array sortedArrayUsingDescriptors:#[descriptor]] return sorted array, not rearranged array elements itself.
Hope this will work.
I have a NSArray of countries that I obtained using [NSLocale ISOCountryCodes]. How do I sort this NSArray such that I can put certain commonly used countries at the top of the list, while keeping the rest in its alphabetical order?
United States of America
United Kingdom
Singapore
Korea
Japan
Hong Kong
Afghanistan
Albania
Algeria
etc etc..
I am using caseInsensitiveCompare: currently to get the alphabetical order, but how can I change it such that I can specify a list to put at the top, while the rest to be kept alphabetical below.
You can delete the objects you do not want to sort,then sort the rest,then add them together.
Example Code:
NSMutableArray * allData = [[NSMutableArray alloc] initWithArray:[[NSLocale ISOCountryCodes]]];
NSArray * yourexceptArray;
[allData removeObjectsInArray:yourexceptArray];
NSMutableArray * result = [[NSMutableArray alloc] initWithArray:yourexcepArray];
sortedArray = //Sort the allData as you like,then add it to result
[result addObjectsFromArray:sortedArray]
As opposed to WenchenHuang's answer (which is valid), I think you could do it with the help of sortedArrayUsingComparator.
Inside the block just compare the strings as usually, but if the string equals to one of the codes that you want to show higher, return YES.
someArray = [someArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
if ([(NSString*)obj1 isEqualToString:#"USA"]) {
return YES;
} else if ([(NSString*)obj1 isEqualToString:#"SOME_OTHER_COUNTRY"]) {
return YES;
}
return [(NSString*)obj1 compare:(NSString*)obj2];
}];
I would do it using Sort Descriptor. I don't like manipulating array again and again. So, I find sort descriptors best in this kind of scenario. (Just personal preference)
Step 1: Create a model class with priority as a key. My model class-
#import <Foundation/Foundation.h>
#interface ISOCountry : NSObject
#property(nonatomic, strong) NSString *countryCode;
#property(nonatomic, retain) NSString *priority;
#end
Step 2: The just do this-
NSArray *ISOCountryCodes = [[NSArray alloc]initWithArray:[NSLocale ISOCountryCodes]];
NSArray *commonUsedCountries= [[NSArray alloc]initWithObjects:#"NR", #"NG", #"KW", #"ES", nil];
NSMutableArray *arrayToBeSorted = [[NSMutableArray alloc]init];
for(NSString *countryCode in ISOCountryCodes){
ISOCountry *isoCountry = [[ISOCountry alloc] init];
[isoCountry setValue:countryCode forKey:#"countryCode"];
if(![commonUsedCountries containsObject:countryCode]){
[isoCountry setValue:[NSString stringWithFormat:#"%d", 2] forKey:#"priority"];
}
else{
[isoCountry setValue:[NSString stringWithFormat:#"%d", 1] forKey:#"priority"];
}
[arrayToBeSorted addObject:isoCountry];
}
NSSortDescriptor *prioritySort = [[NSSortDescriptor alloc] initWithKey:#"priority" ascending:YES];
NSSortDescriptor *countryCodeSort = [[NSSortDescriptor alloc] initWithKey:#"countryCode" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObjects:prioritySort, countryCodeSort, nil];
NSArray *sortedArray = [arrayToBeSorted sortedArrayUsingDescriptors:sortDescriptors];
I've created simple class Student with properties
#property (strong,nonatomic) NSString* firstname;
#property (strong,nonatomic) NSString* lastname;
#property (strong,nonatomic) NSDate* dateOfBirth;
#property (assign,nonatomic) NSInteger index;
After that, I created any objects of this class, gave it firstname, lastname, date and index, add all of them to self.InitialStudentsArray. And start sorting by dateOfBirth:
NSSortDescriptor* descriptorDate=[[NSSortDescriptor alloc]initWithKey:#"dateOfBirth" ascending:YES];
NSArray* descArray=[NSArray arrayWithObjects:descriptorDate, nil];
[self.InitialStudentsArray sortUsingDescriptors:descArray];
So, the result is strange. Array before sorting and after sorting have different items order, but not sorted at all by date.
before sort (
"46 Alex Dupel 25 10 1991",
"236 Ivan Evstegneev 20 09 1980",
"179 Hugo Igonin 03 02 1992",
"189 Alexey Boronenko 06 11 1978" )
after sort (
"236 Ivan Evstegneev 20 09 1980",
"179 Hugo Igonin 03 02 1992",
"189 Alexey Boronenko 06 11 1978",
"46 Alex Dupel 25 10 1991" )
The same thing with firstname and lastname (even if use selectors:
NSSortDescriptor* descriptorLastname=[[NSSortDescriptor alloc]initWithKey:#"lastname" ascending:YES selector:#selector(caseInsensitiveCompare:)];
It's only work for property "index",which is NSInteger.
What I've done else, I created array only with dates from student.dateOfBirth and sorted it with keyname self. And it works! Another experiment - I created array of dictionaries with key "dateOfBirth" and sorted it by key name #"dateOfBirth" and it also works!
I know about other methods live sortUsingComparator, but why this method doesn't work on date and strings in properties??
Upd
Oh, guys, it's my mistake. I appreciate all of your answers, they pushed me to place, where to search mistake. And when I found it, I felt very ashamed. Absolutly stupid mistake. If you are interested in, I used this way to initialize student:
- (instancetype)init
{
self = [super init];
if (self) {
self.firstname=[self getFirstname];
self.lastname=[self getLastname];
self.dateOfBirth=[self getDateOfBirth];
}
return self;
}
-(NSString*) getFirstname {//some code...arrayOfFirstames...name=arc4random()...}
I.e. I occasionally redefine getter for setting property. All three. So, when I was sorting array everytime new values was taken.
Thank you.
You might have wrong another thing, SortDescriptors work fine with strings, here an example:
NSArray *people = #[#{#"name": #"Ivan"},#{#"name": #"Hugo"},#{#"name": #"Alexey"},#{#"name": #"Alex"}];
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES];
NSArray *sorts = #[sort];
NSArray *orderedArray = [people sortedArrayUsingDescriptors:sorts];
NSLog(#"Show orderedArray: %#",[orderedArray description]);
Exit in console:
2014-11-14 20:19:45.377 pro[1366:60b] Show orderedArray: (
{
name = Alex;
},
{
name = Alexey;
},
{
name = Hugo;
},
{
name = Ivan;
}
)
I think it´s good idea to log your array before and after the sortedArrayUsingDescriptor methods.
Hi again. I´ve done the same again, with a Custom Class this is the header:
#import <Foundation/Foundation.h>
#interface CustomClass : NSObject
#property (nonatomic, strong) NSString *name;
#end
The implementation (.m) is blank, and again I´ve done:
CustomClass *ivan = [[CustomClass alloc] init];
ivan.name = #"Ivan";
CustomClass *hugo = [[CustomClass alloc] init];
hugo.name = #"Hugo";
CustomClass *alexey = [[CustomClass alloc] init];
alexey.name = #"Alexey";
CustomClass *alex = [[CustomClass alloc] init];
alex.name = #"Alex";
NSArray *people = #[ivan,hugo,alexey,alex];
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES];
NSArray *sorts = #[sort];
NSArray *orderedArray = [people sortedArrayUsingDescriptors:sorts];
NSLog(#"Show orderedArray:");
for (CustomClass *people in orderedArray) {
NSLog(#"%#\n",people.name);
}
And again, the exit console is:
2014-11-14 22:38:13.297 pro[1406:147113] Show orderedArray:
2014-11-14 22:38:13.298 pro[1406:147113] Alex
2014-11-14 22:38:13.298 pro[1406:147113] Alexey
2014-11-14 22:38:13.298 pro[1406:147113] Hugo
2014-11-14 22:38:13.298 pro[1406:147113] Ivan
There isn´t any problem with sortDescriptors and property. Best
I'm calling a method passing two arrays to it as follow :
NSArray *marked_dates = [NSArray arrayWithObjects:[dateFormat dateFromString:#"19/03/2014"],[dateFormat dateFromString:#"17/04/2014"],[dateFormat dateFromString:#"12/02/2014"], nil];
NSArray *marked_colors = [NSArray arrayWithObjects:[UIColor greenColor],[UIColor greenColor],[UIColor greenColor],nil];
[calendar markDates:marked_dates withColors:marked_colors];
Below is the method receiving this :
-(void)markDates:(NSArray *)dates withColors:(NSArray *)colors {
self.markedDates = dates;
self.markedColors = colors;
NSLog(#"%#",[NSString stringWithFormat:#"%d",[dates count]]);
for (int i = 0; i<[self.markedDates count]; i++) {
NSLog(#"%#",[NSString stringWithFormat:#"%#", self.markedDates[i]]);
}
[self setNeedsDisplay];
}
The log says 0 and I obviously don't get into the for loop.
Thanks for any help.
EDIT :
I will also vote up for any information about the warning : "format string is not a string literal"
Below the declaration of the properties :
#property (nonatomic, retain) NSArray *markedDates;
#property (nonatomic, retain) NSArray *markedColors;
EDIT :
So yes, the formater gives null values.
Here is how I did it :
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"MM/dd/yyyy"];
NSLog(#"%#",[NSString stringWithFormat:#"%#",[dateFormat dateFromString:#"19/03/2014"]]);
//this prints "null"
EDIT with solution :
Bad mistake, I misconfigured the formatter
using this worked for me, thank you all for your help.
[dateFormat setDateFormat:#"dd/MM/yyyy"];
The dates array is probably empty due to the date formatter only producing nil values. Fix the date formatter so it will correctly generate NSDate objects and it should work:
[dateFormat setDateFormat:#"dd/MM/yyyy"];
First of all you should not create the property name and Local instance variable as same name. Because property it's self create instance var with _Property name.And the issue is with line.
NSArray *marked_dates = [NSArray arrayWithObjects:[dateFormat dateFromString:#"19/03/2014"],[dateFormat dateFromString:#"17/04/2014"],[dateFormat dateFromString:#"12/02/2014"], nil];
Add the date format also.
check this again. let me know if you still facing the same issue.
[dateFormat setDateFormat:#"dd/MM/yyyy"]; ?
I have two arrays one of which is a tweets array and contains twitter tweets. Another of which is a instapics array and contains Instagram pictures. Both of these Arrays have different keys for date. The twitter one had created_at and the instagram one has created_time. I want to display both of them on a single UITableView and have them organized by date. Here is what I am doing so far, the problem with this however is that it only shows Instagram Pictures:
- (void)sortArrayBasedOndate {
NSDateFormatter *fmtDate = [[NSDateFormatter alloc] init];
[fmtDate setDateFormat:#"yyyy-MM-dd"];
NSDateFormatter *fmtTime = [[NSDateFormatter alloc] init];
[fmtTime setDateFormat:#"HH:mm"];
totalFeed = [totalFeed sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
// Instagram Date Retrieval
NSDictionary *instagram = self.instaPics;
NSString *createdAt = instagram[#"created_time"];
int createdAtN = [createdAt intValue];
NSTimeInterval timestamp = (NSTimeInterval)createdAtN;
NSDate *date1 = [NSDate dateWithTimeIntervalSince1970:timestamp];
// Twitter Date Retrieval
NSDictionary *twitter = self.tweets;
NSString *twitterCreated = twitter[#"created_at"];
int createdAtTwitter = [twitterCreated intValue];
NSTimeInterval timestampTwitter = (NSTimeInterval)createdAtTwitter;
NSDate *date2 = [NSDate dateWithTimeIntervalSince1970:timestampTwitter];
return [date1 compare:date2];
}];
}
The above is how I am trying to organize them on the array, below is how I am attempting to display them:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
id object = [totalFeed objectAtIndex:indexPath.row];
if ([tweets containsObject:object]) {
static NSString *Twitter = #"TweetCell";
UITableViewCell *twitter = [self.tableView dequeueReusableCellWithIdentifier:Twitter];
NSDictionary *totalArray = totalFeed[indexPath.row/2];;
// Creation Code Not shown
return twitter;
}else{
static NSString *Instagram = #"InstagramCell";
UITableViewCell *instagram = [self.tableView dequeueReusableCellWithIdentifier:Instagram];
NSDictionary *entry = instaPics[indexPath.row / 2];
// Creation Code not Shown
return instagram;
}
}
The easiest solution would be if you add a common "creationDate" key to all objects in the
totalFeed array. The value of this key should be an NSDate created from
the "created_at" or "created_time" key.
Then you can just sort the array according to this key:
NSSortDescriptor *sortDesc = [[NSSortDescriptor alloc] initWithKey:#"creationDate" ascending:YES]];
totalFeed = [totalFeed sortedArrayUsingDescriptors:#[sortDesc]];
If you cannot do that for some reason, you have to fix the comparator method, it does
not use the passed arguments obj1, obj2 at all.
Something like (pseudo-code):
totalFeed = [totalFeed sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSDate *date1, *date2;
if ("obj1 is a Twitter") {
date1 = "get created_at from twitter obj1"
} else {
date1 = "get created_time from instagram obj1"
}
if ("obj2 is a Twitter") {
date2 = "get created_at from twitter obj2"
} else {
date2 = "get created_time from instagram obj2"
}
return [date1 compare:date2];
}];
In any case, in cellForRowAtIndexPath you have to access totalFeed[indexPath.row]
(without dividing by 2, which does not make sense here).
More sample code:
NSArray *instaPics; // your instagrams
NSArray *tweets; // your tweets
NSMutableArray *totalFeed = [NSMutableArray array]; // the common array
// Date formatter for the tweets. The date format must exactly
// match the format used in the tweets.
NSDateFormatter *fmtDate = [[NSDateFormatter alloc] init];
[fmtDate setDateFormat:#"..."];
// Add all instagrams:
for (NSMutableDictionary *instagram in instaPics) {
NSString *createdAt = instagram[#"created_time"];
NSDate *date = [NSDate dateWithTimeIntervalSince1970:[createdAt doubleValue]];
instagram[#"creationDate"] = date;
[totalFeed addObject:instagram];
}
// Add all tweets:
for (NSMutableDictionary *twitter in tweets) {
NSString *twitterCreated = twitter[#"created_at"];
NSDate *date = [fmtDate dateFromString:twitterCreated];
twitter[#"creationDate"] = date;
[totalFeed addObject:twitter];
}
// Sort
NSSortDescriptor *sortDesc = [[NSSortDescriptor alloc] initWithKey:#"creationDate" ascending:YES];
[totalFeed sortUsingDescriptors:#[sortDesc]];