使用 SwiftUI List()、ForEach()、.onTapGesture WatchOS6 传递值的问题

Posted

技术标签:

【中文标题】使用 SwiftUI List()、ForEach()、.onTapGesture WatchOS6 传递值的问题【英文标题】:Problem passing value with SwiftUI List(), ForEach(), .onTapGesture WatchOS6 【发布时间】:2019-12-19 14:11:01 【问题描述】:

我正在尝试使用 .onTapGesture() 调用被点击视图上的方法并传递某种 ID 或任何其他形式的标识符,但我不知道如何。

我有一个视图 ListView,它是根据从数组 trackPreviewList: [TrackpreviewList] 获取的数据创建的。

视图如下所示:

struct ListView: View 
    @ObservedObject var model: PlaybackService
    @State var list = PlaybackService.sharedInstance.trackPreviewList

var body: some View 
        List 
            Section(header: Text("Songs")) 
                ForEach(model.trackPreviewList!, id: \.id) 
                    Text($0.artistName + ": " + $0.name)
                 
                    .onDelete(perform: deleteTrack)
                    .onTapGesture(perform: skipTo)
            
        
    

我对 SwiftUI 和一般编码非常陌生,但我认为正确的方法是说单元格(视图?) 2 已被点击,因此将 2 传递给方法func playerSkipTo(skipToIndex: Int) 我尝试将值 2 硬编码为这适用于硬编码值:

虽然我对如何传递某种标识符一无所知,但我认为我的问题是我试图访问该方法“知道它”的范围之外的对象。 我试图使用 $0.name 变量来查看是否可以传递任何内容,但我收到此错误Contextual closure type '() -> Void' expects 0 arguments, but 1 was used in closure body 我认为这是因为 .onTapGesture() 方法没有闭包?。

我尝试使用与使用 IndexSet 的 .onDelete() 方法相同的逻辑,如下所示:

最后我想将值传递给的方法如下所示:

func playerSkipTo(skipToIndex: Int) 
        if skipToIndex < ((trackPreviewList!.underestimatedCount)-1) 
            _ = firstly 
                TracklistProvider.sharedInstance.getPlaybackURL(trackPreview: trackPreviewList![skipToIndex])
            .map  playbackoptions in
                self.createPlayerItemFromLink(assetURL: (playbackoptions?.playbackUrl)!)
            .done
                self.replacePlayerItem()
            
         else 
            print("The index \(skipToIndex) is out of bounds")
        
    

我知道我将需要更改 playerSkipTo() 方法以接收 IndexSet,我也尝试过尝试将其转换为 Int 等。

非常感谢任何帮助或指点!

Heres the playerSkipTo method:

        if skipToIndex < ((trackPreviewList!.underestimatedCount)-1) 
            _ = firstly 
                TracklistProvider.sharedInstance.getPlaybackURL(trackPreview: trackPreviewList![skipToIndex])
            .map  playbackoptions in
                self.createPlayerItemFromLink(assetURL: (playbackoptions?.playbackUrl)!)
            .done
                self.replacePlayerItem()
            
         else 
            print("The index \(skipToIndex) is out of bounds")
        
    

【问题讨论】:

【参考方案1】:

不是跳到索引,而是跳到特定的轨道对象:

func playerSkipTo(_ playbackoptions: PlaybackOptions) 
   // ...

然后更改您的视图代码以在 Text 而不是 ForEach 上调用此函数:

List 
    Section(header: Text("Songs")) 
        ForEach(model.trackPreviewList!, id: \.id) 
            Text($0.artistName + ": " + $0.name)
                .onTapGesture 
                    self.playerSkipTo($0)
                
        
    

【讨论】:

嘿@Yonat,感谢您的回答。我尝试了你告诉我的,但这让我回到了我之前遇到的另一个错误。 Type '_' has no member 'id' TrackPreviews 不符合 Identifiable,所以我必须指定如何使用 id 参数来识别它们。此外,TrackPreviews 是我在以前的实习中使用的 API 客户端的一部分,因此我无法更改或将协议添加到模型中。我尝试制作模型的副本并使用它,但这需要我跟踪两个数组,因为我需要一个用于显示,一个用于对后端的请求 当我尝试输入硬编码值时,我得到这个错误:Value of type 'ListView' has no member 'playerSkipTo' TrackPreview 有哪些成员?您可以使用其中之一来识别轨道吗?例如:var id: String self.url.absoluteString 至于缺少playerSkipTo:先添加那个函数,然后调用即可。 TrackPreviewpublic let id: IntplayerSkipTomethod 在我的 PlaybackService 中,我会将其添加到我的问题的底部,以便您查看。再次感谢您的宝贵时间,我真的被困住了。【参考方案2】:

您可以使用 ZStack 顶部的按钮:

        List
            ForEach(appData.assets)  asset in
                ZStack 
                    HStack
                        VStack(alignment: .leading) 
                            Text(asset.value)
                                .font(.headline)
                        
                        Spacer()
                    
                    Button(action: assetPressed(id: asset.id), label: 
                        Text("")
                    )
                
            
            .onDelete(perform: deleteAsset)
        

【讨论】:

以上是关于使用 SwiftUI List()、ForEach()、.onTapGesture WatchOS6 传递值的问题的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI 使用 List 和 Foreach 遍历字典中的键并创建列表视图

使用 SwiftUI List()、ForEach()、.onTapGesture WatchOS6 传递值的问题

SwiftUI:List/ForEach 中的滑块行为异常

SwiftUI 的 List/ForEach 视图中是不是可以有一个 Button(action: -)

带有 Xcode 11 beta 7 的 SwiftUI 未更新 List / ForEach 的内容

SwiftUI:当 List 和 ForEach 嵌入 TabView 时 WatchOS 8.1 中的 NavigationView 错误