我创建了一个玩具问题,以了解为什么向下转换后无法设置属性的值。问题出在视图控制器3中:我想为属性artist
分配一个值。
import Foundation
protocol MediaType {
var year: String? { get set }
}
struct Song: MediaType {
var artist: String?
var musicians: [String]?
// Implement Protocol `MediaType`
var year: String?
}
class MediaStateController {
var media: MediaType?
}
//
// view controller 1: controller does not know the media type just yet.
//
let stateController = MediaStateController() // media remains nil for now
print(stateController.media is Song) // false
//
// view controller 2: knows the media type so it can assign the media type.
//
stateController.media = Song()
print(stateController.media is Song) // true
print(stateController.media as? Song) // Optional(Song(artist: nil, musicians: nil, year: nil))
print(stateController.media) // Optional(Song(artist: nil, musicians: nil, year: nil))
print(type(of: stateController.media)) // Optional<MediaType>
// view controller 3: knows only the artist name but not the musicians.
if var song = stateController.media as? Song {
song.artist = "SomeArtist" // ISSUE: this does not set the value (see print-out below)
}
print(stateController.media as? Song) // Optional(Song(artist: nil, musicians: nil, year: nil))
if var song = stateController.media as? Song {
// makes no sense to not use song, but let's do it anyway.
// (stateController.media as? Song)?.artist = "SomeArtist" // error: cannot assign to immutable expression of type 'String?'
}
print(stateController.media as? Song) // Optional(=Song(artist: nil, musicians: nil, year: nil))
if var song = stateController.media as? Song {
// THIS DOES SET THE VALUE, but why?
song.artist = "SomeArtist"
stateController.media = song
}
print(stateControllaer.media as? Song) // Optional(Song(artist: Optional("SomeArtist"), musicians: nil, year: nil))
Song
是一个结构,这是Swift中的值类型。在此示例中:
// view controller 3: knows only the artist name but not the musicians.
if var song = stateController.media as? Song {
song.artist = "SomeArtist" // ISSUE: this does not set the value (see print-out below)
}
您正在将原始Song
实例复制到新的变量中,然后更新该副本的artist
属性。一旦退出if var
的范围,该副本就会被丢弃。