Not able to extend an Objective-C class in Swift - ios

I am using Swift 3.0 on Xcode 8.0 beta. I have installed a library using pods (FMDB) and now I am trying to extend one of its class in swift. I am able to use the API from my extended class but it crashes at runtime.
-[FMResultSet polygonsForColumnIndex:]: unrecognized selector sent to instance 0x608000056890
Below is the code for the extension:
public extension FMResultSet {
public func polygons(forColumnIndex index: Int32) -> [NMAMapPolygon] {
It crashes here when called:
let rs = db.executeQuery("select AsGeoJSON(geometry) from COM262_Project", withArgumentsIn: nil)
while (rs?.next())! {
//Crashes here!
let polygons = rs?.polygons(forColumnIndex: 0)
}
Note: Extensions work for other libraries like Alamofire.

Have you tried setting the function as #objc e.g.
public extension FMResultSet {
#objc public func polygons(forColumnIndex index: Int32) -> [NMAMapPolygon] {
On top of that have you changed the build setting Enable Modules to Yes.. Or if your using a config file CLANG_ENABLE_MODULES = YES

Related

Framework init param is not a member type of class

I am working on one framework and it is working fine if it is directly connected to the test app in the same project. But when I build it for release and implement it into another test app it shows me this error:
Failed to build module 'MySDK' for importation due to the errors above; the textual interface may be broken by project issues or a compiler bug
After some digging, I get an error message ... is not a member type of class ...
And the problem is in the initial parameter and in my observer
this is my entry / init class:
public class MySdk {
...
public init(eventObserver: MyResultObserver){ // this observer is a problem maker
EventObserver.shared.attach(eventObserver)
};
public init(){}
...
and this is how my MyResultObserver looks like (it is in a separate file)
import Foundation
public protocol MyResultObserver: AnyObject {
func success(successMessage: String)
func error(errorMessage: String)
}
and extension:
import Foundation
extension MyResultObserver: NSCopying {
func copy(with zone: NSZone? = nil) -> Any {
return self
}
}
How should it work (it is working in a test project in that SDK folder)
import UIKit
import MySdk
class ViewController: UIViewController, MyResultObserver { // added observer here
func success(successMessage: String) {} // observer function 1
func error(errorMessage: String) {} // observer function 2
...
#IBAction func openSdkClick(){
let myAwesomeSdk = MySDK(eventObserver: self) // init my sdk with observer
}
}
But the problem is when I implement it like this into the test app (as cocoa pod) it will give me an error above. I try to remove this observer parameter and SDK works fine.
How can I make my observer visible? Should I put it into headers somewhere? any hint?
UPDATE
when I am trying to use that framework I can jump to the definition and this is result:
// swift-interface-format-version: 1.0
// swift-compiler-version: Apple Swift version 5.7.1 (swiftlang-5.7.1.135.3 clang-1400.0.29.51)
// swift-module-flags: -target x86_64-apple-ios15.5-simulator -enable-objc-interop -enable-library-evolution -swift-version 5 -enforce-exclusivity=checked -O -module-name WalleePaymentSdk
// swift-module-flags-ignorable: -enable-bare-slash-regex
import AVFoundation
import Foundation
import Swift
import UIKit
#_exported import MySDK
import _Concurrency
import _StringProcessing
public protocol PaymenResultObserver : AnyObject {
func success(successMessage: Swift.String)
func error(errorMessage: Swift.String)
}
public typealias callback = (Swift.String) -> Swift.Void
open class MySDK : MySDK.PaymenResultObserver {
public func success(successMessage: Swift.String)
public func error(errorMessage: Swift.String)
public init(eventObserver: #escaping MySDK.callback)
public func launchPayment(transactionId: Swift.String, token: Swift.String, rootController: UIKit.UIViewController)
public func close()
#objc deinit
}
I did some modification to the code I put Observer inside SDK and I am trying to access the function callback which shuld be define by SDK consumer ... but that observer get this error:
'Observer' is not a member type of class 'MySdk.MySdk'
and callback
'callback' is not a member type of class 'MySDK.MySDK'
problem is this line:
open class MySDK : MySDK.PaymenResultObserver
and this line
public init(eventObserver: #escaping MySDK.callback)
both elements are there but I am accessing them inside the SDK and SDK can not inherit from them itself

No type or protocol named AKNode/AKToggleable

I'm trying to extend AKNode and AKToggelable and this error appears on Project-Swift.h file
What is the way to do this?
My class is
class AKCustom: AKNode, AKToggleable, AKComponent, AKInput {
public typealias AKAudioUnitType = AKBalancerDeplikeAudioUnit
public static let ComponentDescription = AudioComponentDescription(mixer: "dpba")
private var internalAU: AKAudioUnitType?
open dynamic var isStarted: Bool {
return internalAU?.isPlaying() ?? false
}
public init( _ input: AKNode? = nil) {
_Self.register()
super.init()
AVAudioUnit._instantiate(with: _Self.ComponentDescription) { [weak self] avAudioUnit in
self?.avAudioNode = avAudioUnit
self?.internalAU = avAudioUnit.auAudioUnit as? AKAudioUnitType
input?.connect(to: self!)
}
}
open func start() {
internalAU?.start()
}
open func stop() {
internalAU?.stop()
}
}
And error messages in Project-Swift.h file:
Cannot find interface declaration for 'AKNode', superclass of 'AKCustom'
No type or protocol named 'AKToggleable'
add #import "AudioKit/AudioKit-Swift.h" to PROJECT-Bridging-Header.h. Then AKNode will be accessible at Project-Swift.h.
Inside the AudioKit folder is a "Developer" folder that has examples for "Extending AudioKit" on both iOS and Mac. That's probably the best place to start. Make sure you're including the source as a framework properly - the examples in this folder show you how to do it either with source directly or the precompiled framework.

Typhoon parameter injection with initalizer crashing app

i want to use Typhoon (GitHub & WebSite) for dependency injection in my app. I use Swift Version 3 and Typhoon 3.6. Unfortunately my app is crashing when I try to initalize an object. I have the following protocol:
Protocol
import Foundation
#objc public protocol Client {
func method()
}
Protocol implementation
import Foundation
public class ClientWhateverImpl : NSObject, Client{
let name : String
init(name: name) {
self.name = name
}
public func method(){
//make something
}
}
Assembly
import Foundation
import Typhoon
public class MyAssembly: TyphoonAssembly {
public dynamic func client() -> AnyObject {
return TyphoonDefinition.withClass(ClientWhateverImpl.self) {
(definition) in
definition!.useInitializer("initWithName:") {
(initializer) in
initializer!.injectParameter(with: "name")
}
} as AnyObject
}
}
Call it somewhere
let myAssembly : MyAssembly = MyAssembly()
myAssembly.activate()
let client = myAssembly.client()
Unfortunately I got the following error:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Method 'initWithName:' not found on 'MyApp.ClientWhateverImpl'. Did you include the required ':' characters to signify arguments?'
I read some posts on stackoverflow about this error but on their side they forget to use the objectice-c method syntax. But in my case I use the objc method "initWithName". Is there something different in swift 3? Has someone the same problem?
Ok. I found the issue. It has something to do with an object which i wanted to inject. It doesn't inherit from NSObject and Typhoon makes something with it and fails:
definition!.useInitializer("initWithObject:") {
(initializer) in
initializer!.injectParameter(with: MyObject())
}
Before:
public class MyObject{
}
Solution:
public class MyObject: NSObject{
}
The documentation even says it:
Every class you want to inject has to be a subclass of NSObject in
some way (either by subclassing or adding #objc modifier).
I just thought the ClientWhateverImpl in my case has to inherit from NSObject. My fault. This is question closed

No setter method for assignment to property swift 3 with objective-c

I am using below code in one of my swift classes:
import UIKit
public class BRUFIMobile: NSObject {
public var mobileNumber : NSString?
public var provider : NSString?
public var aliasName: NSString?
public var aliasName_en : NSString?
#objc public var isDefault: Bool
public override init() {
self.isDefault = false
super.init()
}
}
My project contains both objective-c and swift codes. The code works fine on xCode 7 but now by updating to xCode 8 I get below error:
No setter method 'setIsDefault:' for assignment to property
I use the attribute in my objective-c code like below:
+ (BRUFIMobile *) convertUFIMobileToBRUFIMobile:(UFIMobile *) ufimobile
{
BRUFIMobile *brUFIMobile = [[BRUFIMobile alloc] init];
brUFIMobile.mobileNumber = ufimobile.number;
brUFIMobile.provider = ufimobile.provider;
brUFIMobile.aliasName = ufimobile.aliasName;
brUFIMobile.aliasName_en = ufimobile.aliasName_en;
brUFIMobile.isDefault = [ufimobile.isDefault boolValue];
return brUFIMobile;
}
is it now neccessary to define seetters manually?
Swift 3 beta makes special treatment for properties with leading is.
For the property isDefault, Swift generates isDefault as getter and setDefault: as setter (not setIsDefault:).
Use setDefault: in your Objective-C code, or make it a computed property and give #objc names manually.
(Addition)
"make it a computed property" means something like this:
private var _default: Bool = false
public var isDefault: Bool {
#objc(isDefault) get {
return _default
}
#objc(setIsDefault:) set {
self._default = newValue
}
}
(Update)
As far as I tested, this seems to work:
#objc(isDefault) public var isDefault: Bool
A little bit simpler than "making it a computed property". Please try.
(Update2)
Apple Staff has confirmed that "This is a known issue that will be fixed in a future beta:"
https://github.com/apple/swift/pull/3254
This is not a Core Data case. But the fix will work for this issue as well.
(It's a pity, as for now, Xcode 8 beta 2 does not include this fix.)
(Update3)
It is said in Xcode 8 beta 3 Release Notes that this feature is removed and I have confirmed that, with no #objc attribute, Objective-C setter setIsDefault: is available for Bool property isDefault.

Strongloop loopback ios swift sdk override repository error

I am usign strongloop's loopback ios sdk.Running XCode 6.3.
Objective: To create an instance of custom LBUser model class from custom LBUserRepository.
Code:
class UserProfileRepository : LBUserRepository
{
override class func repository() -> UserProfileRepository {
let repo = UserProfileRepository(className: "userprofiles")
return repo
}
}
Error:
I get an error: Cannot override 'repository' which has been marked unavailable
Why is this error coming ? is it a swift error in newer version?
References:
Apart from official documentation, I am doing it the same way as it is depicted here :
Strongloop iOS User Creation Error
and also I have even seen exact code in the test cases of obj c to swift converted code: https://github.com/Black-Tobacco/loopback-sdk-ios/tree/swift
I had the same problem and solved it like this:
class ClientRepository:LBUserRepository {
override init!(className name: String!) {
super.init(className: "Clients")
}
}

Resources