I'm trying to retrieve data from web service and then filter the data and store it in another array based on a value. However, I get the following error whenever I try to filter it:
*** Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[__NSCFDictionary Month]:
unrecognized selector sent to instance 0x174079640'
This is my code:
- (void)getDataHTTPClient:(Client *)client didUpdateWithData:(id)data
{
[self.view setUserInteractionEnabled:YES];
if (isPullRefresh)
{
isPullRefresh = NO;
[datasource removeAllObjects];
[self.pullToRefreshView finishLoading];
}
NSMutableArray *array = (NSMutableArray *)data;
if (![array count])
{
isNewsEnded = YES;
[self.tableView reloadData];
return;
}
[hud hide:YES];
[datasource addObjectsFromArray:(NSMutableArray *) data];
NSDate *currentDate = [NSDate date];
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDateComponents* components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:currentDate];
monthInt= [components month];
NSLog(#"month %li", monthInt);
NSLog(#"month after deduction %li", monthInt-1);
monthString = [NSString stringWithFormat:#"%zd",monthInt];
for (EventsBean *item in datasource)
{
if([item.Month isEqualToString:monthString])
{
[filteredArray addObject:item];
}
}
[self.tableView reloadData];
if ([datasource count])
{
[self displayNoRecordMSG:NO];
}
else
{
[self displayNoRecordMSG:YES];
}
}
the error shows on this line
if([item.Month isEqualToString:monthString])
{
[filteredArray addObject:item];
}
The data you received over the network will most likely not be an instance of EventsBean class. From the error log, it looks like it is actually a NSDictionary object. I'm guessing it is already parsed from a JSON string for you. So I would probably try to access the month property by doing item[#"Month"] instead.
for (EventsBean *item in datasource)
Here datasource contains objects of NSDictionaries and not objects of EventBeans.
Either you need to parse that dictionary and create object of EventsBean
Or
You need to do something like this
if([[item objectForKey:#"Month"] isEqualToString:monthString])
Related
Hi I'm making a synchronise function that update database when receive JSON response from server. I want the import only take place if there are different data (new record or update existing record) (To increase performance) (Using coredata and magicalRecord)
Here is my JSON parser method
- (void)updateWithApiRepresentation:(NSDictionary *)json
{
self.title = json[#"Name"];
self.serverIdValue = [json[#"Id"] integerValue];
self.year = json[#"Year of Release"];
self.month = json[#"Month of Release"];
self.day = json[#"Day of Release"];
self.details = json[#"Description"];
self.coverImage = json[#"CoverImage"];
self.thumbnail = json[#"Thumbnail"];
self.price = json[#"Buy"];
NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
[formatter setDateFormat:#"dd/MMMM/yyy"];
NSDate *date = [formatter dateFromString:[NSString stringWithFormat:#"%#/%#/%#",self.day,self.month,self.year]];
self.issueDate = date;
}
And my import method
+ (void)API_getStampsOnCompletion:(void(^)(BOOL success, NSError *error))completionBlock
{
[[ApiClient sharedInstance] getStampsOnSuccess:^(id responseJSON) {
NSManagedObjectContext *localContext = [NSManagedObjectContext MR_context];
NSMutableArray *stamps = [[NSMutableArray alloc]init];
[responseJSON[#"root"] enumerateObjectsUsingBlock:^(id attributes, NSUInteger idx, BOOL *stop) {
Stamp *stamp = [[Stamp alloc]init];
[stamp setOrderingValue:idx];
[stamp updateWithApiRepresentation:attributes];
[stamps addObject:stamp];
}];
[Stamp MR_importFromArray:stamps inContext:localContext];
} onFailure:^(NSError *error) {
if (completionBlock) {
completionBlock(NO, error);
}
}];
}
I'm getting error
CoreData: error: Failed to call designated initializer on NSManagedObject class 'Stamp'
2016-08-02 23:52:20.216 SingPost[2078:80114] -[Stamp setOrdering:]: unrecognized selector sent to instance 0x78f35a30
I have checked my Json parser is working fine. The problem is with my import method. I don't know what wrong with the function. Any help is much appreciate. Thanks!
The error message clearly describes the exact problem. You do this:
Stamp *stamp = [[Stamp alloc]init];
But init is not the designated initializer for NSManagedObject unless you added init in your subclass (which you didn't mention doing). You must call the designated initializer, which is initWithEntity:insertIntoManagedObjectContext:. There's also a convenience factory method on NSEntityDescription called insertNewObjectForEntityForName:inManagedObjectContext:. Either of those will work, but calling init will not.
When processing a json response I a get the below error:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[DADGList setDescription:]:
unrecognized selector sent to instance 0x7ae88880'
The class it crashed on:
#implementation DADGList
-(id)copy
{
DADGList *list = [[DADGList alloc] init];
list.identifier = self.identifier;
list.name = [self.name copy];
list.description = [self.description copy];
list.created = [self.created copy];
list.itemCount = self.itemCount;
list.shareLink = [self.shareLink copy];
return list;
}
+(DADGList *)listFromDictonary:(NSDictionary *)dictonary
{
DADGList *list = [[DADGList alloc] init];
NSLog( #"%#", dictonary );
list.identifier = [[dictonary objectForKey:#"list_id"] integerValue];
list.itemCount = [[dictonary objectForKey:#"list_items_count"] integerValue];
list.name = [NSString stringWithString:[dictonary objectForKey:#"list_name"]];
list.description = [NSString stringWithString:[dictonary objectForKey:#"list_description"]];
list.created = [[NSDate alloc] initWithTimeIntervalSince1970:[[dictonary objectForKey:#"list_created"] doubleValue]];
list.shareLink = [NSString stringWithString:[dictonary objectForKey:#"list_share_url"]];
return list;
}
and the dictonary that is past to listFromDictonary:
You should rename your description property for something else as this is a field already existing in the iOS echosystem (NSObject if I am not mistaken) and that creates all sort of weird crash like this.
If you are using core data maybe you need to implement the following instance:
Mall(entity: NSEntityDescription.entity(forEntityName: "Mall", in: context)!, insertInto: nil)
Where Mall is my entity and context is my view context.
I'm on Xcode 6.0.1, making a test app with Event Kit. The following code successfully populates each event's title, but its notes are returned as (null) even when hasNotes property returns YES. And, I can see the notes for the same event on iPhone's default calendar app.
What am I doing wrong?
- (void)viewDidLoad
{
[super viewDidLoad];
[eventStore requestAccessToEntityType:EKEntityTypeEvent
completion:^(BOOL granted, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error)
{
NSLog(#" !! error");
// display error message here
}
else if (!granted)
{
NSLog(#"Not Granted");
// display access denied error message here
}
else
{
// access granted
NSCalendar *calendar = [NSCalendar currentCalendar];
// Create the start date components
NSDateComponents *oneWeekAgoComponents = [[NSDateComponents alloc] init];
oneWeekAgoComponents.day = -1;
NSDate *oneWeekAgo = [calendar dateByAddingComponents:oneWeekAgoComponents toDate:[NSDate date] options:0];
// Create the end date components
NSDateComponents *oneMonthFromNowComponents = [[NSDateComponents alloc] init];
oneMonthFromNowComponents.month = 1;
NSDate *oneMonthFromNow = [calendar dateByAddingComponents:oneMonthFromNowComponents toDate:[NSDate date] options:0];
// Create the predicate from the event store's instance method
NSPredicate *predicate = [eventStore predicateForEventsWithStartDate:oneWeekAgo endDate:oneMonthFromNow calendars:nil];
// Fetch all events that match the predicate
_eventArray = [eventStore eventsMatchingPredicate:predicate];
[self.tableView reloadData];
}
});
}];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
EKEvent *event = [self.eventArray objectAtIndex:indexPath.row];
cell.textLabel.text = event.title;
if (event.hasNotes) {
cell.detailTextLabel.text = event.notes;
} else {
cell.detailTextLabel.text = #"";
}
return cell;
}
I haven't fully resolved it, but got a clue.
NSArray *events = [eventStore eventsMatchingPredicate:predicate];
This didn't get the notes. So, instead I enumerate through returned events by doing
[eventStore enumerateEventsMatchingPredicate:predicate usingBlock:^(EKEvent *event, BOOL *stop) {
NSLog(#"title: %#",event.title);
NSLog(#"hasNotes: %s",event.hasNotes ? "YES":"NO");
NSLog(#"notes: %#",event.notes);
NSLog(#"-----");
[_eventTitles addObject:event.title];
[_eventTitles addObject:event.hasNotes ? event.notes : #""];
}];
This one returns actual notes (null).
I had a similar issue like this but when accessing the calendar object from the EKEvent. I my case this was because I had released the EKEventStore instance before I attempted to access the calendar (in cellForRowAtIndexPath:).
According to the Apple documentation "Reading and Writing Calendar Events":
An event store instance must not be released before other Event Kit
objects; otherwise, undefined behavior may occur.
https://developer.apple.com/library/mac/documentation/DataManagement/Conceptual/EventKitProgGuide/ReadingAndWritingEvents.html#//apple_ref/doc/uid/TP40004775-SW1
Im quiet new to Xcode and objective-C and Im trying to build this app about events, I have two buttons in my mainViewController one to show today's events and the other will show any future events, my data are coming from a json file [which will include several keys one of them is the date of the event] and the way I thought about how the app will show this by matching the date of the event with the date of the calendar within the app and and I used this code:
#implementation MV_HomeViewController {
NSArray *_events;
}
.....
.......
- (IBAction)upcomingEvents:(id)sender {
// Events *event = [_events object:.row];
//Events *event = [_events objectForKey:#"Events"];
NSDate *currDate = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"dd-MM-YYYY"];
NSString *dateString = [dateFormatter stringFromDate:currDate];
if([_events objectForKey:#"date"] != dateString){
[[self myTableView] reloadData];
}
}
but it is giving me an error # [_events objectForKey:#"date"] which is totally make sense because I have to call my json data again within this action and that is I don't know how to do ?? can anyone plz tell me how to do that or how to make the above code works for my app?
I would be very appreciated.
PS, for more details about how my json file looks like plz see the previous question that I have posted.
Thanks,
I tried the implement the answer below but this with this code:
for (NSDictionary *event in _events) {
// Now you can use [event objectForKey:#"date"] to retrieve the event date
if ([[event objectForKey:#"date"] isEqualToString:dateString]){
[[self myTableView] reloadData];
}
}
but this time Im getting an error saying --> -[Events objectForKey:]: unrecognized selector sent to instance 0x74303f0
Could anyone plzzz tell me what is the problem now!! Im sooo confused ...
objectForKey: is a NSDictionary method, not a NSArray method. To retrieve an event dictionary from the array, you would use objectAtIndex:. If you want to loop over all the event dictionaries in the array, you can use fast enumeration like so:
for (NSDictionary *event in _events) {
// Now you can use [event objectForKey:#"date"] to retrieve the event date
}
When comparing strings, use isEqualToString: rather than the equality operator (==) or inequality operator (!=).
I'm doing my head in trying to figure out an issue I'm having with core-data. I understand what the error means, and I've had it before (and fixed it) but I can't figure out why I'm getting it now.
My app has the following structure :
MPModel -> MPPlace and MPModel -> MPProject
Where MPModel is a subclass of NSManagedObject and MPPlace and MPProject are subclasses of MPModel.
The data model has a relationship between MPPlace and MPProject where MPPlace has-many MPProjects and MPProject belongs-to MPPlace.
When the app loads, it fetches a number of MPPlace objects which works perfectly. When a user selected a place and then selects the projects option, the app attempts to retrieve the list of projects. This is where the app fails however, with the following error
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason:
'Failed to process pending changes before save. The context is still dirty after 100
attempts. Typically this recursive dirtying is caused by a bad validation method,
willSave, or notification handler.'
Each MPModel contains a number of custom methods, including saveAllLocally which simply saves an array of objects to the persistence store if they don't already exist, and loadNestedResources which fetches new objects from the server that are related to the current object. I am finding that the failure is occurring with the loadNestedResources method but I can't figure out why.
The loadNestedResources method looks like this :
- (void) loadNestedResourcesOfType:(Class)type atURL:(NSString *)resURL withBlock:(MPFindObjectsBlock)block
{
if (![type isSubclassOfClass:[MPModel class]]) {
block(nil, nil);
} else {
NSString *url = [NSString stringWithFormat:#"%#%#/%#%#", kMP_BASE_API_URL, [self.class baseURL], self.objID, [type baseURL]];
MPRequest *request = [[MPRequest alloc] initWithURL:url];
// Attempt to see if we already have this relation
NSString *relation = [[MPUtils stripClassName:type].lowercaseString stringByAppendingString:#"s"];
NSSet *relatedObjects = [self valueForKey:relation];
if (relatedObjects && relatedObjects.count > 0) {
// We have some objects so lets exclude these from our request
NSMutableArray *uuids = [NSMutableArray arrayWithCapacity:0];
for (MPModel *obj in relatedObjects) {
[uuids addObject:obj.uuid];
}
[request setParam:[uuids componentsJoinedByString:#";"] forKey:#"exclude_uuids"];
}
[MPUser signRequest:request];
[request setRequestMethod:#"POST"];
[request submit:^(MPResponse *resp, NSError *error) {
if (error) {
if (relatedObjects.count > 0) {
block([relatedObjects allObjects], nil);
} else {
block(nil, error);
}
} else {
// Combine all of our objects
NSMutableArray *allObjects = [[type createListWithResponse:resp] mutableCopy];
if (allObjects.count > 0) {
[allObjects addObjectsFromArray:[relatedObjects allObjects]];
// Make sure they're now all saved in the persistence store
NSArray *savedObjects = [MPModel saveAllLocally:allObjects forEntityName:NSStringFromClass(type)];
for (NSObject *obj in savedObjects) {
[obj setValue:self forKey:[MPUtils stripClassName:self.class].lowercaseString];
}
// Set them as our related objects for this relationship
[self setValue:[NSSet setWithArray:savedObjects] forKey:relation];
[MPModel saveAllLocally:savedObjects forEntityName:NSStringFromClass(type)];
block(allObjects, nil);
} else {
block([relatedObjects allObjects], nil);
}
}
}];
}
}
The methods runs perfectly right up until the second call to saveAllLocally which is where I get the error. The MPModel class also uses the willSave method, which has the following :
- (void) willSave
{
NSDate *now = [NSDate date];
if (!self.updated_at) {
self.updated_at = now;
}
if (!self.created_at) {
self.created_at = now;
}
if (!self.uuid) {
self.uuid = [self createUUID];
}
if (!self.last_sync) {
self.last_sync = now;
}
if ([self isUpdated] && self.changedValues.count > 0) {
if (!self.attribute_updated_at) {
NSDictionary *attributes = [self.entity attributesByName];
NSMutableDictionary *dates = [NSMutableDictionary dictionaryWithCapacity:0];
for (NSString *attr in attributes.allKeys) {
[dates setObject:now forKey:attr];
}
[self setAttributeUpdatedDates:dates];
}
if (_updatedAtSet) {
_updatedAtSet = NO;
} else {
if ([self.changedValues.allKeys containsObject:#"last_sync"]) {
self.updated_at = [self.changedValues objectForKey:#"last_sync"];
} else {
self.updated_at = [NSDate date];
}
_updatedAtSet = YES;
NSDictionary *changed = [self changedValues];
NSMutableDictionary *dates = [[self attributeUpdatedDates] mutableCopy];
for (NSString *key in changed.allKeys) {
[dates setObject:now forKey:key];
}
[self setAttributeUpdatedDates:dates];
}
}
}
From what I can gather, this should be fine as it shouldn't be setting any more values if the _updatedAtSet variable is set to true, however it is still breaking and I cannot figure out why!
Please can someone help me
Thanks
Have solved it.
I just moved the _updatedAtSet = NO; into the didSave method rather than where it is and it's working fine now. Thanks anyway