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

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.

Related

Invoking a static swift function of an extended class from ObjC++ [duplicate]

This question already has answers here:
Objective-C Category Causing unrecognized selector
(8 answers)
Closed 5 months ago.
I have a swift class containing a lot of methods. I've split it into multiple classes using the extension keyword.
Taking an example,
#objc
class SwiftModule : NSObject {
#objc
static func Method1 (_ pArg:UnsafeMutablePointer<NSString>) -> Void {
// Does something
}
#objc
static func Method2 (_ pArg:UnsafeMutablePointer<NSString>) -> Void {
// Does something
}
}
#objc
extension SwiftModule {
#objc
static func Method3 (_ pArg:UnsafeMutablePointer<NSString>) -> Void {
// Does something
}
}
Now, I have to invoke this method from C++ using the ObjC++ wrapper. I have the following in a .mm file,
// Include the generated swift interface header to invoke swift methods from C++
#include "GeneratedSwiftInterfaceHeader.hpp"
bool CppModule::InvokeMethod1 () {
NSString * string;
[SwiftModule Method1:&string];
if ([string length] == 0)
return false;
// Do something with string
return true;
}
bool CppModule::InvokeMethod2 () {
NSString * string;
[SwiftModule Method2:&string];
if ([string length] == 0)
return false;
// Do something with string
return true;
}
bool CppModule::InvokeMethod3 () {
NSString * string;
[SwiftModule Method3:&string];
if ([string length] == 0)
return false;
// Do something with string
return true;
}
I'm able to invoke Method1 and Method2. But Method3 failed with the following error
ibc++abi: terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[SwiftModule Method3:]: unrecognized selector sent to class 0x107343398'
terminating with uncaught exception of type NSException
(lldb)
This means that Method3 is not recognised as part of SwiftModule class, right? Why? Where did I go wrong?
I have seen a few posts (this and this) which showcase a similar problem, but it still doesn't work.
I'm using swift 5.0 and Xcode 13.4.
When discussing the problem in details in the comments section, it turned out that the Objective-C interfaces generated were part of a static library which the final project is linked against.
There is a known issue with Objective-C categories inside of static libraries, where the categories methods implementation are not "glued" to their symbolic names by linker. In order to get it round you pass -ObjC flag to the linker in the application (not library) target build settings. It will make the linker to load all symbols of static libraries found in both Objective-C classes and categories:

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

Using an Timer to switch a Boolean value?

I'm relatively new to coding and I'm trying to switch a boolean value by with Timer. However, I keep getting an error. Here's my code:
var Display = true
var BoolTimer = Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(ThirdViewController.SwitchBool), userInfo: nil, repeats: true)
#objc func SwitchBool()
{
if Display == true{
Display = false
print(Display)
} else {
Display = true
print(Display)
}
}
I get this error when the timer runs out:
[_SwiftValue SwitchBool]: unrecognized selector sent to instance 0x604000646ed0
2018-02-13 10:55:35.664486+1300 HC 1[12286:466779] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_SwiftValue SwitchBool]: unrecognized selector sent to instance 0x604000646ed0'
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
Can someone help me understand why I am getting this error and how to fix it?
If you run this code, what would you expect the output to be?
import Foundation
class C: NSObject {
var foo = type(of: self)
}
print(C().foo)
You're expecting to see C, right? But instead you get:
(C) -> () -> C
The reason for this is that when you use self in a property's default value, self refers to a closure which is created as part of the initialization process, not to the object itself. The reason for this is that the property default values are computed before the object's init function has completed, and you can't use self before the object has completed initialization. So, Objective-C is trying to send the SwitchBool method to a closure, which of course doesn't support that method.
To fix this, just make the property lazy; this will cause the property to be initialized sometime after the object itself has been initialized, which will make it possible to use self and have it actually refer to your object, as you can see from the following test:
import Foundation
class C: NSObject {
lazy var foo = type(of: self)
}
print(C().foo)
which outputs:
C
EDIT: If the object in question is a view controller, initializing the timer to nil and creating it in viewDidLoad, as suggested by #vacawama, is also a good approach to take. Basically you just need to make sure you create the timer at some point after the object has completed its initialization.

Realm Swift crashing with uncaught exception when trying to get object

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.

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>();