I am using FXForm Library and want to get data from my Swift file in Objective C file function.
Demo Project Link
Swift Code Implimnetation:
let fontName = "HelveticaNeue"
let fontSizeLarge:CGFloat = 14.0
var hiddenElementFromFormIndex = [Int]()
//fx form variables
#objc class FXFormVariables : NSObject {
public override init() {}
class func FXFontName() -> String { return fontName }
class func FXFontSize() -> CGFloat { return fontSizeLarge }
class func FXHiddenCell() -> NSArray { return hiddenElementFromFormIndex as NSArray }
}
In Objective C file, I am getting error when we write below like:
NSArray *hideArray = [FXFormVariables FXHiddenCell];
I created the bridge header file correctly and Target Membership is checked in the Objective C file.
Error I am getting:
Undefined symbols for architecture x86_64:
"_OBJC_CLASS_$__TtCC13Social_Engine11AppDelegate15FXFormVariables", referenced from:
objc-class-ref in FXForms.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Architectures and Valid Architectures are:
armv7 and armv64
To use Swift class inside Objective-C file you need to import Xcode-generated header file in your Objective-C file.
#import "ProductModuleName-Swift.h"
I created a Test project with the same name.
Swift File:
//
// FXFormVariables.swift
// Test
//
// Created by Puneet Sharma2 on 12/07/17.
// Copyright © 2017 com.puneet.sh2525. All rights reserved.
//
import Foundation
import UIKit
let fontName = "HelveticaNeue"
let fontSizeLarge:CGFloat = 14.0
var hiddenElementFromFormIndex = [Int]()
//fx form variables
#objc class FXFormVariables : NSObject {
public override init() {}
class func FXFontName() -> String { return fontName }
class func FXFontSize() -> CGFloat { return fontSizeLarge }
class func FXHiddenCell() -> NSArray { return hiddenElementFromFormIndex as NSArray }
}
Objective-C File
#import "ABC.h"
#import "Test-Swift.h"
#implementation ABC
- (void)drawRect:(CGRect)rect {
NSArray *hideArray = [FXFormVariables FXHiddenCell];
}
You can read more about it here.
Literally I spent hours trying to figure out why this was happening with one of my swift files that i was importing into my Objc codebase, and the real reason was due to the use of a nested class.
Such as:
#objc public class MyClass {
#objc public class SecondClass {}
}
And if I tried using SecondClass in my objective-c code, I would the Apple Mach O-Link errors of death. So the solution was to de-nest the class you want to use.
#objc public class MyClass {}
#objc public class SecondClass {}
Related
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
In my CocoaPods, I have a swift Protocol:
#objc
public protocol MyProtocol {
func myFunction()
}
In my main app:
I have Objective-C class that use that protocol as parameter in function:
#import <Foundation/Foundation.h>
#import "MyPod-Swift.h"
#protocol MyProtocol;
#interface OCClass : NSObject
- (void)configure:(id<MyProtocol>)delegate;
#end
I have a Swift class in main app conform to this protocol
class Test: MyProtocol {
func myFunction() {
}
}
In another swift call, I am using my OCClass in swift, it will show error: Argument type 'MyPod.MyProtocol' does not conform to expected type '__ObjC.MyProtocol'
import MyPod
import Foundation
class SwiftClass {
func myFunc() {
let test: MyProtocol = Test()
let ocClass = OCClass()
// Argument type 'MyPod.MyProtocol' does not conform to expected type '__ObjC.MyProtocol'
ocClass.configure(test)
}
}
I think this happen because when we use protocol in OC, it represent as __ObjC.MyProtocol, but after we import MyPod in SwiftClass, it will use the MyPod. MyProtocol from my Pod directly, so it caused the error. I tried to avoid import MyPod as following code, then it will show error: Argument type 'Test' does not conform to expected type 'MyProtocol'. Compiler don't know Test conform to MyProtocol
import Foundation
class SwiftClass {
func myFunc() {
let test = Test()
let ocClass = OCClass()
// Argument type 'Test' does not conform to expected type 'MyProtocol'
ocClass.configure(test)
}
}
Is there any solution for it, other than rewriter the OC to swift
I have two files, one that's called CodeInjection.m with the content like
#import <Foundation/Foundation.h>
#import "Someheaderfile.h"
#interface CodeInjection: NSObject
#end
#implementation CodeInjection
static void __attribute__((constructor)) initialize(void){
NSLog(#"==== Code Injection in Action====");
[[CodeInjectionSwift shared] performTask];
}
#end
Then I have a CodeInjectionSwift.swift file with content
import Foundation
import NetworkInterceptor
#objc class CodeInjectionSwift: NSObject {
#objc public static let shared = CodeInjectionSwift()
override private init(){}
#objc func performTask(){
let requestSniffers: [RequestSniffer] = [
RequestSniffer(requestEvaluator: AnyHttpRequestEvaluator(), handlers: [
SniffableRequestHandlerRegistrable.console(logginMode: .nslog).requestHandler()
])
]
let requestRedirectors: [RequestRedirector] = [
RequestRedirector(requestEvaluator: DomainHttpRequestEvaluator(domain: "www.antennahouse.com"), redirectableRequestHandler: AlternateUrlRequestRedirector(url: URL(string: "https://www.rhodeshouse.ox.ac.uk/media/1002/sample-pdf-file.pdf")!))
]
let networkConfig = NetworkInterceptorConfig(requestSniffers: requestSniffers,
requestRedirectors: requestRedirectors)
NetworkInterceptor.shared.setup(config: networkConfig)
NetworkInterceptor.shared.startRecording()
}
}
When trying to use "CodeInjectionSwift", I get errors like this
Make #objc func performTask() public:
#objc public func performTask()
My original answer is wrong. I've left it below for context.
In fact the whole problem is that you need to import a special header into your Objective-C class.
#import "TestImportSwift-Swift.h"
where TestImportSwift is replaced by the name of your project.
Old wrong answer
shared is not a class member, it is a static member. Unfortunately, Swift doesn't support class variables, only functions, so you could try
#objc class CodeInjectionSwift: NSObject {
static let _shared = CodeInjectionSwift()
#objc public class func shared() -> CodeInjectionSwift { return _shared }
// Rest of the class
Note that I haven't tried this in a real project.
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
I'm trying to implement a framework using swift but the header file is not been updated with the class or the functions:
Here is my code in my swift file:
public class one{
public func two(name:String) -> String {
print(name)
}
}
#objc public class SwiftInObjc:NSObject {
public func bla(){
}
}
After I build this is what I see in my header file:
#import <UIKit/UIKit.h>
FOUNDATION_EXPORT const unsigned char sampleFramework[];
framework using statements like #import <sampleFramework/PublicHeader.h>
How can generate update to the header file?