realm / realm-swift

Realm is a mobile database: a replacement for Core Data & SQLite
https://realm.io
Apache License 2.0
16.32k stars 2.15k forks source link

Store an array in Realm Objective c #3722

Closed vamshikrishna-iitbhu closed 8 years ago

vamshikrishna-iitbhu commented 8 years ago

This is how my JSON response looks like:

{"error":false,"text":{"hotlines":[{"id":"1","department_name":"New Car Sales","flag":"1","numbers":[{"number":"09480825000","name":"Showroom 1"},{"number":"342342423423","name":"second"}]},{"id":"2","department_name":"Used Car Enquiry","flag":"1","numbers":[{"number":"08884412075","name":"Dharmendra Kulkarni"}]}],"change_set":"59"}}

I want to store [text objectForKey:@"hotlines"] and [text objectForKey:@"change_set"] using Realm.I am able to store [text objectForKey:@"change_set"] as it is a simple string but not able to store [text objectForKey:@"hotlines"]. Any help on this?

Realm version: Latest

Xcode version: Latest

iOS/OSX version: Latest

Kirow commented 8 years ago

You just need to write correct Realm models that will fulfill your needs.

You may check issue #3415, maybe you will find something useful.

jpsim commented 8 years ago

This works for me:

let json = "{\"error\":false,\"text\":{\"hotlines\":[{\"id\":\"1\",\"department_name\":\"New Car Sales\",\"flag\":\"1\",\"numbers\":[{\"number\":\"09480825000\",\"name\":\"Showroom 1\"},{\"number\":\"342342423423\",\"name\":\"second\"}]},{\"id\":\"2\",\"department_name\":\"Used Car Enquiry\",\"flag\":\"1\",\"numbers\":[{\"number\":\"08884412075\",\"name\":\"Dharmendra Kulkarni\"}]}],\"change_set\":\"59\"}}"
let jsonObject = try! NSJSONSerialization.JSONObjectWithData(json.dataUsingEncoding(NSUTF8StringEncoding)!, options: [])

class Number: Object {
    dynamic var number = ""
    dynamic var name = ""
}

class Hotline: Object {
    dynamic var id = ""
    dynamic var department_name = ""
    dynamic var flag = ""
    let numbers = List<Number>()
}

class Text: Object {
    let hotlines = List<Hotline>()
    dynamic var change_set = ""
}

class MyModel: Object {
    dynamic var error = false
    dynamic var text: Text?
}

print(MyModel(value: jsonObject))

gets initialized properly, printing this:

MyModel {
    error = 0;
    text = Text {
        change_set = 59;
        hotlines = List<Hotline> (
            [0] Hotline {
                id = 1;
                department_name = New Car Sales;
                flag = 1;
                numbers = List<Number> (
                    [0] <Maximum depth exceeded>,
                    [1] <Maximum depth exceeded>
                );
            },
            [1] Hotline {
                id = 2;
                department_name = Used Car Enquiry;
                flag = 1;
                numbers = List<Number> (
                    [0] <Maximum depth exceeded>
                );
            }
        );
    };
}
vamshikrishna-iitbhu commented 8 years ago

@jpsim ..I am really sorry, I forgot to mention but I am using Objective C

vamshikrishna-iitbhu commented 8 years ago

@jpsim Also along with the model, I want to understand how to insert this data into database.

jpsim commented 8 years ago

Are you asking me to transliterate the Swift sample I posted above into Objective-C? Also, if you have very general questions, maybe the docs would be a good place to start, then you can loop back here if you have specific questions that aren't covered by the docs? https://realm.io/docs/objc/latest/

vamshikrishna-iitbhu commented 8 years ago

@jpsim

// HotlinesModel.h 

#import <Realm/Realm.h>
@interface Numbers : RLMObject
@property (strong, nonatomic) NSString *number;
@property (strong, nonatomic) NSString *name;
@end

RLM_ARRAY_TYPE(Numbers)
@interface Hotlines : RLMObject
@property (strong, nonatomic) NSString *id;
@property (strong, nonatomic) NSString *department_name;
@property (strong, nonatomic) NSString *flag;
@property (strong, nonatomic) RLMArray<Numbers> *numbers;
@end

RLM_ARRAY_TYPE(Hotlines)
@interface Text : RLMObject
@property (strong, nonatomic) NSString *change_set;
@property (strong, nonatomic) RLMArray<Hotlines> *hotlines;
@end

@interface HotlinesModel : RLMObject
@property (strong, nonatomic) Text *text;
@property BOOL *error;
@end

// HotlinesModel.m

#import "HotlinesModel.h"
@implementation HotlinesModel
@end
mrackwitz commented 8 years ago

The only thing which comes to attention is that you can't have a managed property which is a pointer to a bool as a type. Beside that you should be able to use Realm's builtin mapping capabilities to map your JSON format to your object model.

@interface HotlinesModel : RLMObject
@property (strong, nonatomic) Text *text;
-@property BOOL *error;
+@property BOOL error;
@end

If you have further open questions or problems, you'd need to clarify these for us, so that we can guide you.

vamshikrishna-iitbhu commented 8 years ago

@mrackwitz Now I am caught in this error. Terminating app due to uncaught exception 'RLMException', reason: 'Property 'text' is declared as 'Text', which is not a supported RLMObject property type. All properties must be primitives, NSString, NSDate, NSData, NSNumber, RLMArray, RLMLinkingObjects, or subclasses of RLMObject.

mrackwitz commented 8 years ago

And you're still declaring the Text model like seen above?:

@interface Text : RLMObject
@property (strong, nonatomic) NSString *change_set;
@property (strong, nonatomic) RLMArray<Hotlines> *hotlines;
@end
vamshikrishna-iitbhu commented 8 years ago

Yes. Should not I?

mrackwitz commented 8 years ago

No, you should. But the error indicates it wouldn't be defined. I can't reproduce that with the model code you shared. You don't have any other class with the same name in your code and accidentally the file with the Text : RLMObject not added and included to your target?

vamshikrishna-iitbhu commented 8 years ago

No, I do not have any other class named Text. This error is killing me.

mrackwitz commented 8 years ago

From the info I've, I'm out of ideas. If you can share a reproducible sample project with us privately to help@realm.io, I could take a look into that.

vamshikrishna-iitbhu commented 8 years ago

Done

mrackwitz commented 8 years ago

Okay, I thought you were just omitting the implementations of your model classes for brevity, but now I see that you actually didn't provided them completely. You need to provide at least an empty implementation block for all your model objects, otherwise the classes simply don't exist at runtime.

// HotlinesModel.m

#import "HotlinesModel.h"
@implementation HotlinesModel
@end
+
+@implementation Text
+
+@end
+
+@implementation Numbers
+
+@end
+
+@implementation Hotlines
+
+@end
vamshikrishna-iitbhu commented 8 years ago

That worked. Thanks To insert data into db, I am using the following code, but it is not working:

RLMRealm realm = [RLMRealm defaultRealm]; HotlinesModel hotlinesModel = [[HotlinesModel alloc]initWithValue: jsonObject valueForKey:@"text"]; [realm beginWriteTransaction]; [realm addObject:hotlinesModel]; [realm commitWriteTransaction];

mrackwitz commented 8 years ago

Just use [[HotlinesModel alloc] initWithValue:jsonObject].

vamshikrishna-iitbhu commented 8 years ago

Insertion is working fine. How do I update my db? I want to use change_set as my Primary Key

stel commented 8 years ago

To set a model's primary key you should override +primaryKey method, see more info in docs.

jpsim commented 8 years ago

I hope we were able to answer all your questions, @vamshikrishna-iitbhu! I'm closing this issue now since we haven't heard back from you in a little while.

vamshikrishna-iitbhu commented 8 years ago

I want to use 'change_set' my primary key which is a part of 'Text'. But I need to set primary key in 'HotlinesModel'. How do I do that using '+(NSString *)primaryKey{ return @"change_set"; }' ?

mrackwitz commented 8 years ago

A primary key must be stored in the model it is declared on. So you might need to mirror a property to HotlinesModel, so that you can declare there a primary key as well.

vamshikrishna-iitbhu commented 8 years ago

Hey, Thanks for the prompt reply. How do I mirror a property to HotlinesModel in the Text model?

mrackwitz commented 8 years ago

By declaring it there as well and making sure when you create or update objects that the values are the same.

vamshikrishna-iitbhu commented 8 years ago

Is it possible for me to add a property in my model that is not present in my jsonObject? If yes, how?

jpsim commented 8 years ago

@vamshikrishna-iitbhu properties in your model not present in the value you pass in to the initializer or createOrUpdate: won't be affected.

lizhaojie001 commented 7 years ago

Dosen't need to map "id" to other keyword? like "TitleID"?