EXC_BAD_INSTRUCTION使用swift NSObjects和JSON

时间:2015-10-18 17:32:46

标签: ios swift alamofire

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

友谊类文件是:

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,friend),它引用了User:

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(命中)的输出是:

[
["_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.text的方法是什么?

1 个答案:

答案 0 :(得分: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!)
    }
}

这是一个原则,您可以(并且可能应该)应用于整个快速代码库,以防止IUO破坏您的代码。