Reputation: 576
I'm clearly missing something. I would like to do something similar to the Files app in iOS where I can traverse a network server's file tree starting at a share point. I can access the share in the actual Files app just fine but cannot seem to replicate that in my own app. If I test this app in the simulator I can access the file tree on the machine where the simulator resides but the same app on a device can't get to the server's share.
In the example below, the function to connect is below the UI code and in it I first try to call FileManager.default.mountedVolumeURLs and when that fails, which it always does, I call FileManager.default.contentsOfDirectory which demonstrates the above mentioned behavior.
import SwiftUI
import Foundation
struct NetFilesView: View
{
@State var urls: [URL] = []
@State var serverType = "afp"
@State var server = "server"
@State var share = ""
@State var user = ""
@State var password = ""
@State var errormsg = "Enter server, share, user and password"
var body: some View
{
VStack
{
HStack
{
VStack
{
HStack
{
HStack
{
Picker("Server type", selection: $serverType)
{
ForEach("afp,smb,nfs".components(separatedBy: ","), id: \.self)
{
Text($0)
}
}
TextField("Server", text: $server)
.autocapitalization(.none)
}
SecureField("User", text: $user).autocapitalization(.none)
}
HStack
{
TextField("Share", text: $share)
.autocapitalization(.none)
SecureField("Password", text: $password)
.autocapitalization(.none)
}
}
Button("Go")
{
do
{
urls = try connectToNetworkDrive(shareType: serverType, serverAddress: server, sharePath: share, user: (user == "") ? nil : user, password: (password == "") ? nil : password)
errormsg = "Success"
}
catch
{
errormsg = error.localizedDescription
}
}.buttonStyle(.bordered).tint(Color.green)
}
.padding()
.border(Color.red, width: 1)
List(urls, id:\.self)
{ url in
Text(url.lastPathComponent)
.onTapGesture
{
do
{
if let isDir = (try url.resourceValues(forKeys: [.isDirectoryKey])).isDirectory
{
if !isDir
{
// do something with file
} else
{
share = url.relativeString.replacingOccurrences(of: "file:///", with: "").removingPercentEncoding ?? ""
}
}
}
catch
{
errormsg = error.localizedDescription
}
}
.id(url.lastPathComponent)
//self.returnFunction(url)
}
Text(errormsg)
.background(Color.red).foregroundStyle(Color.white)
}
.padding()
}
}
#Preview
{
NetFilesView()
}
func connectToNetworkDrive(shareType: String = "afp", serverAddress: String, sharePath: String, user: String? = nil, password: String? = nil) throws -> [URL]
{
var uc = URLComponents()
uc.scheme = shareType
uc.host = serverAddress
uc.path = (sharePath.starts(with: "/")) ? sharePath : "/" + sharePath
uc.user = user
uc.password = password
print(uc.url ?? "Bad URL")
if let networkDriveURL = uc.url
{
if let urls = FileManager.default.mountedVolumeURLs(includingResourceValuesForKeys: nil)
{
let isMounted = urls.contains(where: { $0.path == networkDriveURL.path })
if !isMounted
{
print("Network drive not mounted")
} else
{
print("Network drive successfully accessed")
return urls
}
} else
{
print("No share at: \(networkDriveURL.absoluteString)")
}
let urls = try FileManager.default.contentsOfDirectory(at: networkDriveURL, includingPropertiesForKeys: nil)
return urls
}
return []
}
Upvotes: 0
Views: 25