【问题标题】:How do i pass a dictionary as a function parameter?如何将字典作为函数参数传递?
【发布时间】:2016-01-03 11:16:34
【问题描述】:

我正在尝试将字典作为函数参数传递。我有以下功能

func makeAndAddVisitorRecord2(visitorDict: Dictionary) -> ABRecordRef <AnyObject, AnyObject> {
    let visitorRecord: ABRecordRef = ABPersonCreate().takeRetainedValue()
    ABRecordSetValue(visitorRecord, kABPersonFirstNameProperty, visitorDict[1], nil)
    ABRecordSetValue(visitorRecord, kABPersonLastNameProperty, visitorDict[2], nil)
    //ABRecordSetValue(visitorRecord, kABPersonEmailProperty, visitorDict[5], nil)

    let phoneNumbers: ABMutableMultiValue =
    ABMultiValueCreateMutable(ABPropertyType(kABMultiStringPropertyType)).takeRetainedValue()
    ABMultiValueAddValueAndLabel(phoneNumbers, visitorDict["visitorPhone"], kABPersonPhoneMainLabel, nil)
    ABRecordSetValue(visitorRecord, kABPersonPhoneProperty, phoneNumbers, nil)

    ABAddressBookAddRecord(addressBookRef, visitorRecord, nil)
    saveAddressBookChanges()

    return visitorRecord
}

我喜欢触发

func addVisitorToContacts(sender: AnyObject) {
    //let visitor = ListVisitors[visitorButton.tag]
    var visitorDict:[Int:String] = [1:"\(visitorName)", 2:"\(visitorCompany)", 3:"\(visitorCity)",
        4:"\(visitorPhone)", 5:"\(visitorEmail)"]

    let visitorRecord: ABRecordRef = makeAndAddVisitorRecord2(visitorDict)
    let contactAddedAlert = UIAlertController(title: "\(visitorName) was successfully added.",
        message: nil, preferredStyle: .Alert)
    contactAddedAlert.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil))
    presentViewController(contactAddedAlert, animated: true, completion: nil)
}

但是makeAndAddVisitorRecord2编译出错

 Cannot specialize non-generic type 'ABRecordRef' (aka 'AnyObject')

[EDIT 1] 可行的解决方案,但不是最佳的,因为我没有使用我的访问者结构

func makeAndAddVisitorRecord2(visitorDict: Dictionary <Int, String>) -> ABRecordRef  {

[EDIT 2] 正如@rsmoz 指出的,我应该使用我的访问者结构

class Visitor {

var visitorName : String
var visitorCompany : String
var visitorPlace : String
var visitorPhone : String
var visitorEmail : String

init(visitorName: String, visitorCompany: String, visitorPlace: String, visitorPhone: String, visitorEmail: String) {
    self.visitorName = visitorName
    self.visitorCompany = visitorCompany
    self.visitorPlace = visitorPlace
    self.visitorPhone = visitorPhone
    self.visitorEmail = visitorEmail
}

}

所以我有一个 ListVisitors 类,它生成一些访客,看起来像

class ListVisitors{
    static var sharedInstance = [Visitor]()

static func load()
    {
        // @todo: stored and loaded data
        var visitor = Visitor(visitorName: "From Class Matt", visitorCompany: "Google", visitorPlace: "San Diego", visitorPhone: "94888484", visitorEmail: "matt@google.com")
        sharedInstance = [visitor]

        visitor = Visitor(visitorName: "From Class John", visitorCompany: "nike", visitorPlace: "New York", visitorPhone: "94888484", visitorEmail: "john@nike.com")
        //        ListVisitors.sharedInstance += [visitor]
        sharedInstance += [visitor]
...
}
}

在我的主控制器中,我有一个表格视图,并且一个选定的行将访问者详细信息发送到 detailcontroller(我如何才能在详细视图控制器中拥有选定的访问者结构??我应该将 let selectedVisitor 传递给详细视图控制器吗?)

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?){
if (segue.identifier == "visitorDetails") {

            if let indexPath = tableView.indexPathForCell(sender as! UITableViewCell) {

                let selectedVisitor = lVisitors[indexPath.row] as Visitor

                let detailVC = segue.destinationViewController as! DetailViewController

                detailVC.visitorName = selectedVisitor.visitorName
                detailVC.visitorCompany = selectedVisitor.visitorCompany
                detailVC.visitorPlace = selectedVisitor.visitorPlace
                detailVC.visitorPhone = selectedVisitor.visitorPhone
                detailVC.visitorEmail = selectedVisitor.visitorEmail

            } // .end accessory select

        } // .end segue

【问题讨论】:

  • 为什么需要Int:String字典?只需使用数组。
  • @stek29 嗯我试过let visitorArr: Array = [String]() and visitorArr["visitorName"] = visitorName 并尝试将数组作为参数传递。你能提供一个简单的代码示例吗???为什么要使用数组 > 字典??

标签: swift dictionary


【解决方案1】:

我不确定你想用ABRecordRef &lt;AnyObject, AnyObject&gt; 做什么,但&lt;&gt; 语法用于指定泛型类型。比如,一个包含字符串的数组是Array&lt;String&gt;。 ABRecordRef 不是泛型类型。

字典需要在参数中指定它保存的类型:Dictionary&lt;String, Int&gt;

此外,您将字典视为数组。最好使用字典,因为它应该被使用。为什么不用[1:"\(visitorName)"] 而不是["visitorName":visitorName]?这样你就可以像dict["visitorName"] 一样访问它,如果visitorName 是一个以字符串开头的,你也不需要"\(visitorName)"。直接使用变量即可。

不过,将访问者表示为结构体而不是数组或字典会更好:

struct Visitor {
    let name: String
    let company: String
    let city: String
    let phone: String //Yes, this should be a String and not an Int
    let email: String
}

你可以这样设置:

let v = Visitor(name: "Joe", company: "A Corp", city: "New York", phone: "+44 392 39275 22", email: "joe@smith.org")

然后像这样访问它:

v.name

而且这样更清洁、更安全。现在您的代码不会因意外访问字典上的错误键而出现任何错误。

哦,你现在应该使用 Contacts framework,而不是 ABAddressBook。

【讨论】:

  • 实际上,Dictionary&lt;Int:String&gt; 是行不通的。这是Dictionary&lt;Int, String&gt;。使用逗号,而不是冒号。
  • @rsmoz,我已经有一个我使用的访问者结构。但是在 detailviewcontroller 中我不知道如何再次使用 Visitor 结构,我只是“吐出”诸如 ` override func viewDidLoad() { super.viewDidLoad() lblName.text = visitorName lblCompany.text = visitorCompany ... 之类的值。 ` 所以我做了什么,我创建了一个“临时”字典,其中包含来自访问者结构的值
  • 也许如果您展示更多代码,我可以更好地帮助您。您应该仍然可以在文件中使用该结构。
  • @rsmoz,我稍微编辑了我的问题。希望你能给我更多的建议。我坚持使用正确的“选择”/将正确的访问者结构传递给详细视图控制器顺便说一句我正在为 > iOS 8 和联系人框架是 > iOS 9 不是吗?
  • @rsmoz 你介意再看一下,我如何在视图控制器之间传递正确的结构/类?
【解决方案2】:

Swift 中的字典类型称为Dictionary。但是,它是通用的,这意味着您需要在类型名称后添加&lt;&gt; 以指定您希望它是什么类型的字典。在这种情况下,它是Dictionary&lt;Int, String&gt;。这是因为您传递给方法的变量 (visitorDict) 的类型为 Dictionary&lt;Int, String&gt;。

像这样写你的函数头:

func makeAndAddVisitorRecord2(visitorDict: Dictionary<Int, String>) -> ABRecordRef <AnyObject, AnyObject> {

如果你想更进一步,你可以使用字典的简写类型名称:

func makeAndAddVisitorRecord2(visitorDict: [Int: String]) -> ABRecordRef <AnyObject, AnyObject> {

此外,如果您的字典键是连续的,例如 1、2、3、4、5 等,您可以改用数组:

func makeAndAddVisitorRecord2(visitorDict: Array<String>) -> ABRecordRef <AnyObject, AnyObject> {

数组的简写是:

func makeAndAddVisitorRecord2(visitorDict: [String]) -> ABRecordRef <AnyObject, AnyObject> {

【讨论】:

    【解决方案3】:

    你必须在swift中指定它是什么类型的字典,像这样:

    func makeAndAddVisitorRecord2(visitorDict: [Int: String]) -> ABRecordRef <AnyObject, AnyObject> {
        let visitorRecord: ABRecordRef = ABPersonCreate().takeRetainedValue()
        ABRecordSetValue(visitorRecord, kABPersonFirstNameProperty, visitorDict[1], nil)
        ABRecordSetValue(visitorRecord, kABPersonLastNameProperty, visitorDict[2], nil)
        //ABRecordSetValue(visitorRecord, kABPersonEmailProperty, visitorDict[5], nil)
    
        let phoneNumbers: ABMutableMultiValue =
        ABMultiValueCreateMutable(ABPropertyType(kABMultiStringPropertyType)).takeRetainedValue()
        ABMultiValueAddValueAndLabel(phoneNumbers, visitorDict["visitorPhone"], kABPersonPhoneMainLabel, nil)
        ABRecordSetValue(visitorRecord, kABPersonPhoneProperty, phoneNumbers, nil)
    
        ABAddressBookAddRecord(addressBookRef, visitorRecord, nil)
        saveAddressBookChanges()
    
        return visitorRecord
    }
    

    然后你可以使用makeAndAddVisitorRecord2(visitorDict),一切都会正常。

    您的集合类型apple doc 有更深入的示例。

    【讨论】:

      【解决方案4】:

      ABRecordRef 不是通用的,因此您不能像以前那样使用。您很可能希望将泛型声明添加到 Dictionary 参数中。

      【讨论】:

        猜你喜欢
        • 2022-11-11
        • 2019-09-14
        • 1970-01-01
        • 2010-09-24
        • 1970-01-01
        • 2017-10-01
        • 2023-03-26
        • 2013-10-29
        相关资源
        最近更新 更多