无法将'String.Type'类型的值转换为预期的参数类型'String'

时间:2018-04-10 08:56:12

标签: swift

Swift 4 / Xcode 9.3 / OS X 10.13.4 / iOS 11.3& 11.2.6

我正在尝试构建我的应用,但是我收到了上述错误消息。我已经检查了一遍又一遍的代码,我无法弄清楚为什么我会收到此错误。我不确定你需要看到哪部分代码,但这里是我收到错误的页面。错误代码标记了最后一行代码。

import UIKit
import os.log

class Bonus: NSObject, NSCoding {

    //MARK: Archiving Paths
    static let DocumentsDirectory = FileManager().urls(for: .documentDirectory, in: .userDomainMask).first!
    static let ArchiveURL = DocumentsDirectory.appendingPathComponent("bonuses")

    //MARK: Properties
    var bonusCode: String
    var category: String
    var name: String
    var value: Int
    var city: String
    var state: String
    var photo: UIImage?

    //MARK: Initialization
    init?(bonusCode: String, category: String, name: String, value: Int, city: String, state: String, photo: UIImage?) {

        // The name must not be empty.
        guard !name.isEmpty else {
            return nil
        }

        // The value must not be negative.
        guard (value >= 0) else {
            return nil
        }

        // Initialize stored properties.
        self.bonusCode = bonusCode
        self.category = category
        self.name = name
        self.value = value
        self.city = city
        self.state = state
        self.photo = photo
    }

    //MARK: Types
    struct  PropertyKey {
        static let bonusCode = "bonusCode"
        static let category = "category"
        static let name = "name"
        static let value = "value"
        static let city = "city"
        static let state = "state"
        static let photo = "photo"
    }

    //MARK: NSCoding
    func encode(with aCoder: NSCoder) {
        aCoder.encode(bonusCode, forKey: PropertyKey.bonusCode)
        aCoder.encode(category, forKey: PropertyKey.category)
        aCoder.encode(name, forKey: PropertyKey.name)
        aCoder.encode(value, forKey: PropertyKey.value)
        aCoder.encode(city, forKey: PropertyKey.city)
        aCoder.encode(state, forKey: PropertyKey.state)
        aCoder.encode(photo, forKey: PropertyKey.photo)
    }

    required convenience init?(coder aDecoder: NSCoder) {
        // The name is required. If we cannot decode a name string, the initializer should fail.
        guard let bonusCode = aDecoder.decodeObject(forKey: PropertyKey.bonusCode) as? String else {
            os_log("Unable to decode the Code for a Bonus object.", log: OSLog.default, type: .debug)
            return nil
        }

        // Because photo is an optional property of Meal, just use conditional cast
        let photo = aDecoder.decodeObject(forKey: PropertyKey.photo) as? UIImage

        let category = aDecoder.decodeObject(forKey: PropertyKey.category)
        let value = aDecoder.decodeInteger(forKey: PropertyKey.value)
        let city = aDecoder.decodeObject(forKey: PropertyKey.city)
        let state = aDecoder.decodeObject(forKey: PropertyKey.state)

        // Must call designated initializer.
        self.init(bonusCode: String, category: String, name: String, value: Int, city: String, state: String, photo: UIImage?)
    }
}

错误是在bonusCode:String上标记,特别是在String中的S上。

我对编程很新,但我只针对这个特定问题找到了另外一个搜索结果,而其他类似问题似乎对所使用的代码非常具体。

2 个答案:

答案 0 :(得分:1)

您必须传递解码的值而不是最后一行中的类型,并且缺少解码名称的行,您必须转换其他字符串对象。力展开是安全的,因为所有非可选值都被正确编码。

let name = aDecoder.decodeObject(forKey: PropertyKey.name) as! String

let category = aDecoder.decodeObject(forKey: PropertyKey.category) as! String
let value = aDecoder.decodeInteger(forKey: PropertyKey.value)
let city = aDecoder.decodeObject(forKey: PropertyKey.city) as! String
let state = aDecoder.decodeObject(forKey: PropertyKey.state) as! String

...

self.init(bonusCode: bonusCode, category: category, name: name, value: value, city: city, state: state, photo: photo)

答案 1 :(得分:1)

self.init(bonusCode: String,
          category: String,
          name: String,
          value: Int,
          city: String,
          state: String,
          photo: UIImage?)

这是函数调用,而不是函数声明 您正在将类型而不是值传递给函数调用。

你应该这样做:

self.init(bonusCode: bonusCode,
          category: category,
          name: name,
          value: value,
          city: city,
          state: state,
          photo: photo)

最后,你的init应该看起来像(略有改进):

required convenience init?(coder aDecoder: NSCoder) {
    //NOTE: `decodeObject(forKey:)` returns optional `Any` and hence all those `as? String`

    //name was missing
    let name = aDecoder.decodeObject(forKey: PropertyKey.name) as? String

    let bonusCode = aDecoder.decodeObject(forKey: PropertyKey.bonusCode) as? String
    let category = aDecoder.decodeObject(forKey: PropertyKey.category) as? String
    let value = aDecoder.decodeInteger(forKey: PropertyKey.value)
    let city = aDecoder.decodeObject(forKey: PropertyKey.city) as? String
    let state = aDecoder.decodeObject(forKey: PropertyKey.state) as? String
    let photo = aDecoder.decodeObject(forKey: PropertyKey.photo) as? UIImage

    /*
     Only photo is optional in order to init but the rest are required
     Hence the optional binding for the rest below
    */
    if let name = name,
        let bonusCode = bonusCode,
        let category = category,
        let city = city,
        let state = state {
        // Must call designated initializer.
        self.init(bonusCode: bonusCode,
                  category: category,
                  name: name,
                  value: value,
                  city: city,
                  state: state,
                  photo: photo)
    }
    else {
        /*
         Some required object/s were missing so we can't call the
         designated initializer unless we want to give default values.

         Hence return nil
         */
        return nil
    }
}