如何在目标C文件中访问Swift公共功能? [英] How to access swift public function in objective c files?

查看:58
本文介绍了如何在目标C文件中访问Swift公共功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用如下所示的public方法将API数据类型转换为Int.

I am using the public method as below to convert the API data type into Int.

public func convertToInt( value : Any) -> Int{
    if let v = value as? String {
        if let myNumber = NSNumberFormatter().numberFromString(v) {
            return myNumber.integerValue
        } else {
            print ("Cannot convert to Int...")
        }
    } else  if let v = value as? Int {
        return v
    } else  if let v = value as? NSNumber {
        return v.integerValue
    }
    return 0
}

我在项目中同时使用了swift和目标c文件.我也想将此功能访问到目标c文件中.如果有人知道解决方案,请帮助我.

I am using both swift and objective c files in my project. I Want to access this function into objective c file also. If anyone know the solution please help me.

推荐答案

问题在于全局Swift功能不适用于Objective-C ,并且协议Any不能在Objective-C中表示.

The problem is both that global Swift functions are unavailable to Objective-C, and the protocol Any cannot be represented in Objective-C.

因此,一种潜在的解决方案是将函数封装在帮助器类中,并在value参数中使用AnyObject –因为IntString可以自由地桥接到NSNumber,因此在导入Foundation时可以将其视为对象.

Therefore, one potential solution is to encapsulate your function in a helper class, and to use AnyObject for your value argument – as Int and String can be freely bridged to NSNumber and NSString respectively, and thus can be treated as objects when Foundation is imported.

@objc final class HelperFunctions : NSObject {

    static func convertToInt(value : AnyObject) -> Int {
        if let v = value as? String {
            if let myNumber = NSNumberFormatter().numberFromString(v) {
                return myNumber.integerValue
            } else {
                print ("Cannot convert to Int...")
            }
        } else  if let v = value as? Int {
            print("int")
            return v
        } 

        // note that this check is completely redundant as NSNumber is freely bridgable
        // to Int – therefore the 'as? Int' check will always get triggered instead
        else if let v = value as? NSNumber { 
            print("nsnum")
            return v.integerValue
        }
        return 0
    }
}

尽管如此,这确实不是Swifty代码. NSNumber可桥接到Int,因此您已经可以直接将其转换:

Although that being said, this really isn't very Swifty code. NSNumber is bridgeable to Int, so you can already convert it directly:

let n = NSNumber(integer: 5)
let i = n as Int // 5

并且Int已经具有可以使用字符串的初始化程序:

And Int already has an initialiser that can take a string:

let i = Int("55") // Optional(55)

因此,我真的看不到此函数正在解决什么Swift问题.尽管我确实看到了它正在解决的Objective-C问题,但出于这个原因,我只是将这个函数实现为Objective-C文件中的C函数.

So, I don't really see what Swift problem this function is solving. Although I do see the Objective-C problem that it's solving, and for that reason I would simply implement this function as a C function in an Objective-C file.

extern NSInteger convertToInt(id _Nonnull value);

inline NSInteger convertToInt(id _Nonnull value) {

    if ([value isKindOfClass:[NSString class]]) {
        NSNumberFormatter* f = [[NSNumberFormatter alloc] init];
        return [f numberFromString:(NSString*)value].integerValue;
    } else if ([value isKindOfClass:[NSNumber class]]) {
        return ((NSNumber*)value).integerValue;
    }

    return 0;
}

如果确实需要,可以始终将其导入回Swift中,然后它将作为全局函数可用.但是我建议您不要将此导入到Swift中,而应该找到更快速的解决方案来解决您的问题.

You can always import this back into Swift if you really want – and then it'll be available as a global function. But I would recommend that you don't import this back to Swift, and instead find a more Swifty solution to your problem.

例如,我建议您使用协议和扩展在Swift中实现.您可以定义IntRepresentable协议,以表示可以转换为Int的类型.这样做的好处是,您对可以转换为Int的类型很明确,而不是让它成为便利功能的实现细节.

For example, I would recommend that you implement this in Swift using protocols and extensions. You can define an IntRepresentable protocol in order to represent types that can be converted to Int. The advantage of doing this is that you're being explicit about the types that you can convert to Int, rather than letting it be an implementation detail of your convenience function.

protocol IntRepresentable {
    func _asInt() -> Int?
}

现在,您可以扩展字典可能包含的类型,并使它们符合IntRepresentable.

Now you can extend the types that your dictionary could contain and make them conform to IntRepresentable.

extension NSString : IntRepresentable {
    func _asInt() -> Int? {return Int(self as String)}
}

extension NSNumber : IntRepresentable {
    func _asInt() -> Int? {return self.integerValue}
}

// not really necessary, as your dict will be [Whatever:AnyObject],
// so the NSString extension will be used – here for completeness
extension String : IntRepresentable {
    func _asInt() -> Int? {return Int(self)}
}

extension Int : IntRepresentable {

    func _asInt() -> Int? {return self}

    init?(representable:IntRepresentable) {
        guard let i = representable._asInt() else {return nil}
        self = i
    }
}

现在,您可以通过执行以下操作将字典从[Whatever:AnyObject]转换为[Whatever:Int]:

Now you can convert your dictionary from [Whatever:AnyObject] to [Whatever:Int] by doing the following:

let inputDict = ["foo":"5", "bar":6, "baz":NSNumber(int:5)]

var outputDict = [String:Int]()
for (key, value) in inputDict {
    if let value = value as? IntRepresentable {
        outputDict[key] = Int(representable: value)
    }
}

print(outputDict) // ["baz": 5, "foo": 5, "bar": 6]

尽管我仍然反对使用全局功能,但是如果您感觉更好,则可以始终将其保留在便利功能中.您可以使用无大小写的枚举,以避免污染全局名称空间:

You can always stick this in a convenience function if it makes you feel better, although I would still advocate against global functions. You can use a caseless enum in order to avoid polluting the global namespace:

enum DictionaryConversion {

    static func toIntValues<Key>(dict:[Key:NSObject]) -> [Key:Int] {
        var outputDict = [Key:Int]()
        for (key, value) in dict {
            if let value = value as? IntRepresentable {
                outputDict[key] = Int(representable: value)
            }
        }
        return outputDict
    }
}

或者只是扩展Dictionary本身:

extension Dictionary {

    func convertValuesToInt() -> [Key:Int] {
        var outputDict = [Key:Int]()
        for (key, value) in self {
            if let value = value as? IntRepresentable {
                outputDict[key] = Int(representable: value)
            }
        }
        return outputDict
    }
}

let outputDict = DictionaryConversion.toIntValues(inputDict)

let outputDict = inputDict.convertValuesToInt()

这篇关于如何在目标C文件中访问Swift公共功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆