You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 15:54:50