Swift 4中尝试将Realm数据库对象用作实例变量的问题
Hey there! Let's walk through the issues in your code and get things working smoothly, especially since you're transitioning from Java to Swift.
Core Issue in Your Current Code
The biggest problem right now is that your mTestResult property is an optional TestRes?, and you're trying to assign to self.mTestResult?.id without first initializing the TestRes instance. If mTestResult is nil (which it is by default), that line of code does nothing—no error, but no value gets set either. That's why your print statement is probably showing nil for the test ID.
Fix 1: Properly Initialize TestRes
You have two solid options here:
Option A: Make mTestResult a Non-Optional Property
If TestRes should always exist when ClassA is initialized, initialize it directly:
public class ClassA { // Swift convention: capitalize class names var mTestResult: TestRes = TestRes() // Initialize immediately func setTestResult(measurement: Measurement){ self.mTestResult.id = measurement.measurementId print("Test Id: \(self.mTestResult.id)") print("Measurement Id: \(measurement.measurementId)") // Verify the source value } }
Option B: Initialize TestRes When Needed
If mTestResult might not exist until a measurement comes in, check and initialize it inside the method:
public class ClassA { var mTestResult: TestRes? func setTestResult(measurement: Measurement){ // Create a TestRes instance if one doesn't exist yet if self.mTestResult == nil { self.mTestResult = TestRes() } self.mTestResult?.id = measurement.measurementId print("Test Id: \(self.mTestResult?.id)") } }
Fix 2: Update ClassA from ClassB
To set ClassA's variable from ClassB, you need a reference to a ClassA instance in ClassB. Here's how to do it:
- Add a property in
ClassBto hold theClassAinstance:
public class ClassB { var classAInstance: ClassA? // Store a reference to your ClassA object // ... your other Bluetooth/RxSwift code }
- When you have a
Measurementobject inClassB, call thesetTestResultmethod:
// Inside ClassB, when you get a new Measurement if let classA = classAInstance { classA.setTestResult(measurement: newMeasurement) }
Bonus: RxSwift-Friendly Approach
Since you're using RxSwift for Bluetooth communication, a reactive pattern will make this cleaner. Here's how to wire it up:
- In
ClassB, create a Subject to broadcast newMeasurementobjects:
import RxSwift public class ClassB { let measurementSubject = PublishSubject<Measurement>() let disposeBag = DisposeBag() // ... your Bluetooth code that emits measurements // When you get a measurement, send it through the subject: // measurementSubject.onNext(newMeasurement) }
- In
ClassA, subscribe to this subject to automatically updatemTestResult:
import RxSwift public class ClassA { var mTestResult: TestRes = TestRes() let disposeBag = DisposeBag() func bind(to classB: ClassB) { classB.measurementSubject .subscribe(onNext: { [weak self] measurement in guard let self = self else { return } self.mTestResult.id = measurement.measurementId print("Updated Test Id: \(self.mTestResult.id)") }) .disposed(by: disposeBag) } }
- Connect them somewhere (like your view controller or app setup):
let classA = ClassA() let classB = ClassB() classA.bind(to: classB)
Realm Integration Notes
Since you're storing these objects in Realm:
- Ensure
TestResis a subclass ofObject:import RealmSwift class TestRes: Object { @objc dynamic var id: String = "" // Use appropriate type for your measurementId // Add other Realm properties here override static func primaryKey() -> String? { return "id" // If id should be the primary key } } - When updating
mTestResultfor Realm, make sure you're doing it inside a write transaction if needed:let realm = try! Realm() try! realm.write { self.mTestResult.id = measurement.measurementId }
Quick Swift Convention Tip
Remember that Swift uses capitalized class names (e.g., ClassA instead of classA)—this makes your code more readable and aligns with standard Swift practices.
内容的提问来源于stack exchange,提问作者Aaron Miller

