2015-10-18 18 views
0

Im學習Swift 2.0開發一個使用Alamofire和Xcode 7的IOS 9應用程序。我使用社交網絡模型的一個示例進行開發。使用swift NSObjects和JSON的EXC_BAD_INSTRUCTION

友誼類文件是:

class FriendShip: NSObject{ 

    var id: String! 
    var userId: String! 
    var user: User! 
    var friendId: String! 
    var friend: User! 
    var date: NSDate! 

    init(dictionary: [String: AnyObject]){  
    id  = dictionary["id"] as? String 
    userId = dictionary["userId"] as? String 
    user  = dictionary["user"] as? User 
    friendId = dictionary["friendId"] as? String 
    friend = dictionary["friend"] as? User 
    date  = dictionary["date"] as? NSDate 

    } 
} 

的友誼類具有兩個屬性(用戶,朋友),它引用類用戶:

class User: NSObject{ 

    var id: String! 
    var name: String! 
    var birthDate: NSDate! 
    var email: String! 
    var gender: String! 
    var profileImageUrl: String! 

    init(dictionary: [String: AnyObject]){ 
    id    = dictionary["id"] as? String 
    name   = dictionary["name"] as? String 
    birthDate  = dictionary["birthDate"] as? NSDate 
    email   = dictionary["email"] as? String 
    gender   = dictionary["gender"] as? String 
    profileImageUrl = dictionary["profileImageUrl"] as? String  
    } 
} 

現在,它調用的API函數如下以JSON格式檢索朋友列表:

func GetFriends(completionHandler: ([FriendShip]?, NSError?) ->()) { 
    Alamofire.request(Router.GetFriends(Test().getUserId())).responseJSON { (_, _, result) in 
     var friends = [FriendShip]() 
     switch result { 
     case .Success(let json): 
      if let responseObject = json as? [String: AnyObject], let hits = responseObject["hits"] as? [[String: AnyObject]] { 
      for dictionary in hits { 
     print(hits) 
       friends.append(FriendShip(dictionary: dictionary)) 
      } 
      completionHandler(friends, nil) 
      } 
     case .Failure(_, let error): 
      completionHandler(nil, error as NSError) 
     }  
    } 
    } 

並且打印(命中)的輸出是:

[ 
["_id": 546a6ef98e6df9703226, "friend": { 
    "_id" = 546a4b3e1f8d2c2630dd; 
    name = "Daniela"; 
    profileImageUrl = "https://www.api-static/profile/546a4b3e1f8d2c2630d.1.jpg"; 
    statusTxt = ""; 
}, "userId": 546a4b651f8d2c2630d, "__v": 0, "created": 2014-11-17T21:56:09.121Z, "user": 546a4b651f8d2c2630d, "friendId": 546a4b3e1f8d2c2630d], 

["_id": 546a6f988e6df9703226, "friend": { 
    "_id" = 546a4ba51f8d2c2630d 
    name = "Mara"; 
    profileImageUrl = "https://www.api-static/profile/546a4ba51f8d2c2630d.1.jpg"; 
    statusTxt = undefined; 
}, "userId": 546a4b651f8d2c2630d, "__v": 0, "created": 2014-11-17T21:58:48.045Z, "user": 546a4b651f8d2c2630d, "friendId": 546a4ba51f8d2c2630d], 

["_id": 546a70a18e6df970322, "friend": { 
    "_id" = 546a4bd61f8d2c2630d; 
    name = "Alejandro"; 
    profileImageUrl = "https://www.api-static/profile/546a4bd61f8d2c2631.jpg"; 
    statusTxt = ""; 
}, "userId": 546a4b651f8d2c2630, "__v": 0, "created": 2014-11-17T22:03:13.817Z, "user": 546a4b651f8d2c2630, "friendId": 546a4bd61f8d2c2630d], 

["_id": 546a715d8e6df970322, "friend": { 
    "_id" = 546a4be01f8d2c2630d; 
    name = "Pedro"; 
    profileImageUrl = "https://www.api-static/profile/546a4be01f8d2c2630dd1.jpg"; 
}, "userId": 546a4b651f8d2c263, "__v": 0, "created": 2014-11-17T22:06:21.806Z, "user": 546a4b651f8d2c2630, "friendId": 546a4be01f8d2c2630d] 
] 

最後,當我執行應用程序的編譯器崩潰到FriendTableViewCell類

friendLabel.text = friendObject?.friend.name 

,誤差

其管理的TableViewCell

class FriendTableViewCell: UITableViewCell { 

     @IBOutlet var friendLabel:UILabel! 
     @IBOutlet var friendImageView:UIImageView! 

     var friendObject:FriendShip? { 
     didSet{ 
      self.setupMainObject() 
     } 
     } 

     func setupMainObject() { 
     friendLabel.text = friendObject?.friend.name 
     if let urlString = self.friendObject?.friend.profileImageUrl{ 
      let url = NSURL(string: urlString) 
      friendImageView.hnk_setImageFromURL(url!) 
     } 
     } 
    } 

內容類

Thread 1:EXC_BAD_INSTRUCTION 

哪種方法可以將friendLabel.text設置爲在輸出中檢索到的朋友的名字?

+0

不,編譯器不會崩潰。這將是編譯器中的錯誤。你的應用程序崩潰。和類似var userId:String!意思是「如果有人試圖指定一個可選的零,請崩潰」。 – gnasher729

回答

0

您在這裏遇到的問題是偏離xcode默認行爲將IBOutlets聲明爲隱式解包選項(IUO)的主要動機之一。

相反,如果我們將它們聲明爲常規選項,那麼您在這裏面臨的問題就會被完全消除,而不是被迫去思考它們何時被初始化等等。

因此,改變這種:

@IBOutlet var friendLabel:UILabel! 
@IBOutlet var friendImageView:UIImageView! 

要這樣:

@IBOutlet var friendLabel:UILabel? 
@IBOutlet var friendImageView:UIImageView? 

而在你的代碼,只需添加?在IBOutlet中的名字後:

func setupMainObject() { 
    friendLabel?.text = friendObject?.friend.name 
    if let urlString = self.friendObject?.friend.profileImageUrl{ 
     let url = NSURL(string: urlString) 
     friendImageView?.hnk_setImageFromURL(url!) 
    } 
} 

這是你可以(並且可能應該)在你的代碼庫迅速應用到保持安全距離IUOs搞亂你的代碼的原則。

+0

對不起丹尼,如果我們將它們聲明爲常規選項,那麼現在在我的代碼中,問題仍然存在 – Edu

+0

,如果我更改** friendLabel.text = friendObject?.friend.name ** by ** friendLabel.text = friendObject?.friend .userId **該應用程序的作品和單元格顯示userId完美 – Edu

+0

好,很好。它是否與將它們聲明爲常規可選項一起使用,還是將它們作爲隱含的解包選項? –

相關問題