2015-10-18 41 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

好,很好。它是否与将它们声明为常规可选项一起使用,还是将它们作为隐含的解包选项? –

相关问题