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

Swift中‘buildExpression’静态方法无匹配错误及视频关联问题

Swift流媒体应用视频匹配播放错误修复

我是Swift新手,正在开发一款流媒体应用。此前将本地视频播放按钮改为跳转至另一Swift文件实现播放,当前使用JSON存储节目名称、图片、视频等信息,希望程序能根据节目名称或ID匹配对应视频播放。

JSON节目结构

"id": "EDCD038C-036F-4C40-826F-61C88CD84DDD",
"name": "Best ouf",
"photoCredit": "Image - Petite",
"mainPicture": "20230331_143548",
"price": 6,
"video": "denoise filml de term 2",
"restrictions": ["G", "V"],
"description": "Sweet, fluffy, and served piping hot, our French toast is flown in fresh every day from Maple City, Canada, which is where all maple syrup in the world comes from. And if you believe that, we have some land to sell you…"

节目详情页代码

struct ItemDetail: View {
    let item: MenuItem
    @EnvironmentObject var order: Order
    var body: some View {
        VStack {
            ZStack{
                Image(item.mainPicture)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
            }
            Text(item.description)
                .padding()
            
            NavigationLink(destination: ItemVideo()) {
                Text("watch")
            }
            .buttonStyle(.borderedProminent)
            Spacer()
            
        }
        .navigationTitle(item.name)
        .navigationBarTitleDisplayMode(.inline)
        
    }
}

struct ItemDetail_Previews: PreviewProvider {
    static var previews: some View {
        NavigationStack{
            ItemDetail(item: MenuItem.example)
                .environmentObject(Order())
        }
    }
}

视频播放页代码(原错误版本)

import AVKit
import SwiftUI
var strVideos = String().self
let menu = Bundle.main.decode([MenuSection].self, from: "menu.json")
var body: some View {
    ForEach(menu) { section in
        Section(section.name) {
            ForEach(section.items) { item in
                strVideos = item.video
            }
        }
    }
}
struct ItemVideo: View {
    let videoUrl = URL(fileURLWithPath: Bundle.main.path(forResource: strVideos, ofType: "mov")!)
    
    var body: some View {
        VideoPlayer(player: AVPlayer(url: videoUrl)) // 3
    }
    
}

遇到的错误

代码中strVideos = item.video一行出现编译错误:No exact matches in reference to static method 'buildExpression'


修复方案

错误原因

你当前的代码逻辑完全不符合SwiftUI语法规范:

  • 游离的body不属于任何View结构体,SwiftUI不允许这种写法
  • 在ForEach中直接给全局变量赋值,会导致视图渲染逻辑混乱,这是报错的直接原因
  • 使用全局变量传递视频文件名的方式,容易引发状态不一致的问题

正确实现步骤

  1. 修改ItemVideo结构体,接收视频文件名参数
import AVKit
import SwiftUI

struct ItemVideo: View {
    // 接收从详情页传递过来的视频文件名
    let videoFileName: String
    
    // 延迟加载视频URL,确保参数传入后再初始化,同时增加容错处理
    private var videoUrl: URL {
        guard let filePath = Bundle.main.path(forResource: videoFileName, ofType: "mov") else {
            fatalError("找不到视频文件:\(videoFileName).mov")
        }
        return URL(fileURLWithPath: filePath)
    }
    
    var body: some View {
        VideoPlayer(player: AVPlayer(url: videoUrl))
    }
}
  1. 在详情页的NavigationLink中传递视频文件名
    修改ItemDetail中的NavigationLink代码:
NavigationLink(destination: ItemVideo(videoFileName: item.video)) {
    Text("watch")
}
.buttonStyle(.borderedProminent)
  1. 删除错误的冗余代码
    删掉原播放页中那些游离的全局变量和无效body:
// 以下代码全部删除
var strVideos = String().self
let menu = Bundle.main.decode([MenuSection].self, from: "menu.json")
var body: some View {
    ForEach(menu) { section in
        Section(section.name) {
            ForEach(section.items) { item in
                strVideos = item.video
            }
        }
    }
}

方案说明

这种通过视图传参的方式,直接把当前节目对应的视频文件名精准传递给播放页面,完全符合SwiftUI的单向数据流逻辑,既解决了编译错误,也避免了全局变量带来的状态混乱问题,同时保证了视频匹配的准确性。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 22:25:07