Expression pattern of type 'String' cannot

2019-01-27 05:03发布

I'm trying to convert my Swift 3 code to Swift 4. I get this error message:

Expression pattern of type 'String' cannot match values of type 'NSStoryboardSegue.Identifier

This is my code:

override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
    switch segue.identifier {

        case "showVC1":
            // DO SOMETHING
            break

        default:
            break
    }
}

Which type should I use instead of "String"?

2条回答
相关推荐>>
2楼-- · 2019-01-27 05:45

As of Swift 4, the storyboard identifier is a optional NSStoryboardSegue.Identifier, which is defined as

extension NSStoryboardSegue {
    public struct Identifier : RawRepresentable, Equatable, Hashable {
        public init(_ rawValue: String)
        public init(rawValue: String)
    }
}

You can switch on its rawValue:

    switch segue.identifier?.rawValue {
    case "showVC1"?:
        // do something ...
    default:
        break
    }

The recommended pattern however is to define constants for each storyboard identifier:

extension NSStoryboardSegue.Identifier {
    static let showVC1 = NSStoryboardSegue.Identifier("showVC1")
    // other storyboard identifiers ...
}

which can then be matched against:

    switch segue.identifier {
    case .showVC1?:
        // do something ...
    default:
        break
    }

In both examples, the "optional pattern" x? (a shortcut for .some(x)) is used to match against an optional value.

Similar types were introduced for other "identifiers", e.g. NSImage.Name, which is the argument type of NSImage(named:) in Swift 4.

For more information, see the discussion on the swift-users mailing list, starting at

The general idea (as I understand it) is to create separate types for each kind of identifier. In particular (from https://lists.swift.org/pipermail/swift-users/Week-of-Mon-20170717/005940.html):

... We are deliberately discouraging the string literal of the name. The string literal should be in only one place: the definition of the name constant. Everything else should use the constant. The compiler can provide autocompletion and typo detection of the constant. The string literal doesn't get that.

查看更多
爱情/是我丢掉的垃圾
3楼-- · 2019-01-27 05:50

Swift 4 switched the type of identifier property from String? to NSStoryboardSegue.Identifier?. The type is RawRepresentable, RawType of String. You may need to change your code to a chain of if statements, or use rawValue explicitly:

switch segue.identifier {
    case let x where x.rawValue == "showVC1":
        // DO SOMETHING
    break
    default:
    break
}
查看更多
登录 后发表回答