Issue with swift framework import - swift

I have created a swift framework.
In this framework i have some swift file and one category in objective-C (so there is the .h and .m files).
I successfully build my framework, but when i import it into another project, only the method from my category (written in objective-C) are visible. If i try to use any swift class i got an error "Use of unresolved identifier".
I have checked the following points in my framework project :
all my swift class are public public class Toto
i have set the build settings - packaging - defines module param to yes
In my project where the framework is imported, i have the following code :
import UIKit
import myframework
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
toto()
}
func toto() {
let data = NSData()
data.isGzippedData()
var client = Client ()
NSLog("ok");
}
}
I have an error "Use of undeclared identifier" for the line var toto = Client (), but in my swift framework the class Client is public and its default constructor is public.
However, if i comment this line, the code works fine, even if the method isGzippedData is declared and implement in my framework (but in objective-C).
How can i use the swift class from my framework into my project ?

Related

NSClassFromString #interface for 'GIDSignIn' declares the selector 'fetchCloudValues' compiler error

I'have a project where i have multiple targets, and in one of those targets i have added a custom class to download some Values from Firebase Remote Config.
Custom class is declared as follows:
#objc (Test)
final class CheckUpdate: NSObject {
#objc static let sharedInstance = CheckUpdate()
#objc func fetchCloudValues() {
// Grab remote config values and do things
}
}
I've added this class as target membership only on one target and in the code I've add
Class asdasd = NSClassFromString(#"Test");
if (asdasd) {
[[asdasd sharedInstance] fetchCloudValues];
}
My issue is that, at line where I call fetchCloudValues I get a compiling error saying that:
no visible #interface GIDSignIn declares the selector fetchCloudValues
but it's obviously an issue because asdasd should not be of type GIDSignIn

NSClassFromString from dependencies

I'm having this problem getting the reflection to work from external frameworks as dependencies.
So let say I had two projects, one is a sample app project
SampleApp.xcodeproj
#obj protocol Extension : NSObjectProtocol {
//..Some definitions
}
And another with the framework project that the sample app will be depended on and is a submodule of the sample app project.
Framework.xcodeproj
class SampleClass : NSObject, Extension {
//some definitions
}
In this framework, Extension.swift file, where the Extension protocol is defined, is included in the build as a reference
Now here's the problem on this code
if let customExtension = NSClassFromString("Framework.SampleClass") as? NSObject.Type {
let extensionInstance = customExtension.init()
if extensionInstance is Extension { //The problem here, it returned false at this point
print("It is an Extension")
} else {
print("It is not an Extension")
}
}
I noticed that the Extension protocol defined in the Framework project was defined as Framework.Extension instead of SampleApp.Extension. How would I make it so the SampleClass class is defined as SampleApp.Extension instead of Framework.Extension?

Why is type undeclared?

I have a very simple example that I can't get to work. Both classes are in the same iOS project. I get this error when I build:
Use of undeclared type 'classB'
It happens in classA on the static var line.
import UIKit
class classB: NSObject {
var temp:Int?
}
import UIKit
class classA: NSObject {
static var classBList:[classB]?
}
Any idea what I'm doing wrong?
The reason why you might get this error is if the ClassB file is not included in the project. If classA and classB are in separate files then verify that classB is included in the project. The reason why you are getting this error is because the compiler is not finding the class definition of classB. This can happen if the file is not included in the target.

Array extension called from other module

Array extension methods are unavailable from other modules (for example the XCTest project)
For the sake of simplicity the code below does nothing but it can be used to reproduce the error
import Foundation
extension Array {
mutating func myMethod(toIndex: Int) -> Int! {
// no real code, it's here only to show the problem
return 0
}
}
Calling it from the same module works as expected but from a test class don't
class MyProjectTests: XCTestCase {
func testMoveObjectsFromIndexes1() {
var arr = ["000", "001", "002", "003"]
arr.myMethod(0)
}
}
I think this is correct because the method visibility is restricted to its own module, indeed I obtain the error '[String]' does not have a member named 'myMethod'
I've tried to define the extended method as public as shown below
extension Array {
public mutating func myMethod(toIndex: Int) -> Int! {
// no real code, it's here only to show the problem
return 0
}
}
But I get the compile error 'Extension of generic type 'Array<T>' from a different module cannot provide public declarations'
Until Beta 7 using public solved the problem but under XCode 6.1 (6A1046a) I obtain this error
How can I fix it to run under other modules/projects?
Swift does not allow public extensions currently so you will need to include that extension swift file in your project and put it part of the target.
While not entirely solving the original question, I did find that I could test extension methods in Swift 2.0 (Under XCode 7.0) by importing the module with the #testable directive:
#testable import MyGreatModule

Private var is accessible from outside the class

This was done in Playground, just to simplify.
class MyPrivateVar
{
private var priv: String?
}
var myInstance = MyPrivateVar()
myInstance.priv = "Something"
No compiler warning. In fact auto-complete is showing priv without a problem.
My understanding is that outside the boundaries of {} of the class, I'm not supposed to be able to see a private anything, func nor var.
Am I missing something?
Access modifiers in Swift are implemented differently than other languages. There are three levels:
private: accessible only within that particular file
internal: accessible only within the module (project)
public: accessible from anywhere
Unless marked otherwise, everything you write is internal by default.
The Swift blog had a post about access control when the features were introduced in beta 4, and Apple's documentation has a chapter as well.
Note: this answer is for Swift 2
The Swift Programming Language states:
Swift provides three different access levels for entities within your
code. These access levels are relative to the source file in which an
entity is defined, and also relative to the module that source file
belongs to.
If you wan't to test private access level with Swift, the following step by step may help you.
1/ Create a new Xcode project.
2/ Create a file, MyPrivateVar.swift, and add the following code in it:
class MyPrivateVar {
private var priv: String? = nil
}
3/ Create a second file, MySecondClass.swift, and add the following code in it:
class MySecondClass {
init() {
var myPrivateVar = MyPrivateVar()
myPrivateVar.priv = "some string"
}
}
Xcode will immediatly give you a Swift compiler error message:
'MyPrivateVar' does not have a member named 'priv'
4/ Now, remove the two previous files from your project and create a single file TwoClassesInAFile.swift with the following code in it:
class MyPrivateVar {
private var priv : String? = nil
}
class MySecondClass {
init() {
var myPrivateVar = MyPrivateVar()
myPrivateVar.priv = "some string"
}
}
This time, you will get no Swift compiler error message and you will be able to access MyPrivateVar's priv private property from MySecondClass because priv and MySecondClass are in the same file (your TwoClassesInAFile.swift file).
Furthermore, access levels also work for global variables. For example, Xcode won't give any compiler error if the following code is part of the same ViewController.swift file:
import UIKit
private var globalPrivate : String? = nil
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
globalPrivate = "some string"
println(globalPrivate)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
However, if you define globalPrivate outside of ViewController.swift, Xcode will generate an error message:
Use of unresolved identifier 'globalPrivate'