ios - 使用 swift NSObjects 和 JSON 的 EXC_BAD_INSTRUCTION

标签 ios swift alamofire

我正在学习 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

使用输出中检索到的 friend 的姓名设置friendLabel.text的方法是什么?

最佳答案

您在这里面临的问题是偏离 Xcode 将 IBOutlet 声明为隐式解包可选 (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 代码库中应用的原则,以防止 IUO 弄乱您的代码。

关于ios - 使用 swift NSObjects 和 JSON 的 EXC_BAD_INSTRUCTION,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33201041/

相关文章:

ios - UIBackgroundModes 不起作用的广告

ios - 为 Swift 二进制框架启用模块稳定性时 dyld 崩溃

ios - 如何在 Swift 和 Alamofire 中将对象映射到对象内部的数组中

swift - 在 alamofire 中发送对象数组

android - 适用于 Android 的类似 iOS 的抽屉导航?

ios - ios 7.1 上的 ibeacon - 应用程序在一段时间后停止收听信标

swift - 客户没有带 ID 的链接源

ios - AlamoFire 无线程警告

ios - 需要强制 Xcode 5 不使用通配符配置文件

ios - 将参数传递给 dispatch_async