我正在制作一个自定义键盘,我想在容器应用程序中构建一个资产(特别是一个trie字典),然后在键盘扩展通过共享容器启动时访问它。为了解决这个问题,我从这个相当基础的课程开始:
class Person: NSObject, NSCoding {
let name: String
let age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
required init(coder decoder: NSCoder) {
self.name = decoder.decodeObject(forKey: "name") as? String ?? ""
self.age = decoder.decodeInteger(forKey: "age")
}
func encode(with coder: NSCoder) {
coder.encode(name, forKey: "name")
coder.encode(age, forKey: "age")
}
}
大。我已经设置了共享容器,并且在容器应用程序的ViewController的viewDidLoad函数中,我加载了共享容器(一些测试变量和自定义对象):
let shared = UserDefaults(suiteName: "group.test_keyboard")
shared!.set("test", forKey:"key_string")
shared!.set(false, forKey:"key_boolean")
shared!.set(34, forKey:"key_int")
let newPerson = Person(name: "Joe", age: 10)
let encodedData = NSKeyedArchiver.archivedData(withRootObject: newPerson)
shared!.set(encodedData, forKey: "people")
为了测试它,我将以下代码添加到viewWillAppear:
let shared = UserDefaults(suiteName: "group.test_keyboard")
let test_string = shared?.string(forKey: "key_string")
if(test_string != nil){
print("string-\(test_string!)")
}
else{
print("nil")
}
// retrieving a value for a key
if let data = shared?.data(forKey: "people"){
let test_person = NSKeyedUnarchiver.unarchiveObject(with: data) as? Person
print("-\(test_person!.name)") // Joe
let data_size = String(data.count)
print("-\(data_size)")
} else {
print("There is an issue")
}
一切都很好。但是当我进入KeyboardViewController并尝试访问东西时,检索简单的字符串工作正常:
let shared = UserDefaults(suiteName: "group.test_keyboard")
shared?.synchronize()
let test_string = shared?.string(forKey: "key_string")
if(test_string != nil){
(textDocumentProxy as UIKeyInput).insertText(test_string!)
}
else{
(textDocumentProxy as UIKeyInput).insertText("nil")
}
但是如果我尝试访问自定义对象Person,那么:
if let data = shared?.data(forKey: "people") {
(textDocumentProxy as UIKeyInput).insertText("found")
(textDocumentProxy as UIKeyInput).insertText(String(data.count))
let myPeople = NSKeyedUnarchiver.unarchiveObject(with: data) as? Person
}
我因以下错误响应而崩溃:
2017-05-10 14:34:46.938253-0700 test_keyboard [3196:857207] viewServiceDidTerminateWithError ::错误 Domain = _UIViewServiceInterfaceErrorDomain Code = 3“(null)” UserInfo = {Message = Service Connection Interrupted}
数据在那里,如果我在两边进行简单的data.count检查,它的大小相同(269)。如果我注释掉NSKeyedUnarchiver系列,那就没问题了,所以我确定问题出在哪里。当它在容器应用程序中正常工作时,究竟发生什么导致它在键盘扩展内崩溃?
答案 0 :(得分:1)
很可能是在不同模块中运行的问题。您的应用程序是与扩展程序不同的模块,而完全限定的类名称包括模块名称。在应用程序中,它类似于AppName.Person
,但在扩展程序中它类似KeyboardExt.Person
。 NSCoding
无法匹配,因此barfs。
有几种解决方法。一种是创建一个app和扩展使用的框架,并将共享类放在那里。然后带有模块的名称总是类似于' FrameworkName.Person`,一切都会起作用。
另一个是专门告诉(un)归档过程该类使用什么名称。然后它会写出您指定的名称并将其与相应的类匹配。在编写任何数据之前,请执行类似
的操作NSKeyedArchiver.setClassName("Person", for: Person.self)
然后在阅读任何数据之前,请执行相反的操作:
NSKeyedUnarchiver.setClass(Person.self, forClassName: "Person")