Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/107.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 访问字典数组Swift 3_Ios_Swift_Facebook Graph Api_Facebook Sdk 4.0 - Fatal编程技术网

Ios 访问字典数组Swift 3

Ios 访问字典数组Swift 3,ios,swift,facebook-graph-api,facebook-sdk-4.0,Ios,Swift,Facebook Graph Api,Facebook Sdk 4.0,我需要访问字典数组中的工作数据,对此我有点困惑。我用的是swift 3。有人能给我一些代码来完成吗 我在用这个 let work: NSArray! = fbData.value(forKey: "work") as! NSArray if let position: NSArray = work[0] as! NSArray { let positionName: String = position.value(forKey: "name

我需要访问字典数组中的工作数据,对此我有点困惑。我用的是swift 3。有人能给我一些代码来完成吗

我在用这个

let work: NSArray! = fbData.value(forKey: "work") as! NSArray
            if let position: NSArray = work[0] as! NSArray {
                let positionName: String = position.value(forKey: "name") as! String
                self.userWorkExpLabel.text = "\(positionName)" as String
            }
但我有一个答案: 无法将类型为“\uuu NSDictionaryI”0x1106c7288的值强制转换为“NSArray”0x1106c6e28

这是API

{
"work": [
{
  "employer": {
    "id": "93643283467",
    "name": "Oracast"
  },
  "location": {
    "id": "111983945494775",
    "name": "Calgary, Alberta"
  },
  "position": {
    "id": "146883511988628",
    "name": "Mobile Developer"
  },
  "start_date": "2017-04-30",
  "id": "1446626725564198"
}
],
好的,伙计们。我尝试了你发布的内容,现在我得到的是这样的:

struct Worker {
    let employer:Employer
    let location:Location
    let position:Position
    let startDate:String
    let id:String

    init?(fromDict dict:Dictionary<String, Any>) {
        guard let employer = Employer(fromDict: dict["employer"] as? Dictionary<String, String>), let location = Location(fromDict: dict["location"] as? Dictionary<String, String>), let position = Position(fromDict: dict["position"] as? Dictionary<String, String>), let startDate = dict["start_date"] as? String, let id = dict["id"] as? String else {
            return nil
        }

        self.employer = employer
        self.location = location
        self.position = position
        self.startDate = startDate
        self.id = id
    }
}

struct Employer {
    let id:String
    let name:String

    init?(fromDict dict:Dictionary<String, String>?) {
        guard let id = dict?["id"], let name = dict?["name"] else {
            return nil
        }
        self.id = id
        self.name = name
    }
}

struct Location {
    let id:String
    let name:String

    init?(fromDict dict:Dictionary<String, String>?) {
        guard let id = dict?["id"], let name = dict?["name"] else {
            return nil
        }
        self.id = id
        self.name = name
    }
}

struct Position {
    let id:String
    let name:String

    init?(fromDict dict:Dictionary<String, String>?) {
        guard let id = dict?["id"], let name = dict?["name"] else {
            return nil
        }
        self.id = id
        self.name = name
    }
}
func workersArray(data:Dictionary<String, Any>)->[Worker]?{
        guard let arrayOfDict = data["work"] as? Array<Dictionary<String, Any>> else {
            return nil
        }

        return arrayOfDict.flatMap({ Worker(fromDict: $0)})
    }
结构类:

import Foundation

struct Worker{
let employer: Employer
let location: Location
let position: Position
let startDate:String
let id: String

init?(fromDict dict: Dictionary<String, Any>){
    guard let employer = Employer(fromDict: dict["employer"] as? Dictionary<String, String>),
        let location = Location(fromDict: dict["location"] as? Dictionary<String, String>),
        let position = Position(fromDict: dict["position"] as? Dictionary<String, String>),
        let startDate = dict["start_date"] as? String,
        let id = dict["id"] as? String else {
            return nil
    }

    self.employer = employer
    self.location = location
    self.position = position
    self.startDate = startDate
    self.id = id
}

}

struct Employer{
let id: String
let name: String

init?(fromDict dict:Dictionary<String, String>?){
    guard let id = dict?["id"],
        let name = dict?["name"] else{
            return nil
    }

    self.id = id
    self.name = name
 }
 }

struct Location {
let id:String
let name:String

init?(fromDict dict:Dictionary<String, String>?) {
    guard let id = dict?["id"],
        let name = dict?["name"] else {
        return nil
    }
    self.id = id
    self.name = name
}
}

struct Position {
let id:String
let name:String

init?(fromDict dict:Dictionary<String, String>?) {
    guard let id = dict?["id"],
        let name = dict?["name"] else {
        return nil
    }
    self.id = id
    self.name = name
}
} 
有人知道发生了什么?标签没有任何问题

我认为这个API比那个简单。我真的对这个过程感到困惑。。。很抱歉,如果这看起来像是愚蠢的问题,但我真的因为这些事情弄糊涂了。。。我真的需要你们的帮助。我的工作取决于此:

使用此代码

if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] {
    if let workArray = json["work"] as? [[String: Any]] {
        if let dictWork = workArray.first {
            if let dictPosition = dictWork["position"] as?  [String: String] {
                print("position name : \(dictPosition["name"])")
            }
        }
    }
}

理想情况下,您应该引入如下模型类:

struct Worker {
    let employer:Employer
    let location:Location
    let position:Position
    let startDate:String
    let id:String

    init?(fromDict dict:Dictionary<String, Any>) {
        guard let employer = Employer(fromDict: dict["employer"] as? Dictionary<String, String>), let location = Location(fromDict: dict["location"] as? Dictionary<String, String>), let position = Position(fromDict: dict["position"] as? Dictionary<String, String>), let startDate = dict["start_date"] as? String, let id = dict["id"] as? String else {
            return nil
        }

        self.employer = employer
        self.location = location
        self.position = position
        self.startDate = startDate
        self.id = id
    }
}

struct Employer {
    let id:String
    let name:String

    init?(fromDict dict:Dictionary<String, String>?) {
        guard let id = dict?["id"], let name = dict?["name"] else {
            return nil
        }
        self.id = id
        self.name = name
    }
}

struct Location {
    let id:String
    let name:String

    init?(fromDict dict:Dictionary<String, String>?) {
        guard let id = dict?["id"], let name = dict?["name"] else {
            return nil
        }
        self.id = id
        self.name = name
    }
}

struct Position {
    let id:String
    let name:String

    init?(fromDict dict:Dictionary<String, String>?) {
        guard let id = dict?["id"], let name = dict?["name"] else {
            return nil
        }
        self.id = id
        self.name = name
    }
}
func workersArray(data:Dictionary<String, Any>)->[Worker]?{
        guard let arrayOfDict = data["work"] as? Array<Dictionary<String, Any>> else {
            return nil
        }

        return arrayOfDict.flatMap({ Worker(fromDict: $0)})
    }
现在,您可以引入如下函数:

struct Worker {
    let employer:Employer
    let location:Location
    let position:Position
    let startDate:String
    let id:String

    init?(fromDict dict:Dictionary<String, Any>) {
        guard let employer = Employer(fromDict: dict["employer"] as? Dictionary<String, String>), let location = Location(fromDict: dict["location"] as? Dictionary<String, String>), let position = Position(fromDict: dict["position"] as? Dictionary<String, String>), let startDate = dict["start_date"] as? String, let id = dict["id"] as? String else {
            return nil
        }

        self.employer = employer
        self.location = location
        self.position = position
        self.startDate = startDate
        self.id = id
    }
}

struct Employer {
    let id:String
    let name:String

    init?(fromDict dict:Dictionary<String, String>?) {
        guard let id = dict?["id"], let name = dict?["name"] else {
            return nil
        }
        self.id = id
        self.name = name
    }
}

struct Location {
    let id:String
    let name:String

    init?(fromDict dict:Dictionary<String, String>?) {
        guard let id = dict?["id"], let name = dict?["name"] else {
            return nil
        }
        self.id = id
        self.name = name
    }
}

struct Position {
    let id:String
    let name:String

    init?(fromDict dict:Dictionary<String, String>?) {
        guard let id = dict?["id"], let name = dict?["name"] else {
            return nil
        }
        self.id = id
        self.name = name
    }
}
func workersArray(data:Dictionary<String, Any>)->[Worker]?{
        guard let arrayOfDict = data["work"] as? Array<Dictionary<String, Any>> else {
            return nil
        }

        return arrayOfDict.flatMap({ Worker(fromDict: $0)})
    }

在试验了Swift 4并按照@PuneetSharma演示的方向进行之后,我发现使用原始JSON文本、可编码和JSONDecoder更容易:

结果是一个包含所有数据的工作结构:

Work(work: [
  Model.Worker(employer : Model.Employer(id  : "93643283467",
                                         name: "Oracast"),
               location : Model.Location(id  : "111983945494775",
                                         name: "Calgary, Alberta"),
               position : Model.Position(id  : "146883511988628",
                                         name: "Mobile Developer"),
               startDate: "2017-04-30", 
               id       : "1446626725564198")
])
我对输出进行了一些格式化,以澄清生成的结构


通过使用Codable,您可以免费获得很多功能。另外,从任何结构生成JSON文本也很简单。

首先,不要在Swift中使用NSArray或NSDictionary,除非确实需要。其次,您有一个字典数组,因此工作[0]是一个字典,而不是数组,这就是强制向下转换失败的原因。它给出了一个错误:无法转换类型为“,”的值,,_向FBSDKGraphRequestHandler类型的预期参数抛出->。如果有大量嵌套的If-let语句,只需使用逗号分隔它们而不是嵌套它们,就可以使其更简单。看起来很干净。我唯一要添加的是类似于enum EmployerKey:String{case id,name}的东西,因此有具体的字符串来匹配字典键。像dict一样使用它们?[EmployerKey.name.rawValue]@ColGraff:我同意,这将以一种很好的方式将硬编码字符串包装到枚举中。谢谢你的建议。@ColGraff:嵌套枚举是应该做的。随着可编码和可解码协议的迅速引入,序列化再次变得有趣:。OP已经接受了另一个答案,所以我不会编辑这个答案,但我肯定会在我的项目中使用嵌套枚举。事实上,我完全忘记了声明为Codable的结构会自动在CodingKeys下获得键。因此,跳过枚举,只需使用struct Employer:Codable{…},然后就可以进行CodingKeys.name。stringValue@ColGraff:是的,但您可能希望提供自定义键和嵌套枚举: