设置实例变量时,`top_level_code`中的访问不良

时间:2015-02-03 23:15:03

标签: swift exc-bad-access

好的,这是一个奇怪的错误,我花了很多时间来追踪确切的位置(虽然原因仍然未知)。错误在64位设备上发生。换句话说,它在我的iPhone 5上工作正常,但在我的iPhone 6 Plus上崩溃。

基本上,我在一个类中有一个私有变量:

class Manager {
   private lastUpdated:NSDate?
}

最初,它没有设置。此类从服务器检索消息,然后将lastUpdated变量设置为NSDate()

  private func checkForNewMessages(complete:Result<[Message]> -> ()) {
      self.server.userMessages(u, fromDate: self.lastUpdated) { result in
        result.onSuccess { messages in
          self.insertMessages(messages)
          self.lastUpdated = NSDate()
          complete(Result(messages))
        }
        result.onError { err in complete(Result(err)) }
      }
  }

我删除了无关的代码,但代码路径中没有任何内容崩溃(只是它周围的东西)

注意:我使用Result枚举。有关此类枚举的更多信息,本文非常擅长解释它:Error Handling in Swift

管理员第一次检索邮件时,一切正常,lastUpdated值设置正确。如果我再次尝试检索邮件,则应用在尝试设置self.lastUpdated = NSDate()时会崩溃。

如果我使用GCD dispatch_after延迟分配,可以让它工作。但我不想这样做。

有谁知道为什么会这样?

更新

  • 仅当我分配NSDate时才会发生这种情况。如果我尝试设置其他对象类型(IntBoolString)等,则不会发生此事。
  • 如果我将存储的变量更改为NSTimeInterval并尝试从NSDate.timeIntervalSinceReferenceDate()
  • 设置,则会发生崩溃
  • 如果我存储更新数组并尝试简单地向该数组添加新日期,则会发生崩溃。
  • 如果我在调用服务器之前尝试设置lastUpdated 而不是在回调中,则会发生崩溃。
  • 如果我将NSDate包装在另一个类中,则会发生崩溃。
  • 发生崩溃是我在后台线程中设置lastUpdated
  • 如果我println(NSDate())(删除作业)
  • ,则不会发生崩溃

1 个答案:

答案 0 :(得分:0)

好的,我花了很多时间,但我终于明白了。

这有点难以解释,我不确定我完全理解发生了什么。该错误实际发生在发出请求的Server类中。它花了lastUpdated日期,将其转换为字符串,然后将其发送到服务器。第一次运行,没有日期,所以没有问题。在第二次运行中,它花了日期并使用日期格式化程序将其转换为字符串。但是,我认为stringFromDate返回了一个Optional。它不是。通常,编译器会警告我,如果我试图解开一些不是一个选项的东西。但是,我使用Swift的功能方面来使用Infix操作符来解包并有条件地将未包装的值传递给另一个函数,然后可以传递它的值。它允许我将unwraps链接在一起,这样我就可以避免&#34;嵌套if-let hell&#34;。

非常简单但功能强大:

infix operator >>? { associativity left}
func >>? <U,T>(opt: T?, f: (T -> U?)) -> U? {
  if let x = opt {
    return f(x)
  }
  return nil
}

请注意,该函数必须返回Optional。出于某种原因,Swift编译器错过了stringFromDate没有返回可选项的事实,所以它没有警告我。我不确定为什么会这样,它之前肯定警告过我:

if let update = fromDate >>? self.dateFormatter.stringFromDate {

此操作失败,但不会立即

展开非可选值并不会立即导致崩溃,错误或任何事情。我成功使用日期字符串从服务器发送和接收数据。我不确定为什么解包非可选字符串会导致崩溃,而当我尝试设置实例变量时,生成字符串的后备NSDate对象的实例变量。我想不知怎的,解开一个非可选的搞砸了一些指针,但不一定是指向未展开对象的指针。我认为崩溃本身与Swift试图在设置新的实例变量(lastUpdated)时释放或解除分配,但发现内存地址搞砸了。我认为只有Apple Swift工程师可以告诉我实际发生了什么,但也许这里有Swift如何在内部工作的线索。