I am trying to build an NSDictionary from an NSManagedObject. I was under the impression that you could do this with: NSMutableDictionary *myDict;
[myDict setObject:self.title forKey:#"title"];
}
Because a dictionary cannot hold nil values, I am testing for nil first. However, when I verify using a break that properties have values, when I build the dictionary it is nil. It shows as nil using a breakpoint and logs to console as NULL. Would appreciate someone confirming that the following is a valid way to create a dictionary and, if so, why the dictionary would be nil?
NSString *title = #"Test";
NSNumber *complete = #1;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = #"yyyy-MM-dd HH:mm:ss";
NSString *lasttouchedstr =[dateFormatter stringFromDate:[NSDate date]];
NSMutableDictionary *myDict;
if (self.title.length>=1) {
[myDict setObject:self.title forKey:#"title"];
}
if (![self.complete isKindOfClass:[NSNull class]]) {
[myDict setObject:self.complete forKey:#"complete"];
}
if (![self.lasttouched isKindOfClass:[NSNull class]]) {
[myDict setObject:lasttouchedstr forKey:#"lasttouchedstr"];
}
NSLog(#"myDict is:%#",myDict)//Logs as NULL
return myDict;
Thanks in advance for any suggestions.
NSMutableDictionary *myDict; declares the value but does not initialize it. You need
NSMutableDictionary *myDict = [[NSMutableDictionary alloc] init];
Secondly, managed objects will not be returning a value of NSNull for any of their attributes. You need to check for != nil instead. See here for a nice explanation of the differences between nulls and nils.
Related
I have the following situation where
I have an NSMutableArray filled with an xml file which I want to search.
When I enter something in the search field I get this Error:
-[NSCFString countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x5b388b0
What does it means and how can I fix it??
I suppose the error is somewhere around here.
- (void)searchTableView{
searchedList = [[NSMutableArray alloc] init];
NSLog(#"new list %#", searchedList);
NSString *searchText = searchBar.text;
NSMutableArray *searchArray = [[NSMutableArray alloc] init];
for (NSDictionary *dictionary in list) {
NSArray *array = [dictionary objectForKey:#"TITLE"];
[searchArray addObjectsFromArray:array];
}
for (NSString *TempArray in searchArray) {
NSRange titleResults = [TempArray rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (titleResults.length > 0)
[searchedList addObject:TempArray];
}
[searchArray release];
searchArray = nil;
}
it means you are calling a method designed for an NSArray (countByEnumeratingWithState:objects:count on a NSString.
I don't know ifthis code is copy/paste from yours, but if so, at the end where you use [searchList addObject:TempArray] you don't have an object named searchList.
Also, work on your naming conventions. big time.
This question already has answers here:
How do I sort an NSMutableArray with custom objects in it?
(27 answers)
Closed 7 years ago.
I'm trying to figure out the best/most efficient way to sort an array that contains n-number of dictionaries. One of the key/value pairs in each dictionary is a date field. After adding all the dictionaries to the array, I would like to sort the array by descending date order.
For example, I have code like this:
NSMutableArray *myArray = [[NSMutableArray alloc] init];
NSMutableDictionary *dictionary1 = [[NSMutableDictionary alloc] init];
NSDate *today = [NSDate date];
[dictionary1 setObject:today forKey:#"date"];
[dictionary1 setObject:#"Another value" forKey:#"anotherKey"];
[myArray addObject:dictionary1];
NSMutableDictionary *dictionary2 = [[NSMutableDictionary alloc] init];
NSDate *tomorrow = [[NSDate date] dateByAddingTimeInterval:60*60*24];
[dictionary2 setObject:tomorrow forKey:#"date"];
[dictionary2 setObject:#"Yet another value" forKey:#"anotherKey"];
[myArray addObject:dictionary2];
Now I need myArray to be sorted by descending date. (array index 0 should be the latest date)
Note: In my actual project, I'm not creating and adding the dictionaries in this way. But for example purposes to see how the date is stored in the dictionary, lets assume I've put these two into the array.
You can use NSSortDescriptors here:
NSMutableArray *myArray = [[NSMutableArray alloc] init];
NSMutableDictionary *dictionary1 = [[NSMutableDictionary alloc] init];
NSDate *today = [NSDate date];
[dictionary1 setObject:today forKey:#"date"];
[dictionary1 setObject:#"Another value" forKey:#"anotherKey"];
[myArray addObject:dictionary1];
NSMutableDictionary *dictionary2 = [[NSMutableDictionary alloc] init];
NSDate *tomorrow = [[NSDate date] dateByAddingTimeInterval:60*60*24];
[dictionary2 setObject:tomorrow forKey:#"date"];
[dictionary2 setObject:#"Yet another value" forKey:#"anotherKey"];
[myArray addObject:dictionary2];
NSSortDescriptor *sortDesciptor = [NSSortDescriptor sortDescriptorWithKey:#"date" ascending:NO];
//Create new sorted array
NSArray *sortedArray = [myArray sortedArrayUsingDescriptors:#[sortDesciptor]];
//Or sort your mutable one
[myArray sortUsingDescriptors:#[sortDesciptor]];
There are lots of ways to do this. You could use an NSSortDescriptor as Krivoblotsky says.
You can also use the NSMutableArray sortUsingComparator method. The code would look something like this:
[myArray sortUsingComparator
^(NSDictionary *obj1, NSDictionary *obj2)
{
return [obj1["date"] compare: obj2["date"]]
}
];
The sortUsingComparator method takes an NSComparator block.
An NSComparator takes two objects of type id, and returns an NSComparisionResult:
typedef NSComparisonResult (^NSComparator)(id obj1, id obj2);
Since NSDate supports the compare method you can just write 1-line comparator block that fetches the date entry for each dictionary and returns the result of comparing them.
I am having an array which contains a date. this is my array.
"2015-03-01",
"2015-03-04",
"2015-03-05",
"2015-03-06",
"2015-03-07",
"2015-03-08",
"2015-03-14",
"2015-03-15"
list the value according to this date.my coding is
NSArray * datevalue = [tempArr valueForKey:#"match_formatted_date"];
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"self" ascending:YES];
NSArray *descriptors = [NSArray arrayWithObject: descriptor];
NSArray *reverseOrder = [datevalue sortedArrayUsingDescriptors:descriptors];
NSPredicate *findFutureDates = [NSPredicate predicateWithBlock: ^BOOL(id obj, NSDictionary *bind){
NSDateFormatter *df = [[NSDateFormatter alloc]init];
[df setDateFormat:#"yyyy-MM-dd"];
[df setTimeZone:[NSTimeZone systemTimeZone]];
NSDate *dd = [df dateFromString:(NSString *)obj ];
return ([[NSDate date] compare:dd] == NSOrderedAscending);
}];
NSArray * arrFutureDates = [reverseOrder filteredArrayUsingPredicate: findFutureDates];
NSLog(#"arrFutureDates:%#",arrFutureDates);
for (id item in arrFutureDates)
{
if (![dataArr containsObject:item])
[dataArr addObject:item];
}
[dataArr sortUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
for (int i= 0; i<[dataArr count]-1; i++) {
for (id item in tempArr)
{
if([#"Mexico: Copa Mexico - Clausura" isEqualToString:[item valueForKey:#"league_name"]]
||[#"Mexico: Liga De Ascenso - Clausura" isEqualToString:[item valueForKey:#"league_name"]]
||[#"Mexico: Primera Division - Clausura" isEqualToString:[item valueForKey:#"league_name"]])
if([[dataArr objectAtIndex:i]isEqualToString:[item valueForKey:#"match_formatted_date"]])
{
NSMutableDictionary *tempDic =[[NSMutableDictionary alloc]init];
[tempDic setValue: [item valueForKey:#"match_formatted_date"] forKey:#"match_formatted_date"];
[tempDic setValue: [item valueForKey:#"league_name"] forKey:#"league_name"];
if (![titleheader containsObject:tempDic])
{
[titleheader addObject:tempDic];
}}}}
my problem is: In title header null value is coming. were I made the mistake, can anyone help me.
Check your code, you didnt initialize titleheader anywhere. In that case it will be nil only.
Before checking condition, initialize and assign some value to titleheader.
Or else i dont know you missed to paste the code.
Unreadable formatting aside, there are few issues in your code, that may cause your problem:
NSArray* datevalue = [tempArr valueForKey:#"match_formatted_date"];
Name suggests, that tempArr is NSArray, however you are accessing it as NSDictionary. There is difference between methods -valueForKey: and -objectForKey:. Former is NSObject method related to KVC, while latter is NSDictionary method for accessing stored objects. They are frequently confused, because called on NSDictionary they behave in the same way.
for (int i= 0; i<[dataArr count]-1; i++) {
This for loop skips last object in dataArr, which - I assume - was not intended. This can be fixed by i < dataArr.count or i <= dataArr.count-1.
Another issue - not related to problem, but opportunity to learn:
NSMutableDictionary *tempDic =[[NSMutableDictionary alloc]init];
[tempDic setValue: [item valueForKey:#"match_formatted_date"] forKey:#"match_formatted_date"];
[tempDic setValue: [item valueForKey:#"league_name"] forKey:#"league_name"];
if (![titleheader containsObject:tempDic])
Objects in containers are stored and compared (by default) as references, thus -containsObject will always return NO - even if there were another NSDictionary with the same key-value pairs.
I have an NSMutableArray called self.objectArray, that contains custom objects. Each object holds an NSDictionary and two other string objects. Actually I need to work only with the dictionary. Every dictionary contains a key named keyDate which holds an NSString that look like this: MM/dd/yy HH:mm:ss.
I would like to sort the array based on their keyDate. The object with the oldest date should be the first object and so on. I've found some questions, that looked helpful and I could create the code that you can see below, but I get an error everytime I run it. As I think NSSortDescriptor won't be the right tool since my keys aren't key value compliant.
PNMessage 0x125c0590> valueForUndefinedKey:]: this class is not key value coding-compliant for the key keyDate.'
NSSortDescriptor *dateDescriptor = [NSSortDescriptor
sortDescriptorWithKey:#"keyDate"
ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:dateDescriptor];
NSArray *sortedEventArray = [self.objectArray
sortedArrayUsingDescriptors:sortDescriptors];
self.finallySorted = [sortedEventArray mutableCopy];
If it's possible I would do it with sort descriptor, however I think there should be some other options, but can't figure out its proper implementation.
So I can also catch every object's keyDate with a for loop, but don't know how can I sort them based on the value. I would really appreciate if somebody could show me the right way.
for(PNMessage *mg in self.objectArray)
{
NSLog(#" test log %#", mg.message[#"keyDate"]);
}
I already checked this answer:
How to sort an NSMutableArray with custom objects in it?
but the structure of my object is different.
My first code based on this question, but it doesn't worked.
How to sort an NSMutableArray with custom objects in it?
UPDATE: my try based on Kaan's answer (doesn't works yet)
static NSDateFormatter *formatter = nil;
if(!formatter) {
formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"MM/dd/yy HH:mm:ss"];
}
NSArray *sortedArray = [self.object sortedArrayUsingComparator:^NSComparisonResult(PNMessage *obj1, PNMessage *obj2) {
NSString *date1String = obj1.message[#"keyDate"];
NSString *date2String = obj1.message[#"keyDate"];
NSDate *date1 = [formatter dateFromString:date1String];
NSDate *date2 = [formatter dateFromString:date2String];
if ( date1 < date2 ) {
return (NSComparisonResult)NSOrderedAscending;
} else if ( date1 > date2 ) {
return (NSComparisonResult)NSOrderedDescending;
}
return (NSComparisonResult)NSOrderedSame;
}];
I would consider using the sortedArrayUsingComparator method
Assuming your custom class is called PNMessage:
static NSDateFormatter *formatter = nil;
if(!formatter) {
formatter = [[NSDateFormatter alloc] init];
[formatter setFormat:#"MM/dd/yy HH:mm:ss"];
}
NSArray *sortedArray = [self.objectArray sortedArrayUsingComparator:^NSComparisonResult(PNMessage *obj1, PNMessage *obj2) {
NSString *date1String = obj1[#"keyDate"];
NSString *date2String = obj1[#"keyDate"];
NSDate *date1 = [formatter dateFromString:date1String];
NSDate *date2 = [formatter dateFromString:date2String];
return [date1 compare:date2];
}];
Tip: If you decide on following this, make sure you declare your NSDateFormatter instance as static outside of the sorting body, since allocating Formatters in iOS can be very expensive and cause serious performance penalties.
I have a tableview that contains multiple sections, grouped by an attribute of my object (date) I try to sort the tableview according to the value of date.I created a function for that , but I get an error :
- (void)sortObjectsDictionnary:(NSArray *)arrayObjects
{
//this is my nsdictionnary
[objects removeAllObjects]
//this is nsmutableaaray that contains dats
[objectsIndex removeAllObjects];
NSMutableSet *keys = [[NSMutableSet alloc] init];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy/MM/dd"];
for(int i=0;i<[arrayObjects count];i++){
Task *myTask=[arrayObjects objectAtIndex:i];
//curentsection contains my objects whith dates
NSMutableArray *currentSection = [objects objectForKey:taskDate];
if (currentSection == nil)
{
[keys addObject:taskDate];
currentSection = [[[NSMutableArray alloc] init] autorelease];
[objects setObject:currentSection forKey:taskDate];
}
// we add objet to the right section
[currentSection addObject:myTask];
}
[dateFormatter release];
for (id element in keys)
{
[objectsIndex addObject:element];
NSMutableArray *currentSection = [objects objectForKey:element];
//I get an error in this line
[currentSection sortUsingSelector:#selector(compare:)];
}
You haven't mentioned what the error message is and I am assuming the error message may be due to accessing NSMutableArray array object without initializing it. Try an alloc and init for array before
NSMutableArray *currentSection = [NSMutableArray]alloc]init];
currentSection = [objects objectForKey:element];
//I get an error in this line
[currentSection sortUsingSelector:#selector(compare:)];
Well it is purely a guess. Post your error message if this not works.
Bharath