0

So I have a small project with a table view. Its cells are populated from another view controller that saves the text/date to user defaults.

Everything works, however, I'm looking to sort the table view by the date it was last saved.

How it's declared:

.h
    NSMutableArray *dateArray;
.m
    self.dateArray = [[NSUserDefaults standardUserDefaults] objectForKey:@"date"];

How can I achieve this? I have seen ways to do it with both an array and mutable, but nothing for a string from userdefaults.

UPDATE w/more info: This is how the date gets saved by the other view controller

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"MMMM d, yyyy 'at' h:mm a"];
NSDate *dateNow = [NSDate date];
NSString *dateNowStr = [dateFormatter stringFromDate:dateNow];

NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSTimeZone *timeZone = [NSTimeZone localTimeZone];
NSLocale *locale = [NSLocale currentLocale];
[dateFormatter setCalendar:gregorianCalendar];
[dateFormatter setTimeZone:timeZone];
[dateFormatter setLocale:locale];

NSArray *tempDateArray = [[NSUserDefaults standardUserDefaults]objectForKey:@"date"];
NSMutableArray *mutableDateArray = [tempDateArray mutableCopy];
[mutableDateArray insertObject:dateNowStr atIndex:self.index];
[[NSUserDefaults standardUserDefaults] setObject:mutableDateArray forKey:@"date"];

It gets loaded via:

self.dateArray = [[NSUserDefaults standardUserDefaults] objectForKey:@"date"];

Thank You.

2
  • As an aside, using NSUserDefaults for this sort of storage is convenient, but it’s not really the intended purpose of user defaults. Generally we’d want to save this sort of data in persistent storage (CoreData or plist or JSON or whatever, in the app support directory). Commented Jun 7, 2020 at 22:35
  • Post updated with more info on saving function. Commented Jun 7, 2020 at 22:52

2 Answers 2

2

A couple of thoughts:

  1. You really should save the dates in the NSMutableArray as NSDate objects. Then you can simply sort the array like:

    [array sortUsingComparator:^NSComparisonResult(NSDate * _Nonnull obj1, NSDate * _Nonnull obj2) {
        return [obj1 compare:obj2];
    }];
    

    Or

    NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:@"self" ascending:YES];
    [array sortUsingDescriptors:@[descriptor]];
    
  2. If you insist in storing date strings (which you really shouldn’t do, because the string should be formatted during presentation, not during storage), you’ll have to take your array of NSString objects, convert them back to an array of NSDate objects, sort that resulting array, and then use a formatter (see below) to display these sorted NSDate objects in the UI.

  3. When you go to show the date in the UI, you can use the formatter. But you don’t need to set the calendar, timezone or locale, because all of those already default to the user’s current settings. And I certainly wouldn’t override the user’s calendar with a Gregorian calendar (as that will be exceedingly annoying for users who have configured their devices to not use Gregorian calendars).

    Also, we generally should avoid specifying date format strings. It’s better to use date/time styles, e.g.:

    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    formatter.dateStyle = NSDateFormatterLongStyle;
    formatter.timeStyle = NSDateFormatterShortStyle;
    

    That way, the US user will see:

    June 7, 2020 at 5:10 PM

    Whereas the German user will see:

    1. Juni 2020 um 17:10

    We should always show dates in the user’s preferred locale/calendar.

Sign up to request clarification or add additional context in comments.

Comments

0

So I ended up doing this a different way, I couldn't really figure out the sorting aspect of it, which is fine.

I did take Rob's advice and ended up scrapping the hard coded date and time. I also changed where it saves.

NSArray *tempArray = [[NSUserDefaults standardUserDefaults] objectForKey:@"note"];
mutableArray = [tempArray mutableCopy];
NSString *textString = [self.textView text];
[mutableArray removeObjectAtIndex:self.index];
[mutableArray insertObject:textString atIndex:self.index]; <- Was: atIndex:0
[[NSUserDefaults standardUserDefaults] setObject:mutableArray forKey:@"note"];

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
//Removed hard coded date
[dateFormatter setDateFormat:@"MMMM d, yyyy 'at' h:mm a"];

//Added new date style
[dateFormatter setDateStyle:NSDateFormatterLongStyle];
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];

NSDate *dateNow = [NSDate date];
NSString *dateNowStr = [dateFormatter stringFromDate:dateNow];

NSArray *tempdateArray = [[NSUserDefaults standardUserDefaults]objectForKey:@"date"];
mutabledateArray = [tempdateArray mutableCopy];
[mutabledateArray removeObjectAtIndex:self.index];
[mutabledateArray insertObject:dateNowStr atIndex:self.index];<- Was: atIndex:0
[[NSUserDefaults standardUserDefaults] setObject:mutabledateArray forKey:@"date"];

The key for me was changing the atIndex part of the insertObject. That saved it in the spot where it was opened from. When the index was 0, it would save to the top of the index, but if I opened any other index besides the top cell, it would bug out. I would save a couple times and it would save over itself and not push the table view count.

So with the index set, I decided to try moving the cell to the top when I close out the modal view. so I did this:

.h
@interface NSMutableArray (MoveArray)
- (void)moveObjectFromIndex:(NSUInteger)from toIndex:(NSUInteger)to;
@end

.m
@implementation NSMutableArray (MoveArray)
- (void)moveObjectFromIndex:(NSUInteger)from toIndex:(NSUInteger)to
{
    if (to != from) {
        id obj = [self objectAtIndex:from];
        [self removeObjectAtIndex:from];
        if (to >= [self count]) {
            [self addObject:obj];
        } else {
            [self insertObject:obj atIndex:to];
        }
    }
}
@end

And finally in my Done button I called:

-(void)done:(id)sender
{
//Moving the saved note to the top
NSArray *tempArray = [[NSUserDefaults standardUserDefaults] objectForKey:@"note"];
mutableArray = [tempArray mutableCopy];
[mutableArray moveObjectFromIndex:self.index toIndex:0];
[[NSUserDefaults standardUserDefaults] setObject:mutableArray forKey:@"note"];

NSArray *tempdateArray = [[NSUserDefaults standardUserDefaults]objectForKey:@"date"];
mutabledateArray = [tempdateArray mutableCopy];
[mutabledateArray moveObjectFromIndex:self.index toIndex:0];
[[NSUserDefaults standardUserDefaults] setObject:mutabledateArray forKey:@"date"];
}

Hope this helps somebody. and Thank you Rob for the direction.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.