Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to extend an Objective-C class with Swift in a framework?

Tags:

I have an (OS X) Objective-C framework to which I want to add some Swift extensions and I'm using Xcode 7ß6 to work with this. There is class in the framework (let's call it "Sample") implemented in the files "Sample.h" and "Sample.m" .. "Sample.h" contains:

#import <Foundation/Foundation.h>
@interface Sample : NSObject
@property   int     x;
@end

.. and "Sample.m" contains:

#import "Sample.h"

@implementation Sample
- (instancetype) init {
    if ((self = [super init]) == nil) return nil;
    self.x = 99;
    return self;
}
@end

I have added "Sample.swift" to the framework containing:

import Foundation

extension Sample {
    func PrettyPrint () {    
        print("\(x)")
    }
}

This is clearly a trivial version of what I want to do in a larger context, here I want to use the Swift file to extend "Sample" by adding a "PrettyPrint" function.

.. the framework builds without error, but the framework function "PrettyPrint" is not visible to a calling app. App code calling into the framework like:

import Foundation
import TestKit

let  sample = Sample()
sample.PrettyPrint()

fails on "sample.PrettyPrint()" with: Value of type 'Sample' has no member 'PrettyPrint'

Why does this fail? and Can it be made to work?

Extra info: If I remove the file "Sample.swift" from the framework and place it the app which is calling into the framework, the "Sample" class is successfully extended and "sample.PrettyPrint()" works as expected (printing "99").

like image 846
Ramsay Consulting Avatar asked Sep 08 '15 22:09

Ramsay Consulting


People also ask

Can I use Swift extension in Objective-C?

You can write a Swift extension and use it in Objective-C code.

How do I add Swift to Objective-C project?

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.

How do you extend a class in Objective-C?

The methods declared by a class extension are implemented in the implementation block for the original class, so you can't, for example, declare a class extension on a framework class, such as a Cocoa or Cocoa Touch class like NSString. Extensions are actually categories without the category name.


2 Answers

Have you tried making the extension and function public?

public extension Sample {
    public func PrettyPrint () {    
        print("\(x)")
    }
}
like image 143
tie Avatar answered Sep 25 '22 10:09

tie


In a similar case, Tie's answer really helped me but it didn't work for me, I had to add @objc for the method:

public extension SearchBarWidget {
    @objc public func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
        self.endEditing(true)
    }
}

The SearchBarWidget class was @objc public signatured.

like image 34
Newsonic Avatar answered Sep 26 '22 10:09

Newsonic