iOS/objective-c: Spooky error setting value of object - ios

I have copied some code that works fine for saving an api to one entity in core data over to save a similar api to another entity. Although everything is largely the same, I cannot get rid of exception error.
Here is the code that throws the exception:
- (NSMutableArray *) convertFeedtoObject:(NSMutableArray*)feed {
NSMutableArray * _newitems = [[NSMutableArray alloc] init];
for (int i = 0; i < feed.count; i++) {
NSDictionary *feedElement = feed[i];
ItemOnServer *newItem = [[ItemOnServer alloc] init];
newItem.itemtitle = feedElement[#"itemtitle"]; //throws exception
newItem.item = feedElement[#"item"];//also throws an exception if above commented out
newItem.descript = #"some item"; //if above lines commented out, littoral throws exception too.
//same goes for any other values I try to set. The first one throws exception.
Here is the error:
2015-11-20 05:26:03.281 [20610:60b] -[ItemOnServer setItem:]: unrecognized selector sent to instance 0x175721b0
No matter what values I try to set, I get a similar error even though I know the values are there.
One item of the feed looks like this:
{
lastviewed = "2015-11-17 15:21:45";
itemtitle = "New";
id = 944;
item = "cotton shirt";
}
)
Thanks for any suggestions.
Edit:
Code from ItemOnServer.h
//.m file is largely empty
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#class ItemsVC;
#class Vendors;
#interface ItemOnServer : NSObject
#property (nonatomic, retain) NSString * item;
#property (nonatomic, retain) NSNumber * id;//this is permanent id shared with server
#property (nonatomic, retain) NSNumber * localid; //this is temp id if first created locally
#property (nonatomic, retain) NSString * itemtitle;
#property (nonatomic, retain) NSDate * lastviewed;
//this is relationship with vendors
#property (nonatomic, retain) Vendors *vendor;
#end

Instead of using an NSDictionary declare feedElement as an NSMutableArray, so something like:
- (NSMutableArray *) convertFeedtoObject:(NSMutableArray*)feed {
NSMutableArray * _newitems = [[NSMutableArray alloc] init];
NSMutableArray *feedElement = [[NSMutableArray alloc] init];
for (int i = 0; i < feed.count; i++) {
feedElement = feed[i];
ItemOnServer *newItem = [[ItemOnServer alloc] init];
newItem.itemtitle = feedElement[#"itemtitle"];
...

It looks like your class ItemOnServer doesn't have implementations for the methods setItem:, setItemtitle and so on. I don't know how you managed to do this, but you should look at the interface and implementation of ItemOnServer.
Look at what the error message says:
-[ItemOnServer setItem:]: unrecognized selector
That means a setItem: message is sent to an object, that object is an ItemOnServer object, and it doesn't implement setItem: The first two of these three points are exactly what you expect to happen when you write newItem.item = ...
Do you have another class named ItemOnServer in your application, maybe linked through some library? You can easily check by renaming ItemOnServer with ItemOnServer2 and checking what happens.

Related

How can I ensure value is in the custom class property at the NSMutableArray?

I create the custom class name with FileModel.
FileModel.h
#import <Foundation/Foundation.h>
#interface FileModel : NSObject
#property (nonatomic, copy) NSString *fileName;
#property (nonatomic, copy) NSString *fileType;
#property (nonatomic, strong) NSDate *editDate;
#property (nonatomic, assign) NSInteger fileSize;
#end
I want to compare the particular string with the fileName.
I create the sample like below .m
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *fileSampleName = [[NSArray alloc] initWithObjects:#"apple.png",#"banana.png",#"cherry.png",#"durian.png",#"grape.png",#"avocado.png", nil];
NSMutableArray *fileData = [NSMutableArray new];
FileModel *fileModel = nil;
for( NSInteger i = 0 ; i < fileSampleName.count ; i++){
fileModel = [FileModel new];
fileModel.fileName = [fileSampleName objectAtIndex:i];
fileModel.fileType = #"photo";
fileModel.fileSize = 0;
fileModel.editDate = [NSDate new];
[fileData addObject:fileModel];
}
// fileData's fileName containsObject #"grape" or not?
}
NSArray has containsObject method.
But How can I check the #"grape" is containsObject using fileData at the custom class property filename?
I known using for loop compare one by one.
Did they have other method to check like containsObject?
--- edit---
I try to using indexOfObjectPassingTest method , But the result always is 1.
BOOL result = [fileData indexOfObjectPassingTest:^ BOOL (id tr,NSUInteger index, BOOL *te){
FileModel *fileModel = (FileModel*)tr;
if([#"orange" isEqualToString: fileModel.fileName]){
*te = YES;
return YES;
}else{
return NO;
}}];
NSLog(#"result:%#",#(result)); // it always return 1
Why? thank you very much.
Take a look that NSArray class reference in Xcode. One method you could use is indexOfObjectPassingTest. There are number of related methods depending on your needs. All take a block that's used to test objects to see if they meet whatever criteria you want. In your case you'd test the fileName string.
So you'd pass in a closure that compared the fileName property of each object to your desired filename.

iOS - JSONModel with dynamic key

I am calling a web service which returns dictionary to render the graph. Dictionary structure is
{"1":0,"2":0,"8":0,"9":2,"10":3,"11":0,"12":0}
The problem is keys are dynamic values like 1,2,3 etc which indicates month. Is it possible to represent this in JsonModel?
See you cant create properties at run time as per response structure. But we can smartly use pre-defined things and achieve this. Do following steps:
Create one model class. So your MyCustomModel.h file will look like this
#import <Foundation/Foundation.h>
#interface MyCustomModel : NSObject
#property (nonatomic, retain) NSString * myCustomKey;
#property (nonatomic, retain) NSString * myCustomValue;
#end
This will be your MyCustomModel.m file
#import "MyCustomModel.h"
#implementation MyCustomModel
#synthesize myCustomKey, myCustomValue;
-(id)init {
self = [super init];
myCustomKey = #"";
myCustomValue = #"";
return self;
}
#end
Now lets suppose {"1":0,"2":0,"8":0,"9":2,"10":3,"11":0,"12":0} is NSDictionary and lets say its name is dictionaryResponse
Now do this stuffs:
NSArray *responseKeys = [[NSArray alloc]init];
responseKeys = [dictionaryResponse allKeys];
So your responseKeys will have all keys of response like ["1","2","8","9","10","11","12",]
Now you can iterate loop and create NSMutableArray of model objects as
NSMutableArray *arrayMonthList = [[NSMutableArray alloc]init];
for (int i = 0; i < responseKeys.count; i++) {
MyCustomModel *myModelObject = [[MyCustomModel alloc]init];
myModelObject.myCustomKey = [NSString stringWithFormat:#"%#",[responseKeys objectAtIndex:i]];
myModelObject.myCustomValue = [dictionaryResponse valueForKey:[NSString stringWithFormat:#"%#",[responseKeys objectAtIndex:i]]];
[arrayMonthList addObject:myModelObject];
}
Now arrayMonthList will consist of objects of type MyCustomModel
So you can use it and parse it. Even you can use it to show on UITableView. Following code is written to print values of model properties, you can customise at your expected level.
for (int i = 0; i < arrayMonthList.count; i++) {
MyCustomModel *myModelObject = [arrayMonthList objectAtIndex:i];
NSLog(#"Month is %# and its value is %#",myModelObject.myCustomKey,myModelObject.myCustomValue);
}

Access and change values of an NSMutableDictionary from one class to another iOS

I am dealing with NSMutableDictionary in one class, But I want to change it's value in an another class.
Here is the code where it is declared.
#interface MyClass0 : NSObject
{
#public
NSMutableDictionary *valuee;
}
#property (nonatomic, copy) NSMutableDictionary *valuee;
#end
and in the implementation of myClass0 I do
#synthesize valuee;
and I also declare value as
valuee = #{#"name" : #"Aryan"};
Now I want to access and change the value of this dictionary in an another class.
Use #property (nonatomic, strong) NSMutableDictionary *valuee;
Now assign the value as
self.valuee = [[NSMutableDictionary alloc] init];
You can do this in the init method of your MyClass0.
Now you can access the value from another class like
MyClass0 *myClassInstance = [[MyClass0 alloc] init];
NSMutableDictionary *dict = myClassInstance.valuee;
You can write the getter by hand --
- valuee {
return valuee;
}
so the code instance.valuee will give you the original object not the copy.

Core Data iCloud fetch sometimes yields no data (iOS)

I have a problem in my test app using iCloud Core Data. The specific problem is triggered when a partial entry in a table view is touched which triggers the full table entry to be displayed on a full screen. Kind of standard table view stuff.
The table view cell contains an unique record ID which is passed into the detail display view. Upon starting up the view, the view controller get uses the full record data and paints it up on the screen.
Here is the code used to do that:
- (void)viewDidLoad {
[super viewDidLoad];
NSString *temp_text;
Item *fetchSelectedItem;
NSString *updateUniqueID;
NSArray *tempFetchedObjects;
NSError *error;
int stopper;
localFindItDataController = [[FindItDataController alloc] init];
NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"Item" inManagedObjectContext: localFindItDataController.managedObjectContext];
[fetch setEntity:entityDescription];
updateUniqueID = [localItem.itemUniqueID stringValue];
[fetch setPredicate:[NSPredicate predicateWithFormat:#"(ANY itemUniqueID = %#)",updateUniqueID]];
tempFetchedObjects = [localFindItDataController.managedObjectContext executeFetchRequest:fetch error:&error];
NSLog(#"did the fetch work %# %lu", updateUniqueID, (unsigned long)[tempFetchedObjects count]);
if ([tempFetchedObjects count] == 0) {
stopper = 1;}
fetchSelectedItem = [tempFetchedObjects objectAtIndex:0];
NSLog(#"only executes if fetch was ok");
localItem = fetchSelectedItem;
temp_text = localItem.itemName;
contentsWhatBox.text = temp_text;
temp_text = localItem.itemLocation;
contentsWhereBox.text = temp_text;
temp_text = localItem.itemDescription;
contentsOtherInfoBox.text = temp_text;
UIImage *tempImage = [UIImage imageWithData:localItem.itemPicture];
CGImageRef imageRef = [self CGImageRotatedByAngle:[tempImage CGImage] angle:270];
UIImage* img = [UIImage imageWithCGImage: imageRef];
contentsImageBox.image = img;
tapImage = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapImageGesture)];
[contentsImageBox setUserInteractionEnabled:YES];
[contentsImageBox addGestureRecognizer:tapImage];
}
Mostly this works just fine but occasionally the fetch comes up empty even though there definitely is data that matches the fetch predicate. Sometimes I can tap on a table view entry, see it come up, go back and forth a few times between table view entries, go back to the original entry and the fetch fails.
I'm at a bit of a loss and any help would be welcome. Thanks in advance.
Edit #1:
This is the object that is being fetched. Might matter so I added it in later:
#interface Item : NSManagedObject {
}
#property (nonatomic, retain) NSString * itemName;
#property (nonatomic, retain) NSString * itemLocation;
#property (nonatomic, retain) NSString * itemDescription;
#property (nonatomic, retain) NSData * itemPicture;
#property (nonatomic, retain) NSNumber * itemUniqueID;
#property (nonatomic, retain) NSNumber * itemNumber1;
#property (nonatomic, retain) NSNumber * itemNumber2;
#property (nonatomic, retain) NSString * itemAttribute1;
#property (nonatomic, retain) NSString * itemAttribute2;
#property (nonatomic, retain) NSString * itemAttribute3;
#property (nonatomic, retain) NSString * itemTimestamp;
#end
Edit #2:
I forgot to mention that the error object from the fetch is nil after the 'bad' fetch.
Edit #3:
Added a loop to check if I got a result and retry a certain number of times before quitting and that worked ok. I'm not sure why it's going on but I suspect the image in the iCloud data might be part of the problem even though the data at this point for sure is replicated to the iOS test device(s).
Added a loop to check if I got a result and retry a certain number of times before quitting and that worked ok. I'm not sure why it's going on but I suspect the image in the iCloud data might be part of the problem even though the data at this point for sure is replicated to the iOS test device(s).

Why can I not initialize this NSArray With Objects?

I have an array containing objects of a custom-made class. However, on initialization the compiler gives me an error - "Lexical or Preprocessor" Expected ':'
interface myClass : NSObject
#property (readwrite, strong) NSString* name;
#property (readwrite, strong) NSString* home;
#property (readwrite, strong) Preference pref; // This is another custom class
-(id) initWithName:(NSString*) name home:(NSString*) home preference:(Preference) preference;
end
#interface MyViewController()
#property (nonatomic, strong) NSArray *rowArray;
#end
#implementation MyViewController
...
...
...
- (void) initializeArray
{
self.rowArray = #{
[[myClass alloc] initWithName:#"Harry" home:#"New York" preference :Acura],
[[myClass alloc] initWithName:#"Win" home:#"Seattle" preference :Toyota];
};
}
Can someone tell me just where I am messing up and why I'm getting this error?
The Objective-C literal for an array is with square brackets,
NSArray *anArray = #[obj1, obj2].
In the code you posted it is trying to make a Dictionary,
NSDictionary *aDict = #{"key1" : obj1, #"key2" : obj2}
so this is why it is saying it expects a :.
The line should read,
self.rowArray = #[
[[myClass alloc] initWithName:#"Harry" home:"New York" preference :Acura],
[[myClass alloc] initWithName:#"Win" home:"Seattle" preference :Toyota];
];
As others have pointed out the there are a few other errors with the code and those city names are not NSString's, but I guess this is just an example snippet.

Resources