Swift类报错:MasjidList.swift:13:43 表达式类型需类型注解
错误原因及解决方法
1. 错误分析(MasjidList.swift:13:43)
错误Type of expression is ambiguous without a type annotation出现在ObjectIdentifier(.self)部分:
- 在类的静态属性初始化阶段(定义
masjidList数组时),.self的指代不明确,编译器无法判断你要获取的是MasjidList类的类型标识,还是类实例的标识。 - 更关键的是,这里用
ObjectIdentifier(.self)作为MasjidDescription的id完全不合理——所有初始化的清真寺实例都会共享同一个id(基于MasjidList类的类型生成),违背了id作为唯一标识的意义。
2. 错误修复方案
把所有ObjectIdentifier(.self)替换为UUID(),让每个MasjidDescription实例拥有独立的唯一ID:
// 原错误代码 MasjidDescription(id: ObjectIdentifier(.`self`), ...) // 修复后代码 MasjidDescription(id: UUID(), ...)
如果MasjidDescription的id类型必须是ObjectIdentifier,则明确指定.self的类型:
MasjidDescription(id: ObjectIdentifier(MasjidList.self), ...)
推荐用UUID(),更符合业务场景中唯一标识的需求。
3. 实现清真寺选择器(Picker)并获取经纬度
3.1 调整数据模型结构
将MasjidList改为遵循ObservableObject的类,让SwiftUI可以监听数据变化:
import Foundation import SwiftUI // 定义清真寺数据结构体(需提前实现) struct MasjidDescription: Identifiable, Hashable { let id: UUID let masjid_id: UUID let masjid_webid: Int let masjid_name: String let user_id: Int let masjid_add_1: String let masjid_local_area: String let masjid_larger_area: String let masjid_post_code: String let masjid_telephone: String let masjid_country: String let latitude: Double let longitude: Double let masjid_created: String let masjid_modified: String let status: Bool let country_code: String let full_country: String let timeZone: String // 遵循Swift小驼峰命名规范,替换原大写开头的TimeZone let plusminusGMT: Int } class MasjidList: ObservableObject { @Published var masjidList: [MasjidDescription] = [] @Published var selectedMasjid: MasjidDescription? // 绑定Picker选中项 init() { // 初始化清真寺数据,用UUID作为每个实例的唯一id masjidList = [ MasjidDescription(id: UUID(), masjid_id: UUID(), masjid_webid: 1, masjid_name: "Masjid-E-Umer", user_id: 731, masjid_add_1: "79 Queens Road", masjid_local_area: "Walthamstow", masjid_larger_area: "London", masjid_post_code: "E17 8QR", masjid_telephone: "2085202658", masjid_country: "UK", latitude: 51.5784686402568, longitude: -0.0233741667985488, masjid_created: "2015-06-01 13:07:52", masjid_modified: "2020-09-21 12:29:15", status: true, country_code: "UK", full_country: "United Kingdom", timeZone: "GMT", plusminusGMT: 0), MasjidDescription(id: UUID(), masjid_id: UUID(), masjid_webid: 2, masjid_name: "Chingford Masjid,142", user_id: 92, masjid_add_1: "92 Chingford Mount Road", masjid_local_area: "Chingford", masjid_larger_area: "London", masjid_post_code: "E4 9AA", masjid_telephone: "020 8523 5826", masjid_country: "UK", latitude: 51.610806, longitude: -0.017989, masjid_created: "2015-06-03 18:55:22", masjid_modified: "2020-02-01 17:00:48", status: true, country_code: "UK", full_country: "United Kingdom", timeZone: "GMT", plusminusGMT: 0), MasjidDescription(id: UUID(), masjid_id: UUID(), masjid_webid: 5, masjid_name: "Lentrica Masjid", user_id: 303, masjid_add_1: "525 London Road", masjid_local_area: "Len Area", masjid_larger_area: "Len City", masjid_post_code: "CR7 6AR", masjid_telephone: "2082797895", masjid_country: "UK", latitude: 51.389457, longitude: -0.112676, masjid_created: "2014-09-27 07:55:58", masjid_modified: "2017-12-23 13:02:48", status: false, country_code: "UK", full_country: "United Kingdom", timeZone: "GMT", plusminusGMT: 0) ] // 默认选中第一个清真寺 selectedMasjid = masjidList.first } }
3.2 实现Picker视图
创建SwiftUI视图,用Picker展示清真寺名称,绑定选中项后即可直接获取经纬度:
struct MasjidPickerView: View { @StateObject private var masjidData = MasjidList() var body: some View { VStack(spacing: 20) { Picker("选择清真寺", selection: $masjidData.selectedMasjid) { ForEach(masjidData.masjidList) { masjid in Text(masjid.masjid_name).tag(masjid as MasjidDescription?) } } .pickerStyle(.menu) // 可根据需求更换样式,比如.wheel // 展示选中清真寺的经纬度 if let selected = masjidData.selectedMasjid { VStack(alignment: .leading) { Text("选中的清真寺: \(selected.masjid_name)") Text("纬度: \(selected.latitude)") Text("经度: \(selected.longitude)") } .padding() // 调用祈祷时间计算逻辑 Button("计算祈祷时间") { calculatePrayerTimes(latitude: selected.latitude, longitude: selected.longitude) } } } .padding() } // 模拟祈祷时间计算函数 func calculatePrayerTimes(latitude: Double, longitude: Double) { // 替换为你的祈祷时间计算库逻辑 print("计算纬度\(latitude),经度\(longitude)的祈祷时间") } }
3.3 注意事项
MasjidDescription遵循Identifiable协议,是为了让ForEach可以直接遍历数组;如果不遵循,可在ForEach中指定id参数:ForEach(masjidData.masjidList, id: \.id)- 原代码中
MasjidList的Hashable实现无实际意义,改为ObservableObject更符合SwiftUI的数据流逻辑
内容的提问来源于stack exchange,提问作者Andy
相关产品推荐
相关产品推荐

