setValuesForKeysWithDictionary in Swift 4?


似乎 Swift 4

正在实现不同的方法来(void)setValuesForKeysWithDictionary(),在 Swift 4 中,这个函数的合适替代品是什么?

我有结构

struct User {
    let name: String?
    let email: String?
}

dictionaryOfUsers来自数据结构,其值根据数据库中的用户数量动态呈现:

let dictionaryOfUsers = [{key1: "name1", key2 : "name1@xyz.com"}, {key1 : "name2", key2 : "name2@gmail.com"} ]   
let users = [User]

现在我想使用这个函数来创建我的用户数组,以便在 Swift 4 中创建字典:

for dictionary in dictionaryOfUsers {
    let user = User()
    user.setValuesForKeysWithDictionary(dictionary) 

并附加到用户

    users.append(user)
}     

请尝试以下方法:

func setValuesForKeys(_ keyedValues: [String : Any])
使用

给定字典中的值设置接收器的属性,使用其键标识属性。默认实现为每个键值对调用setValue(_:forKey:)...

您的代码有许多小问题 - 也有一些主要问题(有关更多信息,请参阅 matt 答案)。无论如何,我认为这应该完成您所追求的:

import Foundation
class User: NSObject {
    @objc var name: String!
    @objc var email: String!
}
let dictionaryOfUsers = [
    ["name": "name1", "email": "name1@xyz.com"],
    ["name": "name2", "email": "name2@gmail.com"]
]
var users = [User]()
for dictionary in dictionaryOfUsers {
    let user = User()
    user.setValuesForKeys(dictionary) 
    users.append(user)
} 

问题是你试图在结构上使用Cocoa键值编码——这就是setValuesForKeys(_:)的来源。你不能这么做。可可是Objective-C;Objective-C不知道Cocoa结构是什么。您需要User是从 NSObject 派生的@objc类,并且它的所有属性也需要作为@objc公开。

或者,使用新的 Swift 4 键路径功能,该功能可以通过其键访问结构属性。例:

struct User {
    var name: String?
    var email: String?
}
let arrayOfDicts = [
    [User.name: "name1", User.email : "name1@xyz.com"],
    [User.name : "name2", User.email : "name2@gmail.com"]
]
for d in arrayOfDicts {
    var user = User()
    for key in d.keys {
        user[keyPath:key] = d[key]!
    }
    print(user)
}
/*
 User(name: Optional("name1"), email: Optional("name1@xyz.com"))
 User(name: Optional("name2"), email: Optional("name2@gmail.com"))
*/
不用

说 Swift 4 没有 setValuesForKeysWithDictionary 方法。此外,当前的 setValuesForKeys 方法在最新的 Xcode 版本的 Swift 4 中经常失败。

我的用户对象如下。

import UIKit
class User: NSObject {
    var name: String?
    var email: String?
}

我自己对这个问题的解决方案是添加手动键作为 NSDictionary,如下所示。

let user = User()
user.email = (snapshot.value as? NSDictionary)?["email"] as? String ?? ""
user.name = (snapshot.value as? NSDictionary)?["name"] as? String ?? ""
print(user.email as Any)
print(user.name as Any)

它没有任何故障。试试吧。

我正在做一些事情。万一有帮助...P.S:请使用泛型进行优化。

  import Foundation
  import CoreData
   enum ModelInitializationResult {
   case none
   case completedWithoutErrors
   case completedWithNullDataErrors
   case completedWithNoSuchKeyErrors
    }
 extension NSManagedObject {
 //Note: For this to work, the keys in the dictionary should be same as attibute name of this class
func initializeModelFromDictionary(dictionary: [String:Any] )  -> ModelInitializationResult{
  var completionResult = ModelInitializationResult.none
  let modelAttributes = self.entity.attributesByName
  let modelAttributeKeys = modelAttributes.keys
  for case let (keyToSet, valueToSet) in dictionary {
    //check for invalid key
      guard modelAttributeKeys.contains(keyToSet) else{
          completionResult = .completedWithNoSuchKeyErrors
          continue;
      }
      //check valueToSetType for Null
      let valueToSetType = type(of: valueToSet)
      guard valueToSetType != NSNull.self else{
          print("ERROR: Found NSNUll for value to set")
          completionResult = .completedWithNullDataErrors
          continue;
      }
      //Check desiredType ; set value for defined types
      let modelAttributeValue = modelAttributes[keyToSet]
      let modelAttributeType = modelAttributeValue?.attributeType
    switch (modelAttributeType!) {
      case .undefinedAttributeType :
          print("Error : undefinedAttributeType")
      case .integer16AttributeType, .integer32AttributeType, .integer64AttributeType :
          if let anInt = valueToSet as? Int{
              self.setValue(anInt, forKey: keyToSet)
          }
          else{
              //print(Pretty//printedFunction(),"Error  in setting value for key:(keyToSet) Incompatible type")
          }
      case .stringAttributeType :
          if let anString = valueToSet as? String{
              self.setValue(anString, forKey: keyToSet)
          }
          else{
              //print(Pretty//printedFunction(),"Error  in setting value for key:(keyToSet) Incompatible type")
          }
      case .booleanAttributeType :
          if let aBool = valueToSet as? Bool{
              self.setValue(aBool, forKey: keyToSet)
          }
          else{
              //print(Pretty//printedFunction(),"Error  in setting value for key:(keyToSet) Incompatible type")
          }
      case .dateAttributeType :
          if let aDate = valueToSet as? Date{
              self.setValue(aDate, forKey: keyToSet)
          }
          else{
              //print(Pretty//printedFunction(),"Error  in setting value for key:(keyToSet) Incompatible type")
          }
      case .binaryDataAttributeType :
          if let aData = valueToSet as? Data{
              self.setValue(aData, forKey: keyToSet)
          }
          else{
              //print(Pretty//printedFunction(),"Error  in setting value for key:(keyToSet) Incompatible type")
          }
      case .transformableAttributeType :// If your attribute is of NSTransformableAttributeType,
          //print(Pretty//printedFunction(), "desiredType : transformableAttributeType")
          if let anObject = valueToSet as? NSObject {
              self.setValue(anObject, forKey: keyToSet)
          }
          else{
              //print(Pretty//printedFunction(),"Error  in setting value for key:(keyToSet) Incompatible type")
          }
      case .doubleAttributeType :
          //print(Pretty//printedFunction(), "desiredType : doubleAttributeType")
          if let anObject = valueToSet as? Double {
              self.setValue(anObject, forKey: keyToSet)
          }
          else{
              //print(Pretty//printedFunction(),"Error  in setting value for key:(keyToSet) Incompatible type")
          }
      case .floatAttributeType :
          //print(Pretty//printedFunction(), "desiredType : floatAttributeType")
          if let anObject = valueToSet as? Float {
              self.setValue(anObject, forKey: keyToSet)
          }
          else{
              //print(Pretty//printedFunction(),"Error  in setting value for key:(keyToSet) Incompatible type")
          }
      case .decimalAttributeType :
          print("Error: Data type decimalAttributeType Not handled(String(describing: modelAttributeType))")
      case .objectIDAttributeType:
          print("Error: Data type transformableAttributeType Not handled(String(describing: modelAttributeType))")
      default :
          print("ERROR : (String(describing: modelAttributeType))")
      }
  }
  return completionResult
}
func toDictionary() -> [String:Any]     {
    let keys = Array(self.entity.attributesByName.keys)
    let dict = self.dictionaryWithValues(forKeys: keys)
    return dict
}
func printAllValues (){
    for key in self.entity.attributesByName.keys{
        let value: Any? = self.value(forKey: key)
        print("(key) = (String(describing: value))")
    }
}

}

相关内容

  • 没有找到相关文章

最新更新