将objective-c代码转换为swift 4

Posted

技术标签:

【中文标题】将objective-c代码转换为swift 4【英文标题】:Converting objective-c codes to swift 4 【发布时间】:2017-11-07 08:15:20 【问题描述】:

我已经用obj-c 写了 1.5 年了,它是一种很好的语言.. 所以我今天看到一篇关于 swift 的中型文章,真的很关注它,现在我正在尝试转换我所有的obj-c代码swift,幸运的是,这部分的一切都完成了..

NSString *path = [[NSBundle mainBundle] pathForResource:@"list" ofType:@"plist"];
    NSArray *plistData = [NSArray arrayWithContentsOfFile:path];

    NSPredicate *filter = [NSPredicate predicateWithFormat:@"english ==[c] %@", self.userQuery.text]; // something like "Abbey"
    NSArray *filtered = [plistData filteredArrayUsingPredicate:filter];



    NSLog(@"found matches: %@ : %@", filtered,[filtered valueForKey:@"kurdi"]);

    if (filtered.count>0) 
        NSDictionary *dic  = filtered[0];
        self.theMeaningLabel.text = dic[@"kurdi"];


     else 
         self.theMeaningLabel.text = @"Yay!‌";
    

我无法将其正确转换为新的swift 4,它会产生随机错误

编辑

经过几次搜索,我可以只写两行代码 这是我的快速代码

    var path: String? = Bundle.main.path(forResource: "list", ofType: "plist")
    var plistData = [Any](contentsOfFile: path!)
    var filter = NSPredicate(format: "english ==[c] %@", searchText)
    // something like "Abbey"
    var filtered = plistData?.filter  filter.evaluate(with: $0) 
    print("found matches: \(filtered) : \(filtered?.value(forKey: "kurdi"))")
    if filtered?.count > 0 
        var dic = filtered[0]
       // theMeaningLabel.text = dic["kurdi"]
    
    else 
        //theMeaningLabel.text = "Yay!‌"
    

但得到

参数标签 '(contentsOfFile:)' 不匹配任何可用的重载

最终编辑

 var path = Bundle.main.path(forResource:"list", ofType: "plist")
var plistData = NSArray(contentsOfFile: path!)

let filter = NSPredicate(format: "english ==[c] %@", searchText)
var filtered = plistData?.filtered(using: filter)
// [error 9:10] no viable alternative at input 'NSLog(@"found matches: %@ : %@"'
if filtered?.count > 0 
    var dic = filtered![0]
   // theMeaningLabel.text = dic["kurdi"]

else 
   // theMeaningLabel.text = "Yay!‌"

上面的代码没问题,但是出现了一个错误

if filtered?.count > 0  // here
    var dic = filtered![0]
   // theMeaningLabel.text = dic["kurdi"]

else 
   // theMeaningLabel.text = "Yay!‌"

得到

二元运算符“>”不能应用于“Int?”类型的操作数和“诠释”

【问题讨论】:

不要显示 Objective-C,显示 Swift 和你遇到的错误。 @Paulw11,我实在想不通,卡在谓词格式中,等待有人给出正确的干净代码 谓词格式完全相同,因为它是基础库的一部分,而不是 Swift 或 Objective-C。 How to use native Swift way to Read Plist in Swift 3?的可能重复 @VishalPatel,不要在没有真正阅读双方的情况下标记问题,你给出了错误的代码,我很感激,但这不是重复的,我自己解决了! 【参考方案1】:

不推荐从 Objective-C 到 Swift 的直译,因为在许多情况下它没有利用 Swift 改进的语义。

由于 Apple 从 String 中删除了所有路径操作 API,并向其他类添加了更多与 URL 相关的 API,因此如果可能,请始终使用 URL

let url = Bundle.main.url(forResource: "list", withExtension: "plist")!

强制解包的 url 是安全的,因为文件必须在包中。崩溃将揭示设计错误,并且不得在运行时发生。


与 Foundation 集合类型不同,Swift 集合类型不支持隐式属性列表转换,因此 Swift 方法是使用 DataPropertyListSerialization

let data = try! Data(contentsOf: url)
let dataArray = try! PropertyListSerialization.propertyList(from: data, format: nil) as! [Any]

出于同样的原因,强制try! 与强制解包url 一样安全。

[Any] 是最未指定的 Swift 数组。如果该数组应该是一个字典数组,则写入[[String:Any]],如果所有值都是String,则甚至写入[[String: String]]。如果它应该是一个字符串数组,请写[String]。 Swift 鼓励开发人员尽可能地指定类型。


NSPredicate 可以替换为 Swift 中的 filter 函数。例如,可以使用

过滤不区分大小写的字符串数组
let filtered = dataArray.filter  $0.compare(searchText, options:.caseInsensitive) == .orderedSame 

如果数组包含字典,则需要指定键(同NSPredicate)

let filtered = dataArray.filter  ($0["foo"] as! String).compare(searchText, options:.caseInsensitive) == .orderedSame 

最后是 ObjC 表达式

 if (filtered.count > 0)  ...

在 Swift 中可以写得更具描述性

 if filtered.isEmpty == false  ...

 if !filtered.isEmpty  ...

如果你只寻找一个项目,你甚至可以写

if let foundObject = dataArray.first(where:  $0.compare(searchText, options:.caseInsensitive) == .orderedSame )  ...

【讨论】:

上次我遇到了 obj-c 的问题,你帮忙了,再说一次,sof 需要更多像你这样的人

以上是关于将objective-c代码转换为swift 4的主要内容,如果未能解决你的问题,请参考以下文章

将 PinchRecognizer Objective-C 代码转换为 Swift

将 NSData Objective-C 代码转换为 Swift 时遇到问题

将代码从 Objective-C 转换为 Swift 后测试用例失败

将 Objective-C 方法转换为 Swift [关闭]

将objective-c块转换为Swift闭包

将 Objective-C malloc 转换为 Swift