Swift PropertyListDecoder 无法处理来自 swift 包的类型
Swift PropertyListDecoder not working on type from swift package
我有一个独立的 watchOS 应用程序。当我将应用程序从 XCode 部署到我的手表时,它会起作用。我已将应用程序放在 TestFlight 上,但应用程序在尝试从 plist 文件读取时崩溃。
它试图解码的类型在 swift 包中。如果我将该类型从 swift 包移动到我的 watchOS 代码库中,那么它在从 TestFlight 部署时就可以工作。但是当它在 swift 包中时,它会在从 TestFlight 部署时崩溃。
我不知道为什么会这样。在 TestFlight 之间使用包和从 XCode 部署有什么不同?
这是崩溃报告的一部分:
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x00000000
VM Region Info: 0 is not in any region. Bytes before following region: 3686400
REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL
UNUSED SPACE AT START
--->
__TEXT 00384000-0039c000 [ 96K] r-x/r-x SM=COW ...Kit Extension
Termination Signal: Segmentation fault: 11
Termination Reason: Namespace SIGNAL, Code 0xb
Terminating Process: exc handler [384]
Triggered by Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libswiftCore.dylib 0x659e0e06 swift_checkMetadataState + 14
1 libswiftCore.dylib 0x659b66a8 type metadata completion function for ClosedRange<>.Index + 14
2 libswiftCore.dylib 0x659dc504 swift_getGenericMetadata + 1112
3 libswiftCore.dylib 0x659b5644 __swift_instantiateGenericMetadata + 28
4 libswiftFoundation.dylib 0x65b80fb0 PropertyListDecoder.decode<A>+ 651184 (_:from:format:) + 310
5 libswiftFoundation.dylib 0x65b80e72 PropertyListDecoder.decode<A>+ 650866 (_:from:) + 40
6 libswiftFoundation.dylib 0x65bf9b2c dispatch thunk of PropertyListDecoder.decode<A>+ 1145644 (_:from:) + 28
7 ...llHelper WatchKit Extension 0x0038ddb6 specialized load<A>(_:) + 40374 (Data.swift:117)
从崩溃报告来看,我的这行代码似乎崩溃了:
return try decoder.decode(T.self, from: data)
以下是我的项目的详细信息:
在项目的手表应用程序代码库中 -> Swift 包选项卡:
我在我的 git 存储库中包含了一个 link。这是 GitHub 上的私人仓库。版本规则我已经设置到master分支了
在 "WatchKit Extension" 目标中,我将我的包包含在 "Frameworks, Libraries and Embedded Content" 部分。
部署目标是 6.1
这是使用崩溃报告中引用的 Data.swift 文件中的 PropertyListDecoder 的代码。
func load<T: Decodable>(_ filename: String) -> T {
let data: Data
guard let file = Bundle.main.url(forResource: filename, withExtension: nil) else {
os_log("Couldn't find %@ in main bundle", log: Log.data, type: .error, filename)
fatalError("Couldn't find \(filename) in main bundle.")
}
do {
data = try Data(contentsOf: file)
} catch {
os_log("Couldn't load %@ from main bundle", log: Log.data, type: .error, filename)
fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
}
do {
let decoder = PropertyListDecoder()
return try decoder.decode(T.self, from: data) <-- this is the line it crashes at
} catch {
os_log("Couldn't parse %@. Error is: %@", log: Log.data, type: .error, filename, error.localizedDescription)
fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
}
}
这是 swift 包管理器中的代码:
import Foundation
public struct Bar: Hashable, Codable, Identifiable, Comparable {
public var id: Bar{self}
public var name: String
public var weight: Double
public let unit: WeightUnit
public init(name: String, weight: Double, weightUnit: WeightUnit) {
self.name = name
self.weight = weight
self.unit = weightUnit
}
public static func < (lhs: Bar, rhs: Bar) -> Bool {
if lhs.name != rhs.name {
return lhs.name < rhs.name
}else if lhs.weight != rhs.weight {
return lhs.weight < rhs.weight
}else {
return lhs.unit < rhs.unit
}
}
public static func == (lhs: Self, rhs: Self) -> Bool {
return
lhs.name == rhs.name &&
lhs.weight == rhs.weight &&
lhs.unit == rhs.unit
}
}
public enum WeightUnit: String, CaseIterable, Identifiable, Codable, Comparable {
case Kilo = "kg"
case Pound = "lb"
public var id: WeightUnit {self}
public func description() -> String {
switch self {
case .Kilo:
return "Metric (\(self.rawValue))"
case .Pound:
return "Imperial (\(self.rawValue))"
}
}
public static func < (lhs: WeightUnit, rhs: WeightUnit) -> Bool {
lhs.description() < rhs.description()
}
public static func == (lhs: Self, rhs: Self) -> Bool {
return lhs.rawValue == rhs.rawValue
}
}
经过更多研究后,我通过 .
解决了我的问题
在应用程序代码库中,我将项目和所有目标中的构建设置 -> 死代码剥离从 "yes" 更改为 "no"。
我有一个独立的 watchOS 应用程序。当我将应用程序从 XCode 部署到我的手表时,它会起作用。我已将应用程序放在 TestFlight 上,但应用程序在尝试从 plist 文件读取时崩溃。
它试图解码的类型在 swift 包中。如果我将该类型从 swift 包移动到我的 watchOS 代码库中,那么它在从 TestFlight 部署时就可以工作。但是当它在 swift 包中时,它会在从 TestFlight 部署时崩溃。
我不知道为什么会这样。在 TestFlight 之间使用包和从 XCode 部署有什么不同?
这是崩溃报告的一部分:
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x00000000
VM Region Info: 0 is not in any region. Bytes before following region: 3686400
REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL
UNUSED SPACE AT START
--->
__TEXT 00384000-0039c000 [ 96K] r-x/r-x SM=COW ...Kit Extension
Termination Signal: Segmentation fault: 11
Termination Reason: Namespace SIGNAL, Code 0xb
Terminating Process: exc handler [384]
Triggered by Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libswiftCore.dylib 0x659e0e06 swift_checkMetadataState + 14
1 libswiftCore.dylib 0x659b66a8 type metadata completion function for ClosedRange<>.Index + 14
2 libswiftCore.dylib 0x659dc504 swift_getGenericMetadata + 1112
3 libswiftCore.dylib 0x659b5644 __swift_instantiateGenericMetadata + 28
4 libswiftFoundation.dylib 0x65b80fb0 PropertyListDecoder.decode<A>+ 651184 (_:from:format:) + 310
5 libswiftFoundation.dylib 0x65b80e72 PropertyListDecoder.decode<A>+ 650866 (_:from:) + 40
6 libswiftFoundation.dylib 0x65bf9b2c dispatch thunk of PropertyListDecoder.decode<A>+ 1145644 (_:from:) + 28
7 ...llHelper WatchKit Extension 0x0038ddb6 specialized load<A>(_:) + 40374 (Data.swift:117)
从崩溃报告来看,我的这行代码似乎崩溃了:
return try decoder.decode(T.self, from: data)
以下是我的项目的详细信息:
在项目的手表应用程序代码库中 -> Swift 包选项卡:
我在我的 git 存储库中包含了一个 link。这是 GitHub 上的私人仓库。版本规则我已经设置到master分支了
在 "WatchKit Extension" 目标中,我将我的包包含在 "Frameworks, Libraries and Embedded Content" 部分。
部署目标是 6.1
这是使用崩溃报告中引用的 Data.swift 文件中的 PropertyListDecoder 的代码。
func load<T: Decodable>(_ filename: String) -> T {
let data: Data
guard let file = Bundle.main.url(forResource: filename, withExtension: nil) else {
os_log("Couldn't find %@ in main bundle", log: Log.data, type: .error, filename)
fatalError("Couldn't find \(filename) in main bundle.")
}
do {
data = try Data(contentsOf: file)
} catch {
os_log("Couldn't load %@ from main bundle", log: Log.data, type: .error, filename)
fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
}
do {
let decoder = PropertyListDecoder()
return try decoder.decode(T.self, from: data) <-- this is the line it crashes at
} catch {
os_log("Couldn't parse %@. Error is: %@", log: Log.data, type: .error, filename, error.localizedDescription)
fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
}
}
这是 swift 包管理器中的代码:
import Foundation
public struct Bar: Hashable, Codable, Identifiable, Comparable {
public var id: Bar{self}
public var name: String
public var weight: Double
public let unit: WeightUnit
public init(name: String, weight: Double, weightUnit: WeightUnit) {
self.name = name
self.weight = weight
self.unit = weightUnit
}
public static func < (lhs: Bar, rhs: Bar) -> Bool {
if lhs.name != rhs.name {
return lhs.name < rhs.name
}else if lhs.weight != rhs.weight {
return lhs.weight < rhs.weight
}else {
return lhs.unit < rhs.unit
}
}
public static func == (lhs: Self, rhs: Self) -> Bool {
return
lhs.name == rhs.name &&
lhs.weight == rhs.weight &&
lhs.unit == rhs.unit
}
}
public enum WeightUnit: String, CaseIterable, Identifiable, Codable, Comparable {
case Kilo = "kg"
case Pound = "lb"
public var id: WeightUnit {self}
public func description() -> String {
switch self {
case .Kilo:
return "Metric (\(self.rawValue))"
case .Pound:
return "Imperial (\(self.rawValue))"
}
}
public static func < (lhs: WeightUnit, rhs: WeightUnit) -> Bool {
lhs.description() < rhs.description()
}
public static func == (lhs: Self, rhs: Self) -> Bool {
return lhs.rawValue == rhs.rawValue
}
}
经过更多研究后,我通过
在应用程序代码库中,我将项目和所有目标中的构建设置 -> 死代码剥离从 "yes" 更改为 "no"。