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.
Related
I am a newbie to Objective C. I would like to create a class that has a nested class in it. To my knowledge, there is nothing like nested classes.
I would like it to be like an NSArray of NSMutableDictionary.
So far I have two different custom classes, where one is supposed to be nested in the other.
Group.h
#import "Category.h"
#interface Group : NSObject
- (instancetype)initWithGroupName:(NSString *)groupName
- (Category *)category;
#end
Group.m
#interface Group ()
#property(nonatomic, strong) NSString *groupName;
#end
#implementation Group
- (instancetype)initWithGroupName:(NSString *)groupName {
self = [super init];
if (self) {
self.groupName = groupName;
self.payID = paymentID;
self.sort = sortOrder;
}
return self;
}
- (NSString *)name {
return self.groupName;
}
- (Category *)category {
Category *test = [[Category alloc] init];
return test;
}
Category.h
#interface Category : NSObject
- (instancetype)initWithCategoryName:(NSString *)name
withDescription:(NSString *)description
ofPercent:(int)percent;
- (NSString *)name;
- (NSString *)description;
- (NSString *)percent;
#end
Category.m
#interface Category ()
#property(nonatomic, strong) NSString *title;
#property(nonatomic, strong) NSString *descrip;
#property(assign) int perc;
#end
#implementation Category
- (instancetype)initWithCategoryName:(NSString *)name
withDescription:(NSString *)description
ofPercent:(int)percent {
self = [super init];
if (self) {
self.title = name;
self.descrip = description;
self.perc = percent;
}
return self;
}
- (NSString *)name {
return self.title;
}
- (NSString *)description {
return self.descrip;
}
- (NSString *)percent {
return [[NSString stringWithFormat:#"%d", self.perc * 100] stringByAppendingString:#"%"];
}
#end
I am not sure how to make it work. What exactly I want to do is to have one Group with many categories in it or one group that has 4 subgroups with many categories in each subgroups.
Thanks in advance for any help!
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.
I'm trying to write a calculator program, but I'm running into this error when pressing a particular key that is linked to the function expressionEvaluation. My calculator works fine, but I am trying to add in the ability to use/store variables. For this, I use the expressionEvaluation button. However, as soon as I press the button linked to that method, the whole app crashes, and xcode gives me the error EXC_BAD_ACCESS code=2. I'm new to objective-c, so I'm not sure how to debug this error. As far as I can tell, though, the issue is with the line
double result = [CalculatorBrain evaluateExpression:self.brain.expression usingVariableValues:testValues];
...in my view controller. I set a break point before this line and it didn't crash, but setting it at this line resulted in the crash I'm experiencing.
I tried to cut the code down below, and have included only the things directly linked to the expressionEvaluation button. Thank you for your help!
Here's the .h for my brain method:
// CalculatorBrain.h
#import <Foundation/Foundation.h>
#interface CalculatorBrain : NSObject
- (void) pushOperand:(double)operand;
- (void) setVariableAsOperand:(NSString *)variableName;
- (void) performWaitingOperation;
- (double) performOperation:(NSString *)operation;
#property (readonly) id expression;
+ (double)evaluateExpression: (id)anExpression
usingVariableValues: (NSDictionary *)variables;
+ (NSSet *)variablesInExpression:(id)anExpression;
+ (NSString *)descriptionOfExpression:(id)anExpression;
+ (id)propertyListForExpression:(id)anExpression;
+ (id)expressionForPropertyList:(id)propertyList;
#end
Here's the .m:
// CalculatorBrain.m
#import "CalculatorBrain.h"
#define VARIABLE_PREFIX #"^"
#interface CalculatorBrain()
#property (nonatomic) double operand;
#property (nonatomic, strong) NSString *waitingOperation;
#property (nonatomic) double waitingOperand;
#property (nonatomic) double storedOperand;
#property (nonatomic) NSMutableArray *internalExpression;
#end
#implementation CalculatorBrain
#synthesize operand = _operand; //operand in use
#synthesize waitingOperation = _waitingOperation; //waiting to be computed
#synthesize waitingOperand = _waitingOperand; //waiting to be used
#synthesize storedOperand = _storedOperand; //stored in memory
#synthesize internalExpression = _internalExpression; //private expression stored
#synthesize expression = _expression;
- (id) expression {;
return [NSMutableArray arrayWithArray:self.internalExpression];
}
//here I have instance methods that add objects to the array internalExpression
//these work fine as far as I can tell
+ (double) evaluateExpression:(id)anExpression usingVariableValues:(NSDictionary *)variables {
double result = 0;
int count = [anExpression count];
CalculatorBrain *brain;
for (int i = 0; i < count; i++) {
if([[anExpression objectAtIndex:i] isKindOfClass:[NSNumber class]]) {
double operand = [[anExpression objectAtIndex:i] doubleValue];
[brain pushOperand:operand];
}
if([[anExpression objectAtIndex:i] isKindOfClass:[NSString class]]) {
NSString *string = [anExpression objectAtIndex:i];
if([string characterAtIndex:0] == '^') {
NSString* variable = [NSString stringWithFormat:#"%c",[string characterAtIndex:1]];
double valueOfVariable = [[variables objectForKey:variable] doubleValue];
[brain pushOperand:valueOfVariable];
}
else {
NSString* operator = [anExpression objectAtIndex:i];
result = [brain performOperation:operator];
}
}
}
return result;
}
#end
Here's the .h for my view controller:
// CalcViewController.h
#import <UIKit/UIKit.h>
//view controller for calculator
#interface CalcViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *display; //real-time display
#property (strong, nonatomic) IBOutlet UILabel *miniDisplay; //past display
#property (strong, nonatomic) IBOutlet UILabel *memDisplay; //display stored digits
- (IBAction)digitPressed:(UIButton *)sender; //pressed number
- (IBAction)operandPressed:(UIButton *)sender; //pressed operation
- (IBAction)variablePressed:(UIButton *)sender; //pressed variable
- (IBAction)expressionEvaluation:(UIButton *)sender; //evaluate expression with variables
#end
Here's the .m:
// CalcViewController.m
#import "CalcViewController.h"
#import "CalculatorBrain.h"
#interface CalcViewController ()
#property (nonatomic, strong) CalculatorBrain *brain;
#property (nonatomic) BOOL userIsInTheMiddleOfTypingANumber;
#end
#implementation CalcViewController
- (CalculatorBrain *) brain {
if (!_brain) _brain = [[CalculatorBrain alloc] init];
return _brain;
}
- (IBAction)expressionEvaluation:(UIButton *)sender {
NSDictionary* testValues = [NSDictionary dictionaryWithObjectsAndKeys:#"x", 2, #"y", 3, #"z", 4, nil];
double result = [CalculatorBrain evaluateExpression:self.brain.expression usingVariableValues:testValues];
NSString *resultString = [NSString stringWithFormat:#"%g", result];
self.display.text = resultString;
}
#end
EDIT: Just as a side note, I am not getting any errors, only one warning: incomplete implementation. This is because I haven't finished a couple class methods yet, but I don't think it is causing the crash.
NSDictionary* testValues = [NSDictionary dictionaryWithObjectsAndKeys:#"x", 2, #"y", 3, #"z", 4, nil];
turned out to be the erroneous line. It should have been:
NSDictionary* testValues = [NSDictionary dictionaryWithObjectsAndKeys:#"x", [NSNumber numberWithInt:2], #"y", [NSNumber numberWithInt:3], #"z", [NSNumber numberWithInt:4], nil];
Thanks to everyone who helped!
You will get more information on the code line raising the exception by adding an exception breakpoint in xCode.
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
I have a singleton object in iOS that when instantiated parses a CSV file and then holds the results. I would like to make this object universally accessible and I would like it to not be released from memory until the app quits. I am running ARC so I cannot do manual retains.
Is there a way I can do this so it will work with ARC?
Header File:
#import <Foundation/Foundation.h>
#import "CHCSV.h"
#import "RCParserObject.h"
#interface ParserStore : NSObject <CHCSVParserDelegate>
{
// CSV Variables
RCParserObject *item;
NSMutableArray *data;
NSMutableArray *parsedData;
int fields;
bool open;
}
#property (atomic, retain) RCParserObject *item;
#property (atomic, retain) NSMutableArray *data;
#property (atomic, retain) NSMutableArray *parsedData;
#property (atomic) int fields;
#property (atomic) bool open;
+ (ParserStore *) defaultStore;
- (void) parseCSVFile:(NSString*)file;
- (void) categorizeData;
Implementation File
#import "ParserStore.h"
#import "RCParserObject.h"
#import "RCDetailItem.h"
static ParserStore *defaultStore;
#implementation ParserStore
#synthesize item, data, parsedData, fields, open;
# pragma mark -
# pragma mark Singleton Methods
+ (ParserStore *) defaultStore
{
if (!defaultStore)
{
defaultStore = [[super allocWithZone:NULL] init];
}
return defaultStore;
}
+ (id) allocWithZone:(NSZone *)zone
{
return [self defaultStore];
}
- (id) init
{
NSLog(#"Running init on parser store");
if (defaultStore)
{
NSLog(#"Self data count is %d, right before return", self.parsedData.count);
return defaultStore;
}
// NSLog(#"This better only happen once");
self = [super init];
[self setParsedData:[[NSMutableArray alloc] init]];
[self parseCSVFile:#"ContentNoPathFileExt2ASCII"];
[self categorizeData];
// NSLog(#"Self data count is %d when first created", self.parsedData.count);
return self;
}
#property (atomic, retain) RCParserObject *item;
#property (atomic, retain) NSMutableArray *data;
#property (atomic, retain) NSMutableArray *parsedData;
#property (atomic) int fields;
#property (atomic) bool open;
+ (ParserStore *) defaultStore;
- (void) parseCSVFile:(NSString*)file;
- (void) categorizeData;
#end
+(MySingleton *)singleton {
static dispatch_once_t pred;
static MySingleton *shared = nil;
dispatch_once(&pred, ^{
shared = [[MySingleton alloc] init];
shared.someVar = someValue; // if you want to initialize an ivar
});
return shared;
}
From anywhere:
NSLog(#"%#",[MySingleton singleton].someVar);
Note that your iOS app already has a singleton that you can access anywhere:
AppDelegate *delegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
a simple singleton would be something like... in the .h:
#interface Foo : NSObject
+ (Foo *)sharedInstance;
#end
and in the .m:
static Foo *_foo = nil;
#implementation Foo
+ (Foo *)sharedInstance {
if (!_foo)
_foo = [[Foo alloc] init];
return _foo;
}
#end