代码之家  ›  专栏  ›  技术社区  ›  Valentin Nreca

无法强制展开非可选类型“AnyObject”的值

  •  -2
  • Valentin Nreca  · 技术社区  · 7 年前

    我已将iOS项目从swift 2转换而来。x到swift 3。x个 现在我的代码中有50多个错误。最常见的一种是“无法强制展开非可选类型‘AnyObject’的值”

    以下是代码的一部分:

    生产线 let documentURL = JSON[eachOne]["media"]!![eachMedia]["media_url"]! 正在产生错误

    如何解决此问题?非常感谢。

    if let JSON = response.result.value as? [[String: AnyObject]]{
        //print("JSON: \(JSON)")
        myDefaultValues.userDefaults.setValue(JSON, forKey: "JSON")
    
        for eachOne in 0 ..< (JSON as AnyObject).count{
            // print("Cover: \(JSON[eachOne]["cover"])")
    
            //Download all Covers
            let documentURL = JSON[eachOne]["cover"]!
            let pathus = URL(string: documentURL as! String)
    
            if pathus != nil {
                HttpDownloader.loadFileSync(pathus!, completion:{(path:String, error:NSError!) in
    
                })
            }
    
            //Download all Media Files
            if JSON[eachOne]["media"] != nil{
                //print(JSON[eachOne]["media"]!)
                //print(JSON[eachOne]["media"]!!.count)
    
                let thisMediaView = JSON[eachOne]["media"]!.count
    
                for eachMedia in 0 ..< thisMediaView!{
                    //print(JSON[eachOne]["media"]!![eachMedia]["media_url"])
                    **let documentURL = JSON[eachOne]["media"]!![eachMedia]["media_url"]!**
                    let pathus = URL(string: documentURL as! String)
    
    
                    if pathus != nil {
    
                        HttpDownloader.loadFileSync(pathus!, completion:{(path:String, error:NSError!) in
                        })
                    }
                }
            }
        }
    }
    
    2 回复  |  直到 7 年前
        1
  •  2
  •   Duncan C    7 年前

    作为一名初学Swift的程序员,您应该假装 ! 强制展开操作符不存在。我称之为“零崩溃”操作符。相反,您应该使用 if let guard let 可选绑定。您将JSON对象转换为字典数组,因此直接使用该数组:

    for anObject in JSON {
       guard let mediaArray = anObject["media"] as [[String: Any]] else 
       { 
         return
       }
       for aMediaObject in mediaArray {
         guard let aMediaDict = aMediaObject as? [String: Any],
           let documentURLString = aMediaDict["media_url"] as? String,
            let url = URL(string: documentURLString ) else 
         {
            return
         }
         //The code below is extracted from your question. It has multiple
         //issues, like using force-unwrap, and the fact that it appears to be
         //a synchronous network call?
         HttpDownloader.loadFileSync(pathus!, 
           completion:{(path:String, error:NSError!) in {
         }
       }
    }
    

    这段代码可能并不完美,但它应该会给你一个想法。

        2
  •  0
  •   Marcel    7 年前

    首先,代码中的以下行生成Int,而不是数组:

    let thisMediaView = JSON[eachOne]["media"]!.count
    

    第二,你可以强行展开你所有的价值观,但这会带来很大的风险。除非。。。不,等等,只是不要强行展开。

    这里的行对JSON中的值类型进行了大量假设,而没有实际检查。

    let documentURL = JSON[eachOne]["media"]!![eachMedia]["media_url"]!
    

    为了更安全、更富有表现力,请尝试按以下方式编写:

    if let value = JSON[eachOne] as? [String: Any],
       let anotherValue = JSON[value] as? [String: Any],
       ...etc,
       let documentURL = anotherValue["media_url"] as? String {
       // do something with the values
    } else {
       // handle unexpected value or ignore
    }