K. Law K. Law - 2 months ago 15
Swift Question

Problems linking objects in realm swift

I am having problems linking objects in realm. I read the question and answer titled "Nested objects in realm" and tried the answer suggested but it did not work for me.

Here are my object classes:

import Foundation
import RealmSwift

class Job: Object {
dynamic var id = NSUUID().UUIDString
dynamic var name = ""
dynamic var address = ""
dynamic var phone = ""
dynamic var email = ""
dynamic var notes = ""
dynamic var material = 0.0
dynamic var edge = 0.0
dynamic var splash = 0.0
dynamic var discount = 0.0
dynamic var trip = 0.0
let rooms = List<Room>()

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

import Foundation
import RealmSwift

class Room: Object {
dynamic var id = NSUUID().UUIDString
dynamic var name = ""
dynamic var material = 0.0
dynamic var edge = 0.0
dynamic var splash = 0.0
dynamic var sinkType = ""
dynamic var sinkModel = ""
dynamic var numberOfSinks = 0
dynamic var faucet = ""
dynamic var rangeType = ""
dynamic var notes = ""
dynamic var jobs: Job?
let countertops = List<Countertop>()
//var linksToJob: [Job] {
// return linkingObjects(Job.self, forProperty: "rooms")
//}

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

}

import Foundation
import RealmSwift

class Countertop: Object {
dynamic var id = NSUUID().UUIDString
dynamic var depth = 0.0
dynamic var width = 0.0
dynamic var cabDescription = ""
dynamic var sqFt = 0.0
dynamic var room: Room?
//var linkToRoom: [Room] {
// return linkingObjects(Room.self, forProperty: "countertops")
//}
override static func primaryKey() -> String {
return "id"
}
}


Here are the functions I use to save the data:

@IBAction func saveButton() {
jobs.name = nameTF.text!
jobs.address = addressTF.text!
jobs.phone = phoneTF.text!
jobs.email = emailTF.text!
jobs.notes = notesTV.text!
jobs.discount = Double(discountTF.text!)!
jobs.material = Double(materialTF.text!)!
jobs.edge = Double(edgeTF.text!)!
jobs.splash = Double(splashTF.text!)!
jobs.trip = Double(tripTF.text!)!
do {
try! realm.write {
realm.add(jobs)
}
}

print(jobs)
// print(Realm.Configuration.defaultConfiguration.path!)

}
func saveData(){
rooms.name = nameTF.text!
rooms.material = Double(materialTF.text!)!
rooms.edge = Double(edgeTF.text!)!
rooms.splash = Double(splashTF.text!)!
rooms.notes = notesTV.text
rooms.sinkType = sinkTypeTF.text!
rooms.sinkModel = sinkModelTF.text!
rooms.numberOfSinks = Int(numberSinksTF.text!)!
rooms.faucet = faucetTF.text!
rooms.rangeType = rangeTF.text!
rooms.jobs?.id = keyValueLabel.text!
//rooms.linksToJob

do {
try! realm.write {
realm.add(rooms)
}
}

print(rooms)
}


and:

@IBAction func addNextButton(sender: AnyObject) {

// self.realm.beginWrite()
let realm = try! Realm()


if widthTF.text != "" {
Calculations.depth = Double(depthTF.text!)!
Calculations.width = Double(widthTF.text!)!

let depthAdded = depthTF.text
cabinetDepth.append(Double(depthAdded!)!)


let widthAdded = widthTF.text
cabinetWidth.append(Double(widthAdded!)!)


let descriptionAdded = pickerLabel.text
cabinetDescription.append(descriptionAdded!)

let runningTotal = Calculations.squareFeet()
squareFeetToBeAdded.append(runningTotal)

let sum = squareFeetToBeAdded.reduce(0,combine: {$0 + $1})

let roundedSqFt = Double(round(sum * 10) / 10)

sqFtLabel.text = "\(roundedSqFt)"

countertops.depth = Double(depthTF.text!)!
countertops.width = Double(widthTF.text!)!
countertops.cabDescription = pickerLabel.text!
countertops.sqFt = Double(sqFtLabel.text!)!
//countertops.linkToRoom

do {
try realm.write {
realm.add(countertops)
}
print(countertops)
} catch {
print("an error occurred")
}


widthTF.text = ""

numberTable.reloadData()
widthTF.becomeFirstResponder()

}
}


When I save the data and print the results here is what I get:

Job {
id = 00F95F55-54D8-426E-B483-C990A4171002;
name = Ken;
address = Address;
phone = phone;
email = email;
notes = Notes :;
material = 8;
edge = 0;
splash = 4;
discount = 1;
trip = 0;
rooms = RLMArray <0x7ffef9df29c0> (

);
}
Room {
id = 7D3F86B9-FCD7-4CB7-AD6E-9B8141A7390C;
name = Kitchen;
material = 9;
edge = 0;
splash = 4;
sinkType = Undermount Kitchen;
sinkModel = 50/50 Stainless Steel;
numberOfSinks = 1;
faucet = Single Hole;
rangeType = Free Standing Range;
notes = Notes:;
jobs = (null);
countertops = RLMArray <0x7ffef9df3720> (

);
}

Countertop {
id = 992B8BAE-392F-4513-85DC-CBA191D2AE08;
depth = 25.5;
width = 65;
cabDescription = Cabinet;
sqFt = 11.5;
room = (null);
}


As you can see the links return null.
Please tell me what I am doing wrong here.
Note: I comment out the linkingObjects in the models because it caused a crash. I'm not sure why.

Answer

Thanks to Austin who got me on the right track. Here is the code that finally did it.

  @IBAction func roomSaveNextBtnPushed(_ sender: UIButton) {
    let room = Room()
    room.roomName = roomTF.text!
    room.material = materialTF.text!
    room.edge = edgeTF.text!
    room.job = realm.objects(Job.self).last
    try! realm.write {
        realm.add(room)
        print(room)
    }
}

The link is made in the ' realm.object(Job.self).last ' line of code. This adds a room to a job as expected.

The suggestion in Austin's example ' let room = realm.create(Room.self) ' caused an error, and the project would not compile.

I am using Xcode 8 with Swift 3 and Realm-swift 1.1.0

Thanks again to those who offered help.

Comments