IOS: NSKnownKeysDictionary1 error - ios

I have an object selectedActivity defined as follows:
#property (strong, nonatomic) Activities *selectedActivity;
At the point I need to work with it logs out as:
{
actname = "Running";
aid = 23;
}
The Activities object is an NSManaged object and its .h file looks like this.
#interface Activities : NSManagedObject
#property (nonatomic, retain) NSString * actname;
#property (nonatomic, retain) NSNumber * aid;
#end
I am trying to place one of the object properties in a variable to work with it using the following:
NSNumber *aid = _selectedActivity.aid;
However, the above line gives the following error message:
[NSKnownKeysDictionary1 aid]: unrecognized selector sent to instance 0x147842fb0
Can anyone explain this error and how to fix it?
Thanks for any suggestions.
Update:
setting of selected activity
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
_selectedActivity =([_activities objectAtIndex:row]);
NSLog(#"selectedActivity in pickerview%#",_selectedActivity);
}
//activities in .h file
#property (strong, nonatomic) NSArray *activities;
//setting of activities
self.activities= [self getActivities];
//method that gets activities
- (id) getActivities{
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"Activities"];
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:#"created" ascending:NO];
[fetchRequest setSortDescriptors:#[sort]];
NSError *error = nil;
self.managedObjectContext = [Model sharedInstance].managedObjectContext;
NSArray *results = [self.managedObjectContext executeFetchRequest:fetchRequest
error:&error];
NSMutableArray *mutableresults = [results mutableCopy];
[mutableresults removeObjectIdenticalTo:[NSNull null]];
return mutableresults;
}

The results are coming as a dictionary.
instead of the usual NSManagedObject-style value retrieval:
Objective-C
NSString *actname = _selectedActivity.actname;
NSNumber *aid = _selectedActivity.aid;
Swift
let actname:String = _selectedActivity.actname
let aid:Int = _selectedActivity.aid
Use the NSDictionary-style value retrieval, like so:
Objective-C:
NSString *actname = [_selectedActivity valueForKey:#"actname"];
NSNumber *aid = [[_selectedActivity valueForKey:#"aid"] intValue];
Swift (tested as of 3.0.1)
_selectedActivity(forKey: "actname") as! String
_selectedActivity.value(forKey: "aid") as! Int

Related

Sort Object inside NSArray?

I have an object, as below
#import <Foundation/Foundation.h>
#interface CountriesDAO : NSObject
#property (nonatomic, retain) NSString * countryname;
#end
#import "CountriesDAO.h"
#implementation CountriesDAO
#synthesize countryname;
#end
I have saved this in Array within appDelegate.
#property (nonatomic, retain) NSArray *countriesArray;
#synthesize countriesArray;
In another controller, I fetch it like
NSArray *countriesArray = appDelegate.countriesArray; It works fine and I get array.
As I try to sort it by this way.
NSArray *countriesArray1 = appDelegate.countriesArray;
NSSortDescriptor *valueDescriptor = [[NSSortDescriptor alloc] initWithKey:#"countryname" ascending:YES];
NSArray * descriptors = [NSArray arrayWithObject:valueDescriptor];
countriesArray = [countriesArray1 sortedArrayUsingDescriptors:descriptors];
I get error
[__NSCFType count]: unrecognized selector sent to instance 0xa83b4d0
2013-11-01 13:21:08.882 ECP[13597:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFType count]: unrecognized selector sent to instance 0xa83b4d0'
Here countriesArray is defined as
#property (nonatomic, retain) NSArray *countriesArray;
I did it like this and it worked for me.
countriesArray = [[NSMutableArray alloc] init];
for (CountriesDAO *info in appDelegate.countriesArray) {
[countriesArray addObject:info.countryname];
}
[countriesArray sortUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
You can also try...
[countriesArray1 sortUsingSelector:#selector(compare:)];
Should work
NSMutableArray *sortedArray = [appDelegate.countriesArray mutableCopy];
[sortedArray sortUsingComparator:^NSComparisonResult(CountriesDAO *object1,
CountriesDAO *object2) {
return [object1.countryname caseInsensitiveCompare:object2.countryname];
}];
NSArray *sortedCountriesArray = [sortedArray copy];
If something went wrong, check the type of object1 and object2
Its is simple Way to sort array in iOS,it's helps to you
[countriesArray sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [ String_1 compare: String_2];
}];
// String_1, String_2 are NSString,it's contains in countriesArray
// use NSMutableArray to rearrange and change values in countriesArray
If the array you want to sort contains NSString (which is what I get from your description) you can replace your sorting code with this:
sortedArray = [countriesArray1 sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];

Adding to created Entities attributes using Magical Record

so I am using Magical Record in my project, and I am attempting to do the following:
- (void)persistNewReadingWithOneA:(NSString *)oneA oneB:(NSString *)oneB{
NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextForCurrentThread];
FinalRead *reading1A = [FinalRead MR_createInContext:localContext];
reading1A.a1 = oneA;
reading1A.b1 = oneB;
[localContext MR_saveOnlySelfAndWait];
}
As you can see I've persisted with a new entry and now I need to be able to update that same entry by adding to it's attributes. I tried doing the following:
- (void)updateReadingWithTwoA:(NSString *)twoA twoB:(NSString *)twoB{
NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextForCurrentThread];
FinalRead *reading2A = [FinalRead MR_createInContext:localContext];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"firstname ==[c] %# AND lastname ==[c] %#"];
FinalRead *finalRead = [FinalRead MR_findFirstWithPredicate:predicate inContext:localContext];
reading2A.a2 = twoA;
reading2A.b2 = twoB;
[localContext MR_saveOnlySelfAndWait];
}
Any Ideas?
EDIT:
I am fetching data from a JSON response like so:
- (void)fetchedData:(NSData *)responseData {
if (self.buttonPressed){
//parse out the json data
NSError* error;
NSArray* json = [NSJSONSerialization
JSONObjectWithData:responseData
options:kNilOptions
error:&error];
NSString *string = [NSString stringWithFormat:#"%#", [json objectAtIndex:0]];
[self persistNewReadingWithOneA:string
oneB:nil];
}else{
//parse out the json data
NSError* error;
NSArray* json = [NSJSONSerialization
JSONObjectWithData:responseData
options:kNilOptions
error:&error];
NSString *string = [NSString stringWithFormat:#"%#", [json objectAtIndex:0]];
[self persistNewReadingWithOneA:nil
oneB:string];
}
}
and then storing to a newly created object like so:
- (void)persistNewReadingWithOneA:(NSString *)oneA oneB:(NSString *)oneB{
NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextForCurrentThread];
FinalRead *reading1A = [FinalRead MR_createInContext:localContext];
reading1A.a1 = oneA;
reading1A.b1 = oneB;
[localContext MR_saveOnlySelfAndWait];
}
The ViewController then pushes to another that asks another question where once again more JSON is parsed and stored, but into the SAME object that was just created in the previous ViewController. I have the following attributes PER object in NSManagedObject:
#interface FinalRead : NSManagedObject
#property (nonatomic, retain) NSString *a1;
#property (nonatomic, retain) NSString *b1;
#property (nonatomic, retain) NSString *a2;
#property (nonatomic, retain) NSString *b2;
#property (nonatomic, retain) NSString *a3;
#property (nonatomic, retain) NSString *b3;
#property (nonatomic, retain) NSString *a4;
#property (nonatomic, retain) NSString *b4;
#end
So basically, every time that I change a new viewController I'm wanting to add to that same object until the final View has been used.
Your update method also creates a new object:
FinalRead *reading2A = [FinalRead MR_createInContext:localContext];
// ... other stuff
reading2A.a2 = twoA;
reading2A.b2 = twoB;
And the object fetched here:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"firstname ==[c] %# AND lastname ==[c] %#"];
FinalRead *finalRead = [FinalRead MR_findFirstWithPredicate:predicate inContext:localContext];
is completely unused. In fact I would expect that fetch request to crash, because the
predicate uses %# formats for which no arguments are supplied.
To update an object, you have to fetch it first. And to fetch it you need some
attributes which identify the object that you want to update. For example:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"firstname ==[c] %# AND lastname ==[c] %#",
firstName, lastName];
FinalRead *finalRead = [FinalRead MR_findFirstWithPredicate:predicate inContext:localContext];
if (finalRead) {
finalRead.a2 = twoA;
finalRead.b2 = twoB;
// ... save context ...
} else {
// no matching object found
}
Update: The solution in your case might be to pass the finalRead object from one
view controller to the next, instead of re-fetching it in each view controller.

EXC_BAC_ACCESS error when saving core data Boolean field

I am getting a EXC_BAC_ACCESS error when attempting to save a TRUE value into a managed object that contains a Boolean attribute.
id delegate = [[UIApplication sharedApplication] delegate];
self.managedObjectContext = [delegate managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"TrafficCameraInfo"
inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"code=%#",self.selectedTrafficCamera.code]];
NSError *error;
TrafficCameraInfo *cgTrafficCamera;
cgTrafficCamera = [[self.managedObjectContext executeFetchRequest:fetchRequest error:&error] lastObject];
NSString *alertMessage;
if (cgTrafficCamera.favourite == NO){
cgTrafficCamera.name = #"TEST"; <-- works ok
cgTrafficCamera.favourite = 1; <-- causes an error
} else {
cgTrafficCamera.favourite = 0;
}
error = nil;
if (![self.managedObjectContext save:&error]) {
The managed object interface looks like this:
#interface TrafficCameraInfo : NSManagedObject
#property (nonatomic, retain) NSString *code;
#property (nonatomic, retain) NSString *postCode;
#property (nonatomic, retain) NSNumber *latitude;
#property (nonatomic, retain) NSNumber *longitude;
#property (nonatomic, retain) NSString *name;
#property (nonatomic, retain) NSString *url;
#property (nonatomic) Boolean favourite;
#end
Elsewhere in my app i am updating another Boolean field by passing a 1 to it and am not encountering a problem.
Any ideas what is causing the error?
I think in your core data attribute table you define "favorite" variable to BOOL,well that means it's an NSNumber Type,so you should set the data using NSNumber
A Boolean is a simple, scalar, non-pointer datatype. Core Data properties are always stored as objects. The Objective-C object wrapper for numeric datatypes is NSNumber. So if favourite is a regular stored property, you should declare it as:
#property (nonatomic, retain) NSNumber *favourite;
Assignment would be done like this:
cgTrafficCamera.favourite = [NSNumber numberWithBool:YES]; // Obj-C style is "YES/NO" for BOOL
Or this if you prefer:
cgTrafficCamera.favourite = [NSNumber numberWithBool:1];
If you don't need to store the Boolean, you can leave it as such and make it a transient property. You'll probably need to get rid of the "(nonatomic)" in that case.

Core Data one-to-many relation won't take values, how do I have do use the accessor methods?

I want to save a method, which has some relations to other Entities. The approach and background are to-one relations, but the method should have be able to have several tipps and examples. I already looked at many other questions and tutorials but I do not know why it won't work.
dataToBeSaved is a Dictionary containing the data as Strings I want to assign to the method.
Here is Method.h
#interface Method : NSManagedObject
#property (nonatomic, retain) NSNumber * id;
#property (nonatomic, retain) NSString * name;
#property (nonatomic, retain) Approach *methodtoapproach;
#property (nonatomic, retain) Background *methodtobackground;
#property (nonatomic, retain) NSSet *methodtoexample;
#property (nonatomic, retain) NSSet *methodtotipps;
#end
#interface Method (CoreDataGeneratedAccessors)
- (void)addMethodtoexampleObject:(Example *)value;
- (void)removeMethodtoexampleObject:(Example *)value;
- (void)addMethodtoexample:(NSSet *)values;
- (void)removeMethodtoexample:(NSSet *)values;
- (void)addMethodtotippsObject:(Tipps *)value;
- (void)removeMethodtotippsObject:(Tipps *)value;
- (void)addMethodtotipps:(NSSet *)values;
- (void)removeMethodtotipps:(NSSet *)values;
#end
and here is my code, I let the commented sections in it, so you can see what I tried to to...
Method *newMethod = [NSEntityDescription insertNewObjectForEntityForName:#"Method" inManagedObjectContext:managedObjectContext];
// [newMethod setValue:[dataToBeSaved objectForKey:#"name"] forKey:#"name"];
// [newMethod setValue:[NSNumber numberWithInt:11] forKey:#"id"];
newMethod.name = [dataToBeSaved objectForKey:#"name"];
newMethod.id = [NSNumber numberWithInt:11];
newMethod.methodtoapproach.summary = [dataToBeSaved objectForKey:#"summary"];
newMethod.methodtobackground.background = [dataToBeSaved objectForKey:#"background"];
NSMutableSet *tippsSet = [[NSMutableSet alloc] initWithObjects:[dataToBeSaved objectForKey:#"tipps"], nil];
NSMutableSet *exampleSet = [[NSMutableSet alloc] initWithObjects:[dataToBeSaved objectForKey:#"example"], nil];
[newMethod addMethodtotipps:tippsSet];
[newMethod addMethodtoexample:exampleSet];
// [[newMethod mutableSetValueForKey:#"methodtotipps"] addObject:[dataToBeSaved objectForKey:#"tipps"]];
// [[newMethod mutableSetValueForKey:#"methodtoexample"] addObject:[dataToBeSaved objectForKey:#"example"]];
// [newMethod addMethodtotippsObject:[dataToBeSaved objectForKey:#"tipps"]];
// [newMethod addMethodtoexampleObject:[dataToBeSaved objectForKey:#"example"]];
// newMethod.methodtotipps.tipps = [dataToBeSaved objectForKey:#"tipps"];
// newMethod.methodtoexample.example = [dataToBeSaved objectForKey:#"example"];
if I run the app exactly like that, I get the error:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString entity]: unrecognized selector sent to instance xxx
if you need more information, just post it in the comments...
Actually, it now worked for me like this:#
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
managedObjectContext = [appDelegate managedObjectContext];
fetchedResultsController = [appDelegate fetchedResultsController];
Method *newMethod = [NSEntityDescription insertNewObjectForEntityForName:#"Method" inManagedObjectContext:managedObjectContext];
Approach *newApproach = [NSEntityDescription insertNewObjectForEntityForName:#"Approach" inManagedObjectContext:managedObjectContext];
Background *newBackground = [NSEntityDescription insertNewObjectForEntityForName:#"Background" inManagedObjectContext:managedObjectContext];
Tipps *newtipp = [NSEntityDescription insertNewObjectForEntityForName:#"Tipps" inManagedObjectContext:managedObjectContext];
Example *newExample = [NSEntityDescription insertNewObjectForEntityForName:#"Example" inManagedObjectContext:managedObjectContext];
[newMethod setName:[dataToBeSaved objectForKey:#"name"]];
[newMethod setId:[NSNumber numberWithInt:11]];
newApproach.summary = [dataToBeSaved objectForKey:#"summary"];
newBackground.background = [dataToBeSaved objectForKey:#"background"];
newtipp.tipps = [dataToBeSaved objectForKey:#"tipps"];
newExample.example = [dataToBeSaved objectForKey:#"example"];
NSMutableSet *tippsSet = [NSMutableSet set];
NSMutableSet *examplesSet = [NSMutableSet set];
[newMethod setMethodtoapproach:newApproach];
[newMethod setMethodtobackground:newBackground];
[newMethod setMethodtoexample:examplesSet];
[newMethod setMethodtotipps:tippsSet];
[newMethod addMethodtoexampleObject:newExample];
[newMethod addMethodtotippsObject:newtipp];
NSError *error;
if (managedObjectContext != nil)
{
if([managedObjectContext hasChanges])
{
[managedObjectContext save:&error];
if(error)
{
NSLog(#"Error Saving data: %#", [error userInfo]);
}
}
}
might be just what #Fogmeister meant but I'm (up till now) fine with how it works. Maybe later there is some optimization necessary... I'll post it here if so...
Yeah, I was caught out by this also.
If you want to use the methods...
- (void)add<blah>Object...
Then you need to write it yourself.
What I actually do is create the relationship the other way around.
instead of creating the child and then adding the child to the parent. I create the child and then tell the child what its parent is.

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