验证可选工作的可选AFTER上的EXC_BAD_INSTRUCTION

时间:2017-05-12 05:57:54

标签: swift

我很困惑。下面我发生了以下情况。

enter image description here 如您所见,我在打开之前检查userOfProfile是否为nil。但后来我在我的控制台中得到了以下内容。

  

致命错误:在解包可选值时意外发现nil

错误后我的堆栈跟踪中也会出现以下内容:

0x10f67b538 <+72>: leaq   0x4d1e1(%rip), %r8        ; partial apply forwarder for Swift.(_fatalErrorMessage (Swift.StaticString, Swift.StaticString, file : Swift.StaticString, line : Swift.UInt, flags : Swift.UInt32) -> Swift.Never).(closure #2)
0x10f67b53f <+79>: movq   %r12, %rsi
0x10f67b542 <+82>: movq   %r13, %rdx
0x10f67b545 <+85>: movl   -0x2c(%rbp), %ecx
0x10f67b548 <+88>: movq   %rax, %r9
0x10f67b54b <+91>: callq  0x10f54de60               ; function signature specialization <preserving fragile attribute, Arg[1] = [Closure Propagated : reabstraction thunk helper from @callee_owned (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> () to @callee_owned (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> (@out ()), Argument Types : [@callee_owned (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> ()]> of generic specialization <preserving fragile attribute, ()> of Swift.StaticString.withUTF8Buffer <A> ((Swift.UnsafeBufferPointer<Swift.UInt8>) -> A) -> A 

任何关于该怎么做的想法都将受到赞赏。我很困惑。

var userOfProfile:User?

func loadProfile(_ user: User){
    self.userOfProfile = user

    if self.userOfProfile != nil{
        self.profileView.firstName = self.userOfProfile!.firstName
    }else{
        self.profileView.firstName = ""
    }
...
}


...
//Init for the user object that was passed in. 

let entityDescription = NSEntityDescription.entity(forEntityName: "User", in: self.managedObjectContext!)
let matchedUser = User(entity: entityDescription!, insertInto: nil)
matchedUser.parseRaw(matchDict)

...

class User: NSManagedObject {

    @NSManaged var userId: String
    @NSManaged var dbId: String
    @NSManaged var aboutMe: String
    @NSManaged var firstName: String
...

名字属性不是可选的。我甚至可以通过在控制台中执行po self.userOfProfile!.firstName打印出firstName的值,并且它可以解析正常...

看,在调试器中解析得很好,在下一行崩溃。有没有搞错。

enter image description here

如果任何其他代码有帮助,请告诉我。

更新:问题是profileView为nil,因此设置profileView.firstName会导致崩溃。

我不明白为什么profileView为零。新建profileView的代码如下所示:

//Event that causes all this
let newProfile = ProfileViewController()
newProfile.matchedUserProfile = true
newProfile.matchedReportDelegate = self
newProfile.loadProfile(self.selectedUser!)


//Within ProfileViewController
override func viewDidLoad() {
    super.viewDidLoad()

    profileView = ProfileView(frame: self.view.frame)
    self.view = profileView

在ProfileViewController的viewDidLoad中,创建了ProfileView。我已经跟踪了堆栈跟踪,并且在viewDidLoad之前调用了loadProfile。我该如何避免这种情况?我在代码中有许多其他位置,我执行此操作并且它不会崩溃(这几周之前并没有用于崩溃和我们的产品版本)

3 个答案:

答案 0 :(得分:2)

如果firstName的{​​{1}}属性是可选的,那么如果值为n并且您尝试强制解包该值,它将在运行时产生错误。所以,如果让我们构建安全解开,请使用。

userOfPrifile

<强>更新

我猜你的if let firstName = self.userOfProfile?.firstName { self.profileView.firstName = firstName } else { self.profileView.firstName = "" } 是零。请在运行时检查profileView

答案 1 :(得分:1)

首先检查nil,然后强制展开,你永远不应该展开选项。

使用条件绑定,这会检查并解开一个原子操作。:

if let user = self.userOfProfile {
    self.profileView.firstName = user.firstName
}
else {
    self.profileView.firstName = ""
}

在这种情况下,使用可选链接 nil coalescence operator 更简洁:

self.profileView.firstName = self.userOfProfile?.firstName ?? ""

答案 2 :(得分:0)

在你的代码中,似乎第一个名称在userProfile中声明为隐式可选:

 var firstName:String!

所以确保firstName在访问之前有价值,否则它会崩溃。

所以改为:

   var firstName:String?

并像这样访问:

   if self.userOfProfile != nil{
       self.profileView.firstName =  self.userOfProfile!.firstName ?? ""
   }