如何解决这个问题“演员隔离属性‘频道’无法从主要演员引用”

问题描述 投票:0回答:1

我写了一个actor,允许我在线下载和解析一些数据,该函数下载数据并将结果附加到通道数组中。


actor BackgroundParser : ObservableObject {
   
    @Published var channels : [String: [PlaylistItem]] = [:]
    
    let parser = PlaylistParser()
 
    
   
    func fetchOnMemory(lista: PlayListModel,url: String ,_ completion: @escaping (_ isdownloading:Bool) -> Void) async  {
        guard let m3uURL = URL(string: url) else {return}
        completion(true)
        var counter = 0
        
        AF.request(m3uURL).responseString { response in
            switch response.result {
            case .success(let m3uContent):
                do{
                    let playlist = try self.parser.parse(m3uContent)
                    
                    let media = playlist.medias
                    print("QUESTA LISTA CONTIENE \(media.count)")
                    for item in media {
                        let  duration = item.duration
                        let attributes = item.attributes
                        let tvgId = attributes.id
                        let tvgName = attributes.name
                        let tgvcountry = attributes.country
                        let tvglanguage = attributes.language
                        let tvgLogo = attributes.logo
                        let tvgchno = attributes.channelNumber
                        let tvgShift = attributes.shift
                        let groupTitle = attributes.groupTitle
                        let seasonNumber = attributes.seasonNumber
                        let episodeNumber = attributes.episodeNumber
                        let kind = item.kind.rawValue
                        let url = item.url
                        let def : String = "XXX"
                        print("\(counter) of \(media.count)-- id: \(tvgId ?? def) -- name: \(tvgName ?? def) -Title: \(groupTitle ?? def)")
                        let playlistItem = PlaylistItem(duration: duration, tvgId: tvgId, tvgName: tvgName, tvgcountry: tgvcountry, tvglanguage: tvglanguage, tvgLogo: tvgLogo, tvgchno: tvgchno, tvgshift: tvgShift, groupTitle: groupTitle ?? "NOT CLASSIFIED", seasonNumber: seasonNumber, episodeNumber: episodeNumber, kind: kind, url: url)
                        
                        
                        self.updateChannelList(with: playlistItem)
                        
                        //                            print("parse-------\(counter)--\(String(describing: tvgName))")
                        counter += 1
                    }
                    
                    completion(false)
                    
                    
                } catch {
                    completion(true)
                    print("FAIL CATCH")
                }
            case .failure(let error):
                completion(true)
                print("Failed to fetch m3u content: \(error)")
            }
        }
    }
    
    
   
  
    
    func updateChannelList(with playlistItem: PlaylistItem) {
        // Assuming listofChannel is a class-level or instance-level variable
        // and you want to modify it in-place

        // Check if the groupTitle already exists in the dictionary
        if var existingPlaylist = channels[playlistItem.groupTitle] {
            // If it exists, append the new playlist item
            existingPlaylist.append(playlistItem)
            channels[playlistItem.groupTitle] = existingPlaylist
        } else {
            // If it doesn't exist, create a new key with an array containing the playlist item
            channels[playlistItem.groupTitle] = [playlistItem]
        }
    }
}


我现在尝试在视图中显示数据,但收到错误“无法从主要参与者引用参与者隔离属性“通道””。

struct ListViewDetails: View {
   
   
  
    @State var isLoading = true
    @StateObject var parser = BackgroundParser()
    let columns = [
        GridItem(.fixed(300)),GridItem(.fixed(300)),GridItem(.fixed(300)),GridItem(.fixed(300)),GridItem(.fixed(300)),GridItem(.fixed(300)),
       ]
    
    var body: some View {
        
        
        if isLoading {
            ProgressView("Fetching Data...")
                .progressViewStyle(CircularProgressViewStyle())
        }
            ScrollView(.vertical){
                LazyVGrid(columns: columns,alignment: .center,spacing: 20) {
                  
                    ForEach(parser.channels.sorted(by: { $0.key < $1.key }), id: \.key)  { group , channels in
                        DetailsChannelGroup(group:  group, channels: channels)
                           
                    }
                }
            }
            
            .task {
               
            
                await parser.fetchOnMemory(lista: item, url: item.playlistUrl) { isdownloading in
                    
                    isLoading = isdownloading
                    
                }

                
            }

}

}

每个循环都会出现错误,因为我尝试访问已发布的数组。

我怎样才能得到这些数据?

swift swiftui async-await task
1个回答
0
投票

您将太多概念混合在一起:完成、异步等待、组合。我可以重构上面的代码,仅在您使用 Alamofire 时才使用

@Published
,并绕过一个步骤:将 AF 完成包装为异步等待。 SwiftUI 中的
View
的作用类似于 ViewModel,因此我们只需要在这里进行数据绑定。
@Published
当 View 的值发生变化时,会大声喊出重新渲染 View,并且还会在此处删除完成。

final class BackgroundParser: ObservableObject {
  @Published var isLoading = false
  @Published var channels: [String: [PlaylistItem]] = [:]
  
  func fetchOnMemory(lista: PlayListModel,url: String)  {
    isLoading = true
    //fetch and sort channels here
    isLoading = false
  }
}
@StateObject private var parser = BackgroundParser()

var body: some View {
  ...
  .onAppear {
    parser.fetchOnMemory()
  }
}

输出应该类似于:

© www.soinside.com 2019 - 2024. All rights reserved.