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

SwiftUI中使用searchQuery初始化MusicCatalogSearchRequest报错求助

解决SwiftUI中Cannot use instance member 'searchQuery' within property initializer错误

问题根源

你把request定义成了视图的存储属性,在视图初始化阶段就会执行闭包创建实例,但此时视图的self还未完全初始化,无法访问@State属性searchQuery,这就是报错的核心原因。

解决方案

移除静态的request属性,改为在fetchMusic函数内部,根据当前的searchQuery动态创建MusicCatalogSearchRequest实例。这样每次触发搜索时,都会使用最新的输入关键词生成请求。

修改后的完整代码:

import SwiftUI 
import MusicKit

struct songInfo: Identifiable { // List要求元素遵循Identifiable协议,补充实现
    let id = UUID()
    let name: String
    let artist: String
    let artworkColor: Color?
    let imageURL: URL?
    let imageURLSmall: URL?
    let imageURLLarge: URL?
}

struct SearchView: View {
    @State var songs = [songInfo]()
    @State var searchQuery = ""
    
    var body: some View {
        VStack {
            TextField("Search", text: $searchQuery, onCommit: {
                fetchMusic()
            })
            .padding()
            
            NavigationView {
                List(songs) { song in
                    HStack {
                        AsyncImage(url: song.imageURL)
                            .frame(width: 75, height: 75, alignment: .center)
                        VStack(alignment: .leading) {
                            Text(song.name)
                                .font(.title3)
                            Text(song.artist)
                                .font(.footnote)
                        }
                        .padding()
                    }
                }
            }
            .onAppear {
                // 初始加载可注释,避免无关键词的无效请求
                // fetchMusic()
            }
        }
    }

    private func fetchMusic() {
        // 过滤空关键词,避免无效请求
        guard !searchQuery.trimmingCharacters(in: .whitespaces).isEmpty else {
            songs = []
            return
        }
        
        Task {
            let status = await MusicAuthorization.request()
            switch status {
            case .authorized:
                do {
                    // 每次搜索时用当前searchQuery创建请求
                    var request = MusicCatalogSearchRequest(term: searchQuery, types: [Song.self])
                    request.limit = 25
                    
                    let result = try await request.response()
                    songs = result.songs.compactMap({
                        .init(name: $0.title,
                              artist: $0.artistName,
                              artworkColor: $0.artwork?.backgroundColor,
                              imageURL: $0.artwork?.url(width: 75, height: 75),
                              imageURLSmall: $0.artwork?.url(width: 256, height: 256),
                              imageURLLarge: $0.artwork?.url(width: 1028, height: 1028))
                    })
                    
                    songs.first.map { print($0) }
                } catch {
                    print("搜索出错:\(error.localizedDescription)")
                }
            default:
                print("未获得音乐库访问权限")
            }
        }
    }
}

#Preview {
    SearchView()
}

额外优化点

  1. 给songInfo补充Identifiable协议实现,满足List的元素要求
  2. 增加空关键词过滤逻辑,避免无意义的API请求
  3. 优化错误信息打印,便于调试
  4. 注释掉初始加载的搜索调用,可根据需求自行开启

内容的提问来源于stack exchange,提问作者Boomarov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 20:35:09