Reputation: 559
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
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