nc14
nc14

Reputation: 559

Back button and creating new entry causes app to crash (UUID cannot be amended) Realm Swift

When I go back to VC1 (which allows the user to input a title for a book and create an entry in realm including the title and a UUID for that book) from VC2 (using the provided back button as part of the navigation controller not a custom segue) and then create a new book object in Realm (by adding another title to the text field in VC1), the app crashes saying I cannot amend the primary key once set.

I am intending to create a new entry (in theory I could add one, go back, add another etc) rather than try to overwrite an existing entry.

I've read the docs (and even looked at an old project where a similar thing is working) but I can't understand why it isn't just creating a new entry. I looked at the Realm docs (e.g. referenced in this answer Realm in IOS: Primary key can't be changed after an object is inserted)

Code here is VC1 allowing the user to create a new novel (by adding a title into a text field which is earlier in the code)

func createNewNovel() {

        let realm = try! Realm()
        novelCreated.novelID = UUID().uuidString
        novelCreated.novelTitle = novelTitleInput.text!
        novelCreated.createdDate = Date()

        do {
            try realm.write {
                realm.add(novelCreated)
                print ("Novel Created Successfully")
            }
        } catch {
            print("error adding novel")
        } 

Then I prepare to pass the novelID to VC2 :

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let novelData = NovelObject()
        novelData.novelID = novelCreated.novelID

        if let destVC = segue.destination as? WriteVC {
        destVC.novelIDPassed = novelData.novelID

        }
    }

This works fine and the segue triggers from a button press on VC1. I can also print the ID of the novel in VC2 so that's working fine.

BUT... when I go back from VC2 and input a new title in the text field in VC1 it should create a new NovelObject, not try to update the existing one (which is causing it to crash). You could even theoretically have the same book title twice but they should have a different UUID (which is the primary key)

I must be missing something trivial I suppose but can't work it out!

The novel is created as at the top :

class NewNovelVC: UIViewController {

let novelCreated = NovelObject()

@IBOutlet weak var novelTitleInput: UITextField!
@IBOutlet weak var createButtonOutlet: UIButton!

then it is populated with variables

Upvotes: 0

Views: 95

Answers (1)

Aakash Dave
Aakash Dave

Reputation: 896

This is due to classic issue of same object being in the memory re-instantiated which points to the same value of primary key. Creating a singleton class can be very handy here as well.

Create a service file. This will keep your RealSwift initialized on a specific thread as your current block.

RealService.swift

import RealmSwift

    class RealmService {

        static let uirealm = RealmService()

        private var _initRS = try! Realm()

        var realm: Realm! {
            return _initRS
        }
    }

Novel.swift :

import RealmSwift

    class Novel : Object {

        @objc dynamic var uid : String? = nil
        @objc dynamic var title: String? = nil

        override static func primaryKey() -> String {
            return "uid"
        }

    }

    extension Novel {

        func writeToRealm(){
            try? RealmService.uirealm.realm.write {
                print("Creating the Novel Object")
                RealmService.uirealm.realm.add(self, update: true)
            }
        }

        func DeleteFromRealm(object: Results<Novel>){
            try? RealmService.uirealm.realm.write {
                print("Deleting the Novel Object")
                RealmService.uirealm.realm.delete(object)
            }
        }

    }

and just implement as @Don mentioned, write in the block where you are setting the title.

   var novel: Novel! // Declare this in above in the class.

    novel = Novel()
    novel.title = title
    novel.uid = uid
    novel.writeToRealm()

Hope that helped.

Upvotes: 1

Related Questions