如何在目标C文件中访问Swift公共功能? [英] How to access swift public function in objective c files?
问题描述
我正在使用如下所示的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
–因为Int
和String
可以自由地桥接到NSNumber
和
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屋!