Xcode 一直说
“ContentView”的重新声明无效 实例将立即被释放,因为属性“navigationDelegate”为“weak”*“weak”只能应用于类和类绑定协议类型,而不是“FilesView”*“WebViewCoordinator”类型的值没有成员“getDocumentsDirectory”*值类型“WebViewCoordinator”没有成员“sanitizeFileName” 类型“[URLResourceKey: Any]”的值没有成员“totalFileAllocationSize”
代码如下:l
`
import SwiftUI
import WebKit
@main
struct UDOWNLOADERZApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
var body: some View {
TabView {
BrowserView()
.tabItem {
Label("Browser", systemImage: "globe")
}
FilesView()
.tabItem {
Label("Files", systemImage: "folder")
}
SettingsView()
.tabItem {
Label("Settings", systemImage: "gearshape")
}
}
}
}
struct BrowserView: View {
@State private var webView = WKWebView()
var body: some View {
WebView(webView: $webView)
.onAppear {
let urls = ["https://youtube.com", "https://soundcloud.com"]
for url in urls {
if let url = URL(string: url) {
let request = URLRequest(url: url)
webView.load(request)
}
}
webView.navigationDelegate = WebViewCoordinator(filesView: nil)
}
}
}
struct WebView: UIViewRepresentable {
@Binding var webView: WKWebView
func makeUIView(context: Context) -> WKWebView {
return webView
}
func updateUIView(_ uiView: WKWebView, context: Context) {}
}
class WebViewCoordinator: NSObject, WKNavigationDelegate {
weak var filesView: FilesView?
init(filesView: FilesView?) {
self.filesView = filesView
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
let jsCode = """
(function() {
var video = document.querySelector('video');
var audio = document.querySelector('audio');
var mediaElement = video || audio;
if (mediaElement) {
return {
src: mediaElement.src,
title: document.title || mediaElement.getAttribute('title') || 'Unknown'
};
}
return null;
})();
"""
webView.evaluateJavaScript(jsCode) { [weak self] (result, error) in
guard let resultDict = result as? [String: String], let urlString = resultDict["src"], let title = resultDict["title"], let url = URL(string: urlString) else { return }
self?.downloadContent(url: url, title: title)
}
}
func downloadContent(url: URL, title: String) {
DispatchQueue.global().async {
let destinationURL = getDocumentsDirectory().appendingPathComponent("\(sanitizeFileName(fileName: title)).mp4")
URLSession.shared.downloadTask(with: url) { [weak self] (tempURL, response, error) in
guard let self = self, let tempURL = tempURL, error == nil else { return }
do {
try FileManager.default.moveItem(at: tempURL, to: destinationURL)
DispatchQueue.main.async {
NotificationCenter.default.post(name: NSNotification.Name("DownloadCompleted"), object: nil)
self.filesView?.reloadFilesList()
}
} catch {
print("Download failed: \(error.localizedDescription)")
}
}.resume()
}
}
}
struct FilesView: View {
@State private var downloadedFiles = [String]()
@State private var storageTaken: String = ""
var body: some View {
VStack {
List {
ForEach(downloadedFiles, id: \.self) { file in
Text(file)
}
}
Text("Storage Taken: \(storageTaken)")
}
.onAppear(perform: loadFiles)
.onReceive(NotificationCenter.default.publisher(for: NSNotification.Name("DownloadCompleted"))) { _ in
loadFiles()
}
}
func loadFiles() {
DispatchQueue.global().async {
do {
let files = try FileManager.default.contentsOfDirectory(at: getDocumentsDirectory(), includingPropertiesForKeys: nil, options: [])
DispatchQueue.main.async {
downloadedFiles = files.map { $0.lastPathComponent }
calculateStorageTaken(files: files)
}
} catch {
print("Failed to load files: \(error.localizedDescription)")
}
}
}
func reloadFilesList() {
loadFiles()
}
private func calculateStorageTaken(files: [URL]) {
let size = files.reduce(0, { $0 + ($1 as NSURL).fileSize() })
storageTaken = ByteCountFormatter.string(fromByteCount: Int64(size), countStyle: .file)
}
}
struct SettingsView: View {
var body: some View {
VStack {
Text("Contact: [email protected]")
Text("Twitter: N/A")
}
}
}
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
return paths[0]
}
func sanitizeFileName(fileName: String) -> String {
let invalidCharacters = CharacterSet(charactersIn: "\\/:*?\"<>|")
return fileName.components(separatedBy: invalidCharacters).joined(separator: "_")
}
extension NSURL {
func fileSize() -> Int {
guard`
`
我尝试重新调整代码,但仍然不起作用。
Invalid redeclaration of 'ContentView’
。在项目的某个地方,有另一个 ContentView 声明。在 Swift 中,不允许有多个同名的类、结构或协议。您应该找到它并删除或重命名。Instance will be immediately deallocated because property 'navigationDelegate' is 'weak’
。如果你写weak var
,则表明你想维护一个对象的弱引用。然而,该对象必须至少有一个强引用,否则它将立即被释放。在您的情况下,您必须在具有强引用的地方保留 WebViewCoordinator,例如 var webViewCoordinator: WebViewCoordinator
,然后将其分配给委托属性。'weak' may only be applied to class and class-bound protocol types, not 'FilesView’
。在 Swift 中,只有引用类型可以有弱引用。由于 Swift 中的结构是值类型,因此不能对它们使用弱引用。在您的场景中,存在一些概念上的误解。如果您想重新加载视图,则无需将视图传递给另一个类。getDocumentsDirectory
、sanitizeFileName
和 totalFileAllocatedSize
相关的错误的反馈,因为在您的示例中,您已将它们移动到不再产生错误的位置。总而言之,考虑通过引入 ViewModel 和服务来重构您的架构。例如,您可以创建一个服务来处理
getDocumentsDirectory
和 sanitizeFileName
等方法,并在必要时使用该服务。
此外,创建一个 ViewModel 并将其传递给“WebViewCoordinator”和“FilesView”。然后协调器可以请求文件重新加载,并且“FilesView”可以从 ViewModel 检索重新加载的文件。