好的,这是一个奇怪的错误,我花了很多时间来追踪确切的位置(虽然原因仍然未知)。错误仅在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
延迟分配,可以让它工作。但我不想这样做。
有谁知道为什么会这样?
Int
,Bool
,String
)等,则不会发生此事。NSTimeInterval
并尝试从NSDate.timeIntervalSinceReferenceDate()
lastUpdated
而不是在回调中,则会发生崩溃。NSDate
包装在另一个类中,则会发生崩溃。lastUpdated
println(NSDate())
(删除作业)答案 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如何在内部工作的线索。