RLMObject unable to use as a normal object - ios

I have a Product model with the header:
#interface Product : RLMObject <NSCopying,NSCoding>
{
}
#property (nonatomic, strong) NSString *title;
#property (nonatomic, strong) NSString *thumbnailURL;
#property (nonatomic, strong) UIImage *thumbnail;
-(id)initWithInfo:(NSDictionary*)dictionary;
-(UIImage*)getThumbnail;
and implementation:
#implementation Product
-(id)initWithInfo:(NSDictionary*)dictionary
{
self = [self init];
if (self) {
_title = dictionary[#"title"];
_thumbnailURL = dictionary[#"thumbnailURL"];
_thumbnail = [self getThumbnail];
}
return self;
}
-(UIImage*)getThumbnail
{
if (_thumbnail) {
return _thumbnail;
}
//load image from cache
return [self loadImageFromCache];
}
Now, when I try to create a Product object and insert it into Realm, I always get the exception
[RLMStandalone_Product getThumbnail]: unrecognized selector sent to instance 0xcd848f0'
Now, I remove _thumbnail = [self getThumbnail]; and it works fine. But then I get another exception
[RLMStandalone_Product title]: unrecognized selector sent to instance 0xd06d5f0'
when I reload my view. I have created my Product object in the main thread, so it should be fine to using its property and method, isn't it?
Any advice will be appreciated!

Because Realm object properties are backed by the database rather than in-memory ivars, accessing those properties' ivars is not supported. We're currently clarifying our docs to convey this:
Please note that you can only use an object on the thread from which is was created or obtained, ivars shouldn't be accessed directly for any persisted properties, and that getters and setters for persisted properties cannot be overridden.
So to work with Realm, your model should look like this:
#interface Product : RLMObject
#property NSString *title;
#property NSString *thumbnailURL;
#property (nonatomic, strong) UIImage *thumbnail;
#end
#implementation Product
-(UIImage*)thumbnail
{
if (!_thumbnail) {
_thumbnail = [self loadImageFromCache];
}
return _thumbnail;
}
-(UIImage*)loadImageFromCache
{
// Load image from cache
return nil;
}
+(NSArray*)ignoredProperties
{
// Must ignore thumbnail because Realm can't persist UIImage properties
return #[#"thumbnail"];
}
#end
And usage of this model could look like this:
[[RLMRealm defaultRealm] transactionWithBlock:^{
// createInDefaultRealmWithObject: will populate object keypaths from NSDictionary keys and values
// i.e. title and thumbnailURL
[Product createInDefaultRealmWithObject:#{#"title": #"a", #"thumbnailURL": #"http://example.com/image.jpg"}];
}];
NSLog(#"first product's image: %#", [(Product *)[[Product allObjects] firstObject] thumbnail]);
Notice how initWithInfo isn't necessary because RLMObject already has initWithObject: and createInDefaultRealmWithObject: already do this.

Related

Can't write NSDictionary parameters into custom Object

I was stuck on writing NSDictionary into Object process, I am sure that problem is simple as I imagine but would be great to get assistant. Here is my code:
my custom object:
#interface User : NSObject
#property (nonatomic, retain) NSString *cId;
#property (nonatomic, retain) NSString *firstName;
#property (nonatomic, retain) NSString *lastName;
....
-(instancetype) initWithParameters:(NSDictionary*) parameters;
#end
#import "User.h"
#implementation User
-(instancetype) initWithParameters:(NSDictionary*) parameters
{
self = [super init];
if (self) {
[self setParameters:parameters];
}
return self;
}
- (void) setParameters:(NSDictionary*) parameters{
_cId = parameters[#"cId"];
_firstName = parameters[#"first_name"];
_lastName = parameters[#"last_name"];
....
}
and writing process:
id userObjects = [resultData objectForKey:#"data"];
NSMutableArray* mUsers = [[NSMutableArray alloc] init];
for (NSDictionary* userParameters in userObjects) {
User *user = [[User alloc] initWithParameters:userParameters];
[mUsers addObject:user];
}
userObjects - NSArray got from JSON object from server data.
The problem is : nothing happening and user object still empty after initialization, then I have tried - setValuesForKeysWithDictionary after I called variables same as keys in dictionary and nothing changed.
after adding in mUsers:
Could anybody tell me what I am doing wrong? Thank you!
I believe you think those objects are uninitialized because you are seeing 0 key/value pairs next to each User object.
Your code looks good and I think things will change once you implement [NSObject description] (or [NSObject debugDescription]) like this:
- (NSString *)description
{
return [NSString stringWithFormat:#"cId=%#, firstName=%#, lastName=%#",
_cId, _firstName, _lastName];
}

Changing an NSObject inside of a NSMutableArray from a Singleton

I have a singleton which looks like this:
#implementation BARTicketManager
+ (BARTicketManager *)sharedManager {
static dispatch_once_t pred;
static BARTicketManager *shared = nil;
dispatch_once(&pred, ^{
shared = [[BARTicketManager alloc] initUniqueInstance];
});
return shared;
}
- (id) initUniqueInstance {
if (self = [super init]) {
/* holds the list of TicketPurchase objects */
_ticket_list = [[NSMutableArray alloc] init];
}
return self;
}
The _ticket_list above is declared as:
#property (nonatomic, retain) NSMutableArray *ticket_list;
This list holds objects of type TicketPurchase. A method inside of TicketPurchase is 'setTicketAsReserved' as follows:
- (void) setTicketAsReserved:(NSDate *)reserved_datetime {
_status = RESERVED;
_reserved_datetime = reserved_datetime;
}
The problem I am having, is that when I run through the objects in the _ticket_list and call 'setTicketAsReserved' on some of those objects, and then attempt to access them by calling the singleton again, the value for _reserved_datetime is not saved, whereas the value of _status IS saved.
Can anyone understand why this would be the case?
Edit:
Relevant declarations for TicketPurchase:
#property (weak, nonatomic) NSDate *reserved_datetime;
#property (nonatomic) TicketStatus status;
Since your reserved_datetime property is declared weak, it's likely getting deallocated. Try changing that declaration to strong, since you want the TicketPurchase class to keep the reserved_datetime property around.

Core Data One to Many Relationship: unrecognized selector sent to instance

I am having two classes or objects: User and Medicine. Here is my User class:
#interface User : NSManagedObject
#property (nonatomic, retain) NSString * name;
#property (nonatomic, retain) NSSet *medicine;
#end
#interface User (CoreDataGeneratedAccessors)
- (void)addMedicineObject:(Medicine *)value;
- (void)removeMedicineObject:(Medicine *)value;
- (void)addMedicine:(NSSet *)values;
- (void)removeMedicine:(NSSet *)values;
#end
and then the Medicine class
#interface Medicine : NSManagedObject
#property (nonatomic, retain) NSString * medName;
#property (nonatomic, retain) NSString * medType;
#property (nonatomic, retain) Dose *dose;
#property (nonatomic, retain) User *user;
#end
As my interfaces clearly show that user may have multiple medicines. (I am from database background thats why I am interpreting it like this).
When I add new object in User, it is easily done, but when I try to add new Medicine for existing object of user, I feel that my Xcode has a deep wish to shoot me at that time (vice versa).
Now here is the code that describes what I am doing:
Medicine *object = [[self fetchedResultsController] objectAtIndexPath:indexPath];
User *user = [NSEntityDescription insertNewObjectForEntityForName:#"User" inManagedObjectContext:self.managedObjectContext];
if(![self checkUser])
{
object.user = user;
[user setName:self.userName];
NSLog(#"%# %#",object, user);
self.detailViewController.detailItem = object;
}
else
{
Medicine *medicine = [NSEntityDescription insertNewObjectForEntityForName:#"Medicine" inManagedObjectContext:self.managedObjectContext];
user = [self getUser:self.userName];
medicine.medName = object.medName;
medicine.medType = object.medType;
[medicine setUser:user];
self.detailViewController.detailItem = medicine;
}
I am having a simple logic: if name entered by user in text field, already exist in DB, then return the User object. Then just add another Medicine record for the same User. Other wise add new User and a Medicine object as well.
but I get error at:
[medicine setUser:user];
I also tried this one: (as I got it in another question like mine)
[user addMedicineObject:medicine];
Now I think that I have to override addMedicineObject method or something else.
Oh I forgot the error. I get this error: (the real villain)
[__NSArrayM managedObjectContext]: unrecognized selector sent to instance 0x8136bf0
Now any suggestion?
It is because you trying to mutate NSSet object. You need to create a mutable copy before you edit it.

Custom Object empty after creation

I have a custom object: Vendor that extends NSObject. I am initiating it like so:
NSDictionary *vendorObj = [vendors objectAtIndex:i];
Vendor *vendor = [[Vendor alloc] initWithVendorInfo:vendorObj];
NSLog(#"VendorObj: %#", vendorObj);
NSLog(#"Vendor: %#", vendor);
Here is what the class looks like:
#interface Vendor : NSObject
#property (nonatomic, copy) NSString *name;
#property (nonatomic, copy) NSString *description;
- (id)initWithVendorInfo:(NSDictionary *)vendorDetails;
#end
#implementation Vendor
- (id)initWithVendorInfo:(NSDictionary *)vendorDetails
{
self = [super init];
if(self)
{
_name = [vendorDetails[#"company_name"] copy];
_description = [vendorDetails[#"description"] copy];
}
return self;
}
If I NSLog vendorObj all the details are there. Once I initiate the Vendor object and NSLog it, the log shows:
2013-11-21 22:22:44.769 [48202:a07] Vendor:
I cannot seem to figure out why my object is nothing, no memory address, not even a null. What am I doing wrong here?
The problem is your description property. The NSObject class defines a description method. This method is called when you use a %# format specifier with an object.
Your description property is overriding that method.
Rename your description property to something else.

Pass Array to NSObject Class

I'm new to iphone app development and I'm stuck on this problem I'm having with the app I'm trying to develop.
I have a datacontroller for populating a tableview. I created it using this tutorial:
About Creating Your Second iOS App
I'm trying to pass an array from one of my viewcontrollers that was created from a JSON response.
Here is some code from my viewcontroller.h that needs to pass the array:
#interface ViewController : UIViewController
#property (nonatomic, retain) DataController *Data;
#property (nonatomic, retain) NSMutableArray *array;
#end
viewcontroller.m:
#import "DataController.h"
[Data setMasterList: self.array];
DataController.h:
#interface DataController : NSObject
#property (nonatomic, strong) NSMutableArray *masterList;
- (void)setMasterList:(NSMutableArray *)newList;
#end
DataController.m
#import "LoginViewController.h"
- (void)setMasterList:(NSMutableArray *)newList {
if (_masterList != newList) {
_masterList = [newList mutableCopy];
NSLog("List: %#", newList);
}
}
The NSLog message never shows up in the console and the array is nil.
Any help is appreciated.
Thanks.
EDIT:
Here's the updated viewcontroller.m:
Data = [[DataController alloc] init];
[Data setMasterList: self.array];
The datacontroller.m:
- (void)setMasterList:(NSMutableArray *)newList {
if (_masterList != newList) {
_masterList = [newList mutableCopy];
NSLog("List: %#", self.masterList);
}
}
- (NSUInteger)countOfList {
NSLog("List: %#", self.masterList);
return [self.masterList count];
}
The first nslog inside setMasterList returns the correct array values, but the second nslog inside countOfList returns null. The list always returns null anywhere outside of setMasterList. Is it because I'm creating a new instance of the DataController? If so, how else could I pass the array to the datacontroller.
As in first comment Till have suggested, Data must be initialized before calling setMasterList. Such As:
Data = [[DataController alloc] init];
[Data setMasterList: self.array];

Resources