PFObject Subclass as a Property in another PFObject Subclass - ios

[X-Post from parse.com]
Person is a subclass of PFObject.
Address is also a subclass of PFObject. Address has a #property of type Person.
i.e.
// Person.h
#interface Person : PFObject<PFSubclassing>
#property (retain) NSString *firstName;
#property (retain) NSString *secondName;
+ (NSString *)parseClassName;
#end
// Person.m
#import <Parse/PFObject+Subclass.h>
#implementation PP4MEAddress
#dynamic firstName;
#dynamic firstName;
+ (NSString *)parseClassName {
return #"Person";
}
// Address.h
#interface Address : PFObject<PFSubclassing>
#property (retain) Person *deliverToPerson;
#property (retain) NSString *line1;
#property (retain) NSString *line2;
+ (NSString *)parseClassName;
// Address.m
#import <Parse/PFObject+Subclass.h>
#implementation PP4MEAddress
#dynamic deliverToPerson;
#dynamic line1;
#dynamic line2;
+ (NSString *)parseClassName {
return #"Address";
}
Both subclasses are registered in the App Delegate.
In a method in MyViewController I want to set these as so
e.g.
-(void)myMethod
{
Address *address = [Address object];
address.deliverToPerson.firstName = #"John";
address.deliverToPerson.secondName = #"Smith";
address.line1 = #"123";
address.line2 = #"Main Street";
[address saveInBackground];
}
When this code executes, an entry of Class Address is input into the Data Browser on the Parse.com Web App. However, the only columns are objectId, createdAt, updatedAt and ACL
I imagine this is because, under the hood the Address #property of type Person is not being allocated and initialised.
How do I overcome this?
Do I write a custom setter and getter for
#property (retain) Person *deliverToPerson;
in Address.m ?
If so, I notice that the #property is atomic and thus will I need to write locking code in said setter and getter?
Thank You

I am not familiar with parse.com, but I strongly assume that you have to
allocate the Person object before setting the relationship. Something like
Address *address = [Address object];
address.line1 = #"123";
address.line2 = #"Main Street";
Person *person = [Person object];
person.firstName = #"John";
person.secondName = #"Smith";
address.deliverToPerson = person;
[address saveInBackground];

you have to set your PFobject
like this
PFObject *anotherPlayer = [PFObject objectWithClassName:#"Player"];
[anotherPlayer setObject:#"DataValue" forKey:#"Name"];

Related

RLMResults:allObjects crash (iOS Objective-C)

I have old project written on Objective-C. Need to do migration to Realm.
I created several objects/classes inheritance from RLMObject. When I do fetching objects only with one main object type (ConnectionRealm) - working fine, but if I do add (only add, not include, not use) to project two or more another classes (inheritance from RLMObject), like as FloorRealm class, APP crash on [ConnectionRealm allObjects] without any errors.
Also ConnectionRealm contains RLMArray of FloorRealm. App still crashing.
(Can`t solve and understand this few days.) Thanks.
Connection Model:
#import <Foundation/Foundation.h>
#import <Realm/Realm.h>
#import "FloorRealm.h"
#interface ConnectionRealm : RLMObject
#property int connectionID;
#property NSString *name;
#property NSString *localIPAddress;
#property NSString *localPort;
#property NSString *remoteIPAddress;
#property NSString *remotePort;
#property NSString *userName;
#property NSString *password;
#property NSString *deviceID;
#property RLMArray <FloorRealm *> *floors;
- (instancetype)initWith:(NSString *)name
localIP:(NSString *)localIPAddress
localPort:(NSString *)lPort
remoteIP:(NSString *)remoteIPAddress
remotePort:(NSString *)rPort
userName:(NSString *)userName
password:(NSString *)password
deviceID:(NSString *)deviceID;
#end
#import "ConnectionRealm.h"
#implementation ConnectionRealm
- (instancetype)initWith:(NSString *)name
localIP:(NSString *)localIPAddress
localPort:(NSString *)lPort
remoteIP:(NSString *)remoteIPAddress
remotePort:(NSString *)rPort
userName:(NSString *)userName
password:(NSString *)password
deviceID:(NSString *)deviceID {
if (self = [super init]) {
self.connectionID = [self incrementID];
self.name = name;
self.localIPAddress = localIPAddress;
self.localPort = lPort;
self.remoteIPAddress = remoteIPAddress;
self.remotePort = rPort;
self.userName = userName;
self.password = password;
self.deviceID = deviceID;
}
return self;
}
+ (NSString *)primaryKey { return #"connectionID"; }
- (int)incrementID {
RLMResults *objects = [ConnectionRealm allObjects];
return self.connectionID = [[objects maxOfProperty:#"connectionID"] intValue] + 1;
}
#end
FloorModel:
#import <Realm/Realm.h>
#interface FloorRealm : RLMObject
#property int floorID;
#property NSInteger floorNumber;
#property NSString *floorName;
- (instancetype)initWith:(NSInteger)floorNumber floorName:(NSString *)name;
#end
RLM_ARRAY_TYPE(FloorRealm)
#import "FloorRealm.h"
#implementation FloorRealm
- (instancetype)initWith:(NSInteger)floorNumber floorName:(NSString *)name {
if (self = [super init]) {
self.floorID = [self incrementID];
self.floorNumber = floorNumber;
self.floorName = name;
}
return self;
}
+ (NSString *)primaryKey { return #"floorID"; }
- (int)incrementID {
RLMResults *objects = [FloorRealm allObjects];
return self.floorID = [[objects maxOfProperty:#"floorID"] intValue] + 1;
}
#end
[SOLVED]
RLM_ARRAY_TYPE(FloorRealm) need put on ConnectionRealm in .h after #includes. But in official docs written another.
Also: #property RLMArray <FloorRealm *><FloorRealm> *floors; instead of #property RLMArray <FloorRealm *> *floors;
I created test project with the same models and seed all errors. Strange, but in original project Xcode not showing this errors.

Schema validation failed: Property declared as origin of linking objects property is not a link

I have two RLMObjects named RCRealmUser and RCRealmLocation. RCRealmUser has a one-to-one relationship defined on RCRealmLocation and RCRealmLocation has an inverse relation with the RCRealmUser. This is how I have defined these two:
RCRealmUser.h
#interface RCRealmUser : RLMObject
#property NSNumber <RLMInt> *userId;
#property NSString *username;
#property NSNumber <RLMInt> *countryCode;
#property NSNumber <RLMDouble> *phoneNumber;
#property NSString *fullName;
#property NSString *profileImageURL;
#property RCRealmLocation *location;
- (id)initWithMantleModel:(RCUserProfile *)user;
#end
RLM_ARRAY_TYPE(RCRealmUser)
RCRealmUser.m
#implementation RCRealmUser
+ (NSString *)primaryKey {
return #"userId";
}
+ (NSArray *)indexedProperties {
return #[#"fullName"];
}
+ (NSDictionary *)defaultPropertyValues {
return #{#"countryCode": #91};
}
- (id)initWithMantleModel:(RCUserProfile *)user {
self = [super init];
if(!self) return nil;
self.userId = user.userId;
self.username = user.username;
self.countryCode = user.countryCode;
self.phoneNumber = user.phoneNumber;
self.fullName = user.fullName;
self.profileImageURL = user.profileImageURL.absoluteString;
self.location = [[RCRealmLocation alloc] initWithMantleModel:user.location];
return self;
}
#end
RCRealmLocation.h
#interface RCRealmLocation : RLMObject
#property (readonly) RLMLinkingObjects *userId;
#property NSNumber <RLMDouble> *latitute;
#property NSNumber <RLMDouble> *longitude;
#property NSDate *timestamp;
#property NSNumber <RLMInt> *accuracy;
- (id)initWithMantleModel:(RCLocation *)location;
#end
RLM_ARRAY_TYPE(RCRealmLocation)
RCRealmLocation.m
#implementation RCRealmLocation
+ (NSArray<NSString *> *)indexedProperties {
return #[#"timestamp"];
}
+ (NSDictionary<NSString *,RLMPropertyDescriptor *> *)linkingObjectsProperties {
return #{#"userId": [RLMPropertyDescriptor descriptorWithClass:RCRealmUser.class propertyName:#"userId"]};
}
- (id)initWithMantleModel:(RCLocation *)location {
self = [super init];
if(!self) return nil;
self.latitute = location.latitute;
self.longitude = location.longitude;
self.timestamp = location.timestamp;
self.accuracy = location.accuracy;
return self;
}
Now when I try to insert into RCRealmUser I encounter an error
'RLMException', reason: 'Schema validation failed due to the following
errors:
Property 'userId' declared as origin of linking objects property 'userId' is not a link.'
Am I doing something wrong somewhere?
"Linking objects" properties must represent links (relationships).
In your case, you're saying that the RCRealmLocation.userId property should represent RCRealmUser objects that link to that location via its userId property. However, RCRealmUser.userId isn't a relationship to RCRealmLocation objects, it's an optional integer.
I believe what you want is a property on RCRealmLocation that refers to all RCRealmUsers linking to that location with its locations relationship. You can accomplishing this by changing your RCRealmLocation.userId property to this:
#property (readonly) RLMLinkingObjects *users;
and your linkingObjectsProperties implementation to this:
return #{#"users": [RLMPropertyDescriptor descriptorWithClass:RCRealmUser.class propertyName:#"location"]};
Read Realm's docs on inverse relationships for more information.

PFUser Property on subclassed PFObject

I've subclassed the PFObject with the following Class (dynamic properties, and +load & parseClassName Methods in .m file)
#interface DAOpponents : PFObject <PFSubclassing>
#property (nonatomic, strong) PFObject* fromUser;
#property (nonatomic, strong) PFObject* toUser;
#property (nonatomic) BOOL isVisible;
#property (nonatomic) BOOL isPersistent;
+ (NSString *)parseClassName;
#end
In a Unit Test I try to create a Sample DAOpponents-Object:
DAOpponents* follow = [DAOpponents object];
follow.fromUser = user1; // caught "NSInvalidArgumentException", "PFObject values may not have class: PFUser"
follow.toUser = user2;
[follow save];
If I do the same without a subclassed Version of the opponents there's no Exception
PFObject* follow = [[PFObject alloc] initWithClassName:#"DAOpponents"];
[follow setObject:user1 forKey:#"fromUser"]; // no exception!!!
[follow setObject:user1 forKey:#"toUser"];
Why does a subclassed PFObject can not point to a PFUser object?
Any help appreciated! Thanks a lot!
I was able to get around this problem by first subclassing PFUser, then using my subclass called User in my other PFObject subclasses.
My PFUser subclass, User.h:
#import <Parse/Parse.h>
#class Person;
#class Parish;
#interface User : PFUser<PFSubclassing>
//+ (NSString *)parseClassName;
// Return the current user
+ (User *)currentUser;
#property (retain) NSNumber *acceptedAgreements;
#property (retain) NSNumber *isAdmin;
#property (retain) Person *person;
#end
and my User.m:
#import "User.h"
#import <Parse/PFObject+Subclass.h>
#import "Person.h"
#implementation User
#dynamic acceptedAgreements;
#dynamic isAdmin;
#dynamic person;
//+ (NSString *)parseClassName {
// return #"User";
//}
// Return the current user
+ (User *)currentUser {
return (User *)[PFUser currentUser];
}
#end

Can't store object in array

This is Apprecord class
#interface AppRecord : NSObject
#property (nonatomic, strong) NSString *appIcon;
#property (nonatomic, strong) NSString * name;
#property (nonatomic, strong) NSString * description;
#property (nonatomic, strong) NSString * location;
#property (nonatomic, strong) NSString * address;
#property (nonatomic, strong) NSString * contacts;
#property (nonatomic, strong) NSString * additional_info;
#property (nonatomic, strong) NSString * image;
#end
and I am parsing json adding to an object of App record class
#import "ParserClass.h"
#import "AppRecord.h"
#interface ParserClass ()
#property (nonatomic, strong) NSArray *appRecordList;
#property (nonatomic, strong) NSData *dataToParse;
#property (nonatomic, strong) NSMutableArray *workingArray;
#property (nonatomic, strong) AppRecord *workingEntry;
#property (nonatomic, strong) NSMutableString *workingPropertyString;
#property (nonatomic, strong) NSArray *elementsToParse;
#property (nonatomic, readwrite) BOOL storingCharacterData;
#end
#implementation ParserClass
- (id)initWithData:(NSData *)data
{
self = [super init];
if (self != nil)
{
_dataToParse = data;
}
return self;
}
- (void)main
{
self.workingArray = [NSMutableArray array];
self.workingPropertyString = [NSMutableString string];
self.workingArray=[[NSMutableArray alloc]init];
NSDictionary *allData=[NSJSONSerialization JSONObjectWithData:_dataToParse options:0 error:nil];
NSLog(#"%#",allData);
for (NSDictionary *dict in allData)
{
NSLog(#"dict====%#",dict);
self.workingEntry=[[AppRecord alloc]init];
self.workingEntry.name=[dict objectForKey:#"name"];
self.workingEntry.description=[dict objectForKey:#"description"];
self.workingEntry.location=[dict objectForKey:#"location"];
self.workingEntry.address=[dict objectForKey:#"address"];
self.workingEntry.contacts=[dict objectForKey:#"contacts"];
self.workingEntry.additional_info=[dict objectForKey:#"additional_info"];
self.workingEntry.image=[dict objectForKey:#"image"];
[self.workingArray addObject:self.workingEntry];
}
NSLog(#"WORKING ARRAY========%#",self.workingArray);// Not getting proper value of working array
self.workingArray = nil;
self.workingPropertyString = nil;
self.dataToParse = nil;
}
#end
My problem is not getting proper value of working array,it only stores description property,but it should store apprecord object,please help.
OUTPUT
alldata=
(
{
"additional_info" = "lOREN iPSUM";
address = "1972 Hillview St. Sarasota,FL 34239";
contacts = 8745674556;
description = "Very cute place, awesome wait staff, great food. I am here on vacation and it was an awesome place to go to after a day relaxing at the beach.";
id = 1;
image = "http://..";
location = "1972 Hillview St. Sarasota,FL 34239";
name = "Beer Tasting at Hurricane Hanks";
},
{
"additional_info" = gdfgdfg;
address = "Farrer Place, Sydney, New South Wales, Australia";
contacts = 3423423423423;
description = restataurant;
id = 16;
image = "http://..";
location = kolkata;
name = "mosco ";
}
)
WORKING ARRAY========(
"Very cute place, awesome wait staff, great food. I am here on vacation and it was an awesome place to go to after a day relaxing at the beach.",
restataurant
)
First object name== Beer Tasting at Hurricane Hanks
First you remove 2 time intialization of self.workingArray
And please replace
#property (nonatomic, strong) NSString * description;
deccription with some other name
To know the reason click this link
for (NSDictionary *dict in allData)
{
AppRecord *createAppRecord=[[AppRecord alloc]init];
//Do some thing
[self.workingArray addObject:createAppRecord];
}
I think it will be helpful to you.

iOS: Object returning *nil description* after alloc and init

Let me preface this question by saying that I believe it to be a memory management mistake on my end. I just can't seem to figure out why it is happening.
I have a viewcontroller and a model class named Part.
#import <Foundation/Foundation.h>
#interface Part : NSObject
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) NSString *partType;
#property (nonatomic, strong) NSString *description;
#property (nonatomic, strong) NSNumber *price;
- (id)initWithName:(NSString *)name AndType:(NSString *)type;
#end
In the view controller I have a property set as follows:
#property (nonatomic, strong) Part *part;
In the init function of ViewController I create some static arrays and create objects out of them:
- (id)init {
self = [super init];
self.partList = [[NSMutableArray alloc] init];
NSArray *inputArray = #[#"Part1",
#"Part2",
#"Part3",
#"Part4",
#"Part5",
#"Part6",
#"Part7",
#"Part8"];
NSString *tempType = #"PartCategory";
// Add dummy static data
for (int i = 0; i < [inputArray count]; i++) {
Part *partInput = [[Part alloc] initWithName:[inputArray objectAtIndex:i] AndType:tempType];
//partInput.name = [inputArray objectAtIndex:i];
//partInput.partType = tempType;
NSLog(#"Inserting Part %#", partInput);
[self.partList addObject:partInput];
}
return self;
}
The NSLog I call in that loop returns Inserting Part *nil description* for every part. I just can't track down what is happening here.
EDIT: Here is the initWithName method from Part that the controller uses:
- (id)initWithName:(NSString *)name AndType:(NSString *)type {
if(self = [super init]) {
self.name = name;
self.partType = type;
}
return self;
}
When using %# to print NSObject, it calls debugDescription that by default calling the description method of that object and your Part object always have nil description.
You better solve this by changing the description property name to something else, because it conflicts with the description method of NSObject.
See also: NSObject description and debugDescription

Resources