Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift framework nested classes are not exported well in Objective C

I have the following classes contained by Geography.framework (a Swift framework project):

public class Contact : NSObject
{
    public static let  Table: String = "contacts"

    public class Fields : NSObject
    {
        public static let  Id: String = "_id"
        public static let  Name: String = "name"
        static let  rawId: String = "rawId"
    }
}


public class Country : NSObject
{
    public class Fields : NSObject
    {
        public static let  Id: String  = "_id"
        public static let  Prefix: String = "prefix"
        static let  rawId: String  = "rawId"
    }
}

In my swift app using this framework everything works smoothly:

import geography

func setFields()
{
    var contactName:String = Contact.Fields.Name
    var countryPrefix:String = Country.Fields.Prefix
    var contactsTable: String  = Country.Table
}

Well, if I use the same Geography.framework in ObjectiveC, I see Contact and Country class but the nested classes Fields are not seen. Also the value of Contact.Table is not seen.

What I need to do in order to have same library structure and library usage in ObjectiveC?

Thank you,

like image 505
Colateral Avatar asked Aug 18 '15 06:08

Colateral


People also ask

Can we use Swift code in Objective-C?

You can work with types declared in Swift from within the Objective-C code in your project by importing an Xcode-generated header file. This file is an Objective-C header that declares the Swift interfaces in your target, and you can think of it as an umbrella header for your Swift code.

How do I reference a Swift class in Objective-C?

To access and use swift classes or libraries in objective-c files start with an objective-c project that already contains some files. Add a new Swift file to the project. In the menu select File>New>File… then select Swift File, instead of Cocoa Touch Class. Name the file and hit create.

Is it good practice to use nested classes?

Nested Class can be used whenever you want to create more than once instance of the class or whenever you want to make that type more available. Nested Class increases the encapsulations as well as it will lead to more readable and maintainable code.

Does nested classes increase encapsulation?

Nesting such "helper classes" makes their package more streamlined. It increases encapsulation: Consider two top-level classes, A and B, where B needs access to members of A that would otherwise be declared private . By hiding class B within class A, A's members can be declared private and B can access them.


2 Answers

You have to be explicit here with definition for ObjC.

public class Country: NSObject {

    @objc(CountryFields) public class Fields: NSObject {
        // ...
    }
}

This should expose your Switf's Country.Fields for your ObjC as CountryFields. I haven't tested it but I believe you don't have to be explicit about inheriting from NSObject. @objc attribute should do it for you when compiling.

Update for Swift 3:

Looks like this was broken in Swift 3 and won't be fixed. https://bugs.swift.org/browse/SR-2267?focusedCommentId=21033&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-21033

like image 101
Stanislav Smida Avatar answered Oct 07 '22 11:10

Stanislav Smida


You can use a trick with typealias to have the same syntax when using it :

public class Contact : NSObject
{
    public static let  Table: String = "contacts"

    typealias Fields = ContactFields
}

@objcMembers
public class ContactFields : NSObject
{
    public static let  Id: String = "_id"
    public static let  Name: String = "name"
    static let  rawId: String = "rawId"
}

public class Country : NSObject
{
    typealias Fields = CountryFields
}

@objcMembers
public class CountryFields : NSObject
{
    public static let  Id: String  = "_id"
    public static let  Prefix: String = "prefix"
    static let  rawId: String  = "rawId"
}
like image 40
Axel Guilmin Avatar answered Oct 07 '22 12:10

Axel Guilmin