"Cannot subscript a value of type 'Dictionary<NSObject, AnyObject>' with an index of type 'String" 错误
"Cannot subscript a value of type 'Dictionary<NSObject, AnyObject>' with an index of type 'String" error
我一直在做一个需要从 .plist
恢复保存的数据的项目,但是我遇到了一个错误 Cannot subscript a value of type 'Dictionary' with an index在我的代码中属于 'String' 类型。我正在尝试解决它,但不幸的是我不知道如何解决。我尝试了一些在 Whosebug 中找到的解决方案,但没有成功。请帮助我,因为这是我第一次创建恢复数据的功能。谢谢
@objc func restoreSucceed() {
performSelector(inBackground: #selector(stopIndicator), with: nil)
//エラーアラートビューの表示
let alertController = UIAlertController(title: "", message: "リストアが完了しました \n (Restore completed)", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: .default))
self.present(alertController, animated: true, completion: nil)
if floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_7_1 {
var pref = UserDefaults.standard
//ローカルplist格納先を取得
let strWorkPath = NSSearchPathForDirectoriesInDomains(.libraryDirectory, .userDomainMask, true)[0]
let strPlistPath = "\(strWorkPath)/\(S_DIRECTORY_NAME)/\(S_PLIST_NAME)"
let dicPref = NSDictionary(contentsOfFile: strPlistPath) as Dictionary?
if let key1 = (dicPref as NSDictionary?)?.keyEnumerator() {
for key in key1 {
let strKey = key as? String
pref.set(dicPref?[strKey ?? ""], forKey: strKey ?? "")
}
}
pref.synchronize()
}
navigationController?.popViewController(animated: true)
}
替换:
let dicPref = NSDictionary(contentsOfFile: strPlistPath) as Dictionary?
与 :
let dicPref = NSDictionary(contentsOfFile: strPlistPath)
.
let pref = UserDefaults.standard
let dicPref = NSDictionary(contentsOfFile: "")
if let key1 = dicPref?.keyEnumerator() {
for key in key1 {
let strKey = key as? String
pref.set(dicPref?[strKey ?? ""], forKey: strKey ?? "")
}
}
将dicPref?[strKey ?? ""]
替换为dicPref?[strKey as! NSString]
注意:尽可能避免强行展开。
使用以下
pref.set(dicPref?[strKey! as NSString], forKey: strKey ?? "")
@Roy 的回答是正确的,但它会给你警告展开
试试下面的代码
var pref = UserDefaults.standard
let strWorkPath = NSSearchPathForDirectoriesInDomains(.libraryDirectory, .userDomainMask, true)[0]
let strPlistPath = "\(strWorkPath)/\(S_DIRECTORY_NAME)/\(S_PLIST_NAME)"
if let dicPref = NSDictionary(contentsOfFile: strPlistPath) as? Dictionary<String, AnyObject> {
// use swift dictionary as normal
if let key1 = (dicPref as NSDictionary?)?.keyEnumerator() {
for key in key1 {
if let strKey = key as? String {
pref.set(dicPref[strKey], forKey: strKey)
}
}
}
}
pref.synchronize()
您的代码使用了很多不恰当的 objective-c-ish API.
这是推荐的 Swift 读取和解析 属性 列表文件的方法
if #available(iOS 7.1, *) {
//ローカルplist格納先を取得
do {
let strWorkURL = try FileManager.default.url(for: .libraryDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let strPlistURL = strWorkURL.appendingPathComponent("\(S_DIRECTORY_NAME)/\(S_PLIST_NAME)")
let strPlistData = try Data(contentsOf: strPlistURL)
guard let dicPref = try PropertyListSerialization.propertyList(from: strPlistData, format: nil) as? [String:Any] else { return }
for (key, value) in dicPref {
UserDefaults.standard.set(value, forKey: key)
}
} catch { print(error) }
}
也不要使用 performSelector(inBackground:)
。使用 GCD
DispatchQueue.global().async {
stopIndicator()
}
我一直在做一个需要从 .plist
恢复保存的数据的项目,但是我遇到了一个错误 Cannot subscript a value of type 'Dictionary' with an index在我的代码中属于 'String' 类型。我正在尝试解决它,但不幸的是我不知道如何解决。我尝试了一些在 Whosebug 中找到的解决方案,但没有成功。请帮助我,因为这是我第一次创建恢复数据的功能。谢谢
@objc func restoreSucceed() {
performSelector(inBackground: #selector(stopIndicator), with: nil)
//エラーアラートビューの表示
let alertController = UIAlertController(title: "", message: "リストアが完了しました \n (Restore completed)", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: .default))
self.present(alertController, animated: true, completion: nil)
if floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_7_1 {
var pref = UserDefaults.standard
//ローカルplist格納先を取得
let strWorkPath = NSSearchPathForDirectoriesInDomains(.libraryDirectory, .userDomainMask, true)[0]
let strPlistPath = "\(strWorkPath)/\(S_DIRECTORY_NAME)/\(S_PLIST_NAME)"
let dicPref = NSDictionary(contentsOfFile: strPlistPath) as Dictionary?
if let key1 = (dicPref as NSDictionary?)?.keyEnumerator() {
for key in key1 {
let strKey = key as? String
pref.set(dicPref?[strKey ?? ""], forKey: strKey ?? "")
}
}
pref.synchronize()
}
navigationController?.popViewController(animated: true)
}
替换:
let dicPref = NSDictionary(contentsOfFile: strPlistPath) as Dictionary?
与 :
let dicPref = NSDictionary(contentsOfFile: strPlistPath)
.
let pref = UserDefaults.standard
let dicPref = NSDictionary(contentsOfFile: "")
if let key1 = dicPref?.keyEnumerator() {
for key in key1 {
let strKey = key as? String
pref.set(dicPref?[strKey ?? ""], forKey: strKey ?? "")
}
}
将dicPref?[strKey ?? ""]
替换为dicPref?[strKey as! NSString]
注意:尽可能避免强行展开。
使用以下
pref.set(dicPref?[strKey! as NSString], forKey: strKey ?? "")
@Roy 的回答是正确的,但它会给你警告展开
试试下面的代码
var pref = UserDefaults.standard
let strWorkPath = NSSearchPathForDirectoriesInDomains(.libraryDirectory, .userDomainMask, true)[0]
let strPlistPath = "\(strWorkPath)/\(S_DIRECTORY_NAME)/\(S_PLIST_NAME)"
if let dicPref = NSDictionary(contentsOfFile: strPlistPath) as? Dictionary<String, AnyObject> {
// use swift dictionary as normal
if let key1 = (dicPref as NSDictionary?)?.keyEnumerator() {
for key in key1 {
if let strKey = key as? String {
pref.set(dicPref[strKey], forKey: strKey)
}
}
}
}
pref.synchronize()
您的代码使用了很多不恰当的 objective-c-ish API.
这是推荐的 Swift 读取和解析 属性 列表文件的方法
if #available(iOS 7.1, *) {
//ローカルplist格納先を取得
do {
let strWorkURL = try FileManager.default.url(for: .libraryDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let strPlistURL = strWorkURL.appendingPathComponent("\(S_DIRECTORY_NAME)/\(S_PLIST_NAME)")
let strPlistData = try Data(contentsOf: strPlistURL)
guard let dicPref = try PropertyListSerialization.propertyList(from: strPlistData, format: nil) as? [String:Any] else { return }
for (key, value) in dicPref {
UserDefaults.standard.set(value, forKey: key)
}
} catch { print(error) }
}
也不要使用 performSelector(inBackground:)
。使用 GCD
DispatchQueue.global().async {
stopIndicator()
}