Realm Swift crashing with uncaught exception when trying to get object - swift

I am using RealmSwift in my MacOS/OSX application on OSX 10.12.3 and Realm crashes with uncaught exception when I try to get an object from the database.
Here's the code snippet that crashes on the get object func:
private var database: Realm!
init(some_var: String) {
var configuration = Realm.Configuration()
configuration.fileURL = configuration.fileURL!.deletingLastPathComponent().appendingPathComponent("\(some_var).realm")
do {
debugPrint("Inside init: Current thread \(Thread.current)")
self.database = try Realm(configuration: configuration)
} catch {
debugPrint("realmInit: Can't create realm database.")
}
}
func getObject<T: Object, K>(with primaryKey: K) -> T? {
debugPrint("Inside getObject: Current thread \(Thread.current)")
return self.database.object(ofType: T.self, forPrimaryKey: primaryKey) // THIS LINE THROWS EXCEPTION
}
I get a crash with an uncaught exception:
"Inside init: Current thread <NSThread: 0x600000075700>{number = 5, name = (null)}"
"Inside getObject: Current thread <NSThread: 0x600000075700>{number = 5, name = (null)}"
libc++abi.dylib: terminating with uncaught exception of type NSException
At first I thought it was a threading issue, but you can see that I init the Realm and getObject on the same thread.
Any help would be appreciated please?

Turns out the issue was with the return type being an optional generic.
After a conversation with one of the contributors to the Realm library on github, it sounded like it could potentially be a RealmSwift bug.
Issue has been raised here https://github.com/realm/realm-cocoa/issues/4951
Workaround is to implement a function that returns a Bool if the object exists, and then return a non-optional generic when it does, while create a new object if it doesn't exist.

Related

Run method on class knowing only its name

how can I launch method knowing its name (as String)
// key.rawValue.firstUppercased is `ApiAddress`
let result = preferencesRepository.perform(Selector("get\(key.rawValue.firstUppercased)"))
where preferencesRepository has method getApiAddress() and conforms to NSObject
public class RealPreferencesRepository: NSObject {
func getApiAddress() -> String
// ...
I have fatal error:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '-[PreferencesModule.RealPreferencesRepository getApiAddress]:
unrecognized selector sent to instance 0x600000090a70'
thanks for help in advance
You need to prefix the getApiAddress() method with #objc attribute.
Also, since the return value of the perform method is Unmanaged, you need to use takeRetainedValue() to convert the return value.
public class RealPreferencesRepository: NSObject {
#objc func getApiAddress() -> String {
return "success"
}
}
let preferencesRepository = RealPreferencesRepository()
let result = preferencesRepository.perform(Selector("getApiAddress"))
let value = result?.takeRetainedValue() as! String
print(value)
// => success

realm migration, cannot add property

testing realm, cannot add a new property to my testing class. Followed documentation and some answer here but both are not working. In my code even the "plain" empty default block for migration is not working, using updated realm.
getting this error
Thread 1: Fatal error: 'try!' expression unexpectedly raised an error: Error Domain=io.realm Code=10 "Migration is required due to the following errors:
- Property 'ComicType.creationDate' has been added." UserInfo={NSLocalizedDescription=Migration is required due to the following errors:
- Property 'ComicType.creationDate' has been added., Error Code=10}
it seems I'm not changing the schemaVersion, but I did in the "basic" migration block. I check the schema version in app delegate with:
let configCheck = Realm.Configuration();
do {
let fileUrlIs = try schemaVersionAtURL(configCheck.fileURL!)
print("schema version \(fileUrlIs)")
} catch {
print(error)
}
my AppDelegate:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let config = Realm.Configuration(schemaVersion: 1, migrationBlock: { migration, oldSchemaVersion in
if (oldSchemaVersion < 1) {
}
})
Realm.Configuration.defaultConfiguration = config
_ = try! Realm()
return true
}
my class:
import Foundation
import RealmSwift
class ComicType: Object {
#objc dynamic var name : String = ""
#objc dynamic var creationDate : Date? //the new property
}
Issue solved this way: the real issue is not about schema number, but about not calling at all the migration code, I realized the migration schema remained always the same. True error is calling let realm = try! Realm() in my view controller using it as global constant. Now using lazy var realm = try! Realm() Great help found here . Now after each change in my model, I update in appDelegate the schemaVersion.
What worked for was to remove the app from the iOS Simulator, and then run it again using XCode. More about this is found here: https://github.com/RocketChat/Rocket.Chat.iOS/issues/104
I was facing a similar issue, my error stack trace was beginning like this:
`fatal error: 'try!' expression unexpectedly raised an error: Error Domain=io.realm Code=10 "Migration is required due to the following errors:
The errors shown was just confirming the some objects have been saved locally. so, there was no clue on what caused the problem.
What I figured was, the issue was that the schema of Realm Database was violated, since I updated the Objects' classes that I have been saving locally. So, it requested that I update the schema.
I suppose that a new Realm file with is created when the app is removed and run again. If so, then a new schema is created that works with latest code

uncaught exception 'NSInvalidArgumentException', reason: '-[SubResultComponent setDate:]: unrecognized selector sent to instance 0x60000046b640'

I have an error to which I am not sure on how to fix.
Here is there error
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[SubResultComponent setDate:]: unrecognized selector sent to instance 0x60000046b640'
Here is the SubResultComponent
extension SubResultComponent {
#nonobjc public class func fetchRequest() -> NSFetchRequest<SubResultComponent> {
return NSFetchRequest<SubResultComponent>(entityName: "SubResultComponent")
}
#NSManaged public var date: String?
#NSManaged public var price: NSDecimalNumber?
}
This is where I Call set date
func updateUI() {
guard rateLog != nil else {
return
}
// Update cell UI
self.dateLabel.text = rateLog?.date
self.priceLabel.text = numberFormatter.string(from: (rateLog?.price)!)
}
#NSManaged acts similar to the objective c version of dynamic; it is a promise to the compiler that the object will have those properties at runtime. It does not actually make those properties. For this to work these properties need to be setup correctly in the core data model file. Using the editor's "Create NSManagedObject Subclass..." option greatly helps in keeping you code and the model in sync.

RLMException: Object type does not match RLMArray type

I have a simple object:
class MyObject : Object {
dynamic var dummyField: String!;
}
and another object which inherits from MyObject:
class MyOtherObject : MyObject {
dynamic var anotherDummyField: String!;
}
Now I do the following. I have a Realm List of MyObject and I create an instance of MyOtherObject and try to save it inside the list:
class Operator {
internal var myObjects: List<MyObject>!;
internal var myObject: MyObject!;
func operate() {
self.myObject = MyOtherObject();
self.myObject.dummyField = "dummy field";
self.myObject.anotherDummyField = "another dummy field";
self.myObjects = List<MyObject>();
self.myObjects.append(myObject); // crash!
}
}
It crashes with the error:
Terminating app due to uncaught exception 'RLMException', reason: 'Object type 'MyOtherObject' does not match RLMArray type 'MyObject'.'
Since MyOtherObject is a subclass of MyObject I cannot understand why the app is crashing at this point with this error message.
Realm Lists are not covarient. You can only store objects of exactly the declared type in them.
self.myObjects = List<MyObject>();
This is not a proper value
self.myObjects = List<Needs actual object here not class>();

NSSetUncaughtExceptionHandler not firing in Swift 3?

I'm trying to catch all NSExceptions in a Swift3 program - have been following this Stack Overflow answer
So I've got this:
override func viewDidLoad() {
super.viewDidLoad()
NSSetUncaughtExceptionHandler { exception in
print("EXCEPTION CAUGHT HERE....")
print(exception)
print(exception.callStackSymbols)
}
// force NSException
let array = NSArray()
_ = array.object(at: 99)
}
but the exception's not being called
Instead I get this output:
2016-09-04 14:49:14.252 catchAllErrorsTest[8126:164827] Failed to set
(contentViewController) user defined inspected property on (NSWindow):
*** -[__NSArray0 objectAtIndex:]: index 99 beyond bounds for empty NSArray
I also tried putting the exception into AppDelegate (in applicationWillFinishLaunching and applicationDidFinishLaunching), but same result
I did as follows and works for me in Swift 3.
Define your NSSetUncaughtExceptionHandler as a constant outside any method declaration in your AppDelegate:
let uncaughtExceptionHandler : Void = NSSetUncaughtExceptionHandler { exception in
NSLog("Name:" + exception.name.rawValue)
if exception.reason == nil
{
NSLog("Reason: nil")
}
else
{
NSLog("Reason:" + exception.reason!)
}
}
This fires at any uncaught exception as this constant is evaluated as soon as your App Delegate instance loads i.e. at app launch.
Note: the Void type declaration removes a compiler warning for a Void inferred type that "could be unexpected" ;-) .