EXC_BAD_INSTRUCTION using swift NSObjects and JSON



我正在学习Swift 2.0,使用Alamofire和Xcode 7开发IOS 9应用程序。我正在开发一个使用社交网络模型的例子。

友情类文件为:

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
  }  
}

FriendShip类有两个引用user类的属性(user,friend):

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)
      }     
    }
  }

, print(hits)的输出是:

[
["_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]
]  

最后是管理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!)
    }
  }
}

当我执行应用程序时,编译器崩溃成FriendTableViewCell类

friendLabel.text = friendObject?.friend.name

,错误是

Thread 1:EXC_BAD_INSTRUCTION

是设置friendLabel的方式。在输出中检索到的带有朋友名称的文本?

你在这里面临的问题是偏离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!)
    }
}

这是一个你可以(而且可能应该)在你的swift代码库中应用的原则,以防止IUOs弄乱你的代码。

最新更新