能否通过变量值调用Swift结构体中的成员变量?
你原来的写法行不通,因为Swift是静态类型语言,不能通过字符串插值直接动态访问结构体属性,编译器无法在编译阶段解析audio.\(soundSelect)这种语法,所以会抛出"Expected member name following '.'"错误。
下面提供两种可行的解决思路:
方法一:用KeyPath(推荐,类型安全)
把soundSelect参数改为KeyPath<Audio, String>,既保留编译时类型检查,又能灵活指定要访问的属性:
func playSound(audio: Audio, soundSelect: KeyPath<Audio, String> = \.startSound) { let soundName = audio[keyPath: soundSelect] if let path = Bundle.main.path(forResource: soundName, ofType: audio.soundType) { do { audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: path)) audioPlayer?.play() } catch { print("ERROR: Could not find and play the sound file!") } } } // 调用示例 let audioConfig = Audio() playSound(audio: audioConfig) // 默认播放startSound playSound(audio: audioConfig, soundSelect: \.endSound) // 指定播放endSound
这种方法的优势是类型安全,如果传入不存在的KeyPath,编译器会直接报错,避免运行时错误。
方法二:字符串映射(兼容原字符串参数需求)
如果一定要用字符串作为参数,可以在Audio结构体中添加映射逻辑,将字符串关联到对应的属性值:
struct Audio { var startSound: String = "happyMusic" var endSound: String = "sadMusic" var soundType: String = "mp3" // 新增映射方法 func soundName(for key: String) -> String? { switch key { case "startSound": return startSound case "endSound": return endSound default: return nil } } } // 修改playSound函数 func playSound(audio: Audio, soundSelect: String = "startSound") { guard let soundName = audio.soundName(for: soundSelect) else { print("ERROR: Invalid sound selection!") return } if let path = Bundle.main.path(forResource: soundName, ofType: audio.soundType) { do { audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: path)) audioPlayer?.play() } catch { print("ERROR: Could not find and play the sound file!") } } }
这种方法保留了字符串参数的调用方式,但后续新增音效属性时,需要同步更新soundName(for:)方法里的switch分支。
另外注意:你原代码中的try!会在初始化失败时直接崩溃,改为try配合do-catch块能更安全地处理错误。
内容的提问来源于stack exchange,提问作者VirtualYogi
相关产品推荐
相关产品推荐

