当 Swift 中的扩展仅使用变量时,如下所示:
extension NSString {
var isNumber: Bool {
return length > 0 && rangeOfCharacter(from: CharacterSet.decimalDigits.inverted).location == NSNotFound
}
}
我可以使用非常友好的语法从 Objective-C 调用它:
NSString *str = @"twelve";
BOOL isNumber = str.isNumber;
但是,当扩展使用如下所示的函数时,我在语法上遇到了困难:
extension String {
func asImage(withAttributes attributes: [NSAttributedString.Key: Any]? = nil, size: CGSize? = nil) -> UIImage? {
let size = size ?? (self as NSString).size(attributes: attributes as! [String : Any])
if #available(iOS 10.0, *) {
return UIGraphicsImageRenderer(size: size).image { _ in
(self as NSString).draw(in: CGRect(origin: .zero, size: size),
withAttributes: attributes as! [String : Any])
}
} else {
// Fallback on earlier versions
return nil
}
}
这可以从 Swift 调用,只需:
var image = "Hello World".asImage()
但我不知道如何从 Objective-C 调用它。
事实上,autotype 甚至无法识别 str.asImage,当我尝试各种操作时,它会让我陷入错误的兔子洞并修复它,从而导致其他错误。
如何从 Objective-C 调用上述扩展?
最佳答案
如果 Swift 类、扩展或协议(protocol)可转换或用 @objc
显式标记,则只能用 Objective-C 表示。这意味着它要求所有参数都可转换为 Objective-C也是如此。
struct
也无法转换,因此我们只剩下类(即:类和具体类的扩展),并且要标记类 @objc
,它必须继承NSObject
。
示例:
@objc
extension NSString {
func asImage(withAttributes attributes: [NSAttributedString.Key: Any]? = nil, size: CGSize = .zero) -> UIImage? {
let size = size == .zero ? self.size(withAttributes: attributes!) : size
if #available(iOS 10.0, *) {
return UIGraphicsImageRenderer(size: size).image { _ in
self.draw(in: CGRect(origin: .zero, size: size),
withAttributes: attributes!)
}
} else {
// Fallback on earlier versions
return nil
}
}
}
请注意,我将 CGSize
参数更改为非可选,并与零进行比较。
另请注意,我将其标记为 @objc
并将其更改为 NSString
上的扩展,因为 String
本身无法转换为 Objective-C因为它是一个结构
!
然后在 Objective-C 中你可以这样调用它:
[str asImageWithAttributes:@{....} size:CGSizeZero];
或者任何你想要的参数..
关于ios - 调用字符串扩展,包括从 Objective-C 用 Swift 编写的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58423761/