【发布时间】:2017-04-25 04:08:30
【问题描述】:
我已经获得并成功地为我的 iOS 应用程序生成了一个崩溃报告。但是,查看堆栈跟踪我似乎无法理解它。
Thread 0 Crashed:
0 libswiftCore.dylib 0x00000001005d330c specialized _assertionFailure(StaticString, String, file : StaticString, line : UInt, flags : UInt32) -> Never (__hidden#17347_:134)
1 libswiftCore.dylib 0x00000001004d7d2c Error<A where ...>._code.getter (__hidden#18979_:221)
2 libswiftCore.dylib 0x00000001004d7bf4 swift_errorInMain + 0
3 MyAppName 0x00000001000c2190 specialized PersonRepository.hydrate(Row) -> Person (PersonRepository.swift:0)
4 MyAppName 0x00000001000fbebc specialized Database.checkSchemaVersion(connection : Connection) -> () (Database.swift:0)
5 MyAppName 0x00000001000fc254 _TTSf4d_g__TZFC6MyAppName8DatabaseP33_909B711B8156620EE1EFE30EC21C4C0C11getInstancefT_S0_ (Database.swift:0)
6 MyAppName 0x00000001000fade8 static Database.getInstance() -> Database (Database.swift:0)
7 MyAppName 0x00000001000a7a6c TaskRepository.init() -> TaskRepository (TaskRepository.swift:38)
(......)
让我摸不着头脑的是它到底是如何从 4 级升到 3 级的。
在我的理解中,这意味着 Database.checkSchemaVersion(connection : Connection) -> () 在某些时候会调用 PersonRepository.hydrate(Row) -> Person - 这没有任何意义。
这是我的完整数据库类(不是太大)
// Database.swift
import SQLite
import Foundation
class Database
{
private var connection : Connection?
private static var instance : Database?
private static func getInstance() -> Database
{
if (instance == nil) {
instance = Database()
instance!.checkSchemaVersion(connection: instance!.connection!)
}
return instance!
}
private init()
{
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
connection = try! Connection("(path)/myappname.sqlite3");
}
deinit {
connection = nil
}
static func getConnection() -> Connection
{
return getInstance().connection!
}
func checkSchemaVersion(connection : Connection)
{
guard let buildString = Bundle.main.infoDictionary?["CFBundleVersion"] as? String else {
Application.debug("Database: could not convert Build to String")
return
}
guard let build = Int64(buildString) else {
Application.debug("Database: could not convert Build from String to Int64")
return
}
let schemaVersion = try! connection.scalar("PRAGMA user_version") as? Int64 ?? 0
Application.debug("Database: checking schema version - DB=(schemaVersion) vs app=(build)")
if schemaVersion < build {
Application.debug("Database: old schema version detected - updating now")
PersonRepository.getInstance().updateSchema(from: schemaVersion, to: build)
PictureRepository.getInstance().updateSchema(from: schemaVersion, to: build)
TaskRepository.getInstance().updateSchema(from: schemaVersion, to: build)
TaskCommentRepository.getInstance().updateSchema(from: schemaVersion, to: build)
VenueRepository.getInstance().updateSchema(from: schemaVersion, to: build)
try! connection.run("PRAGMA user_version = (build)")
}
}
}
任何想法堆栈跟踪(不是很堆叠,是吗?)应该是什么意思,或者它是如何到达这种情况的?如果事情真的以这种方式发展,难怪它会崩溃。
更新
虽然我相信堆栈跟踪表明在 Database.checkSchemaVersion(connection : Connection) -> () 的某个地方有一个对 PersonRepository.hydrate(Row) -> Person 的直接调用并且这个添加是无关的,这里是 PersonRepository 的相关部分
private init()
{
db = Database.getConnection()
table = Table("persons")
pictureRepository = PictureRepository.getInstance()
try! db.run(table.create(ifNotExists: true) {
t in
t.column(id, primaryKey: true)
t.column(name)
t.column(email)
t.column(phone)
t.column(company)
t.column(pictureId)
})
}
public func updateSchema(from: Int64, to: Int64)
{
if from < 2016121201 {
try! db.run(table.addColumn(active, defaultValue: 1))
}
}
static func getInstance() -> PersonRepository
{
if (instance == nil) {
instance = PersonRepository()
}
return instance!
}
【问题讨论】:
-
看起来此崩溃日志已被删除。您能否也发布 PersonRepository 的代码。看起来它来到 `PersonRepository.getInstance().updateSchema(from: schemaVersion, to: build)` 行
-
@dRAGONAIR - 我添加了该类的一部分,但我认为它不相关。从堆栈跟踪中可以看出,有一个从
Database.checkSchemaVersion(connection : Connection)到PersonRepository.hydrate(Row)的直接调用——但没有任何这样的调用。如果它不是直接的,那么这两者之间应该有中间层。调用堆栈就是这样工作的,不是吗?
标签: ios swift3 crash-reports