Hello, I am relatively new to iOS development and am trying to learn by creating an app to connect to my SMB server to view and manipulate files. I am aware that the built in Files app has SMB capabilities, but I wanted to take a crack at building my own as I saw a few shortcomings and places where it could be improved.
Anyway, I am running into a weird issue. I am working on the functionality that would show the user any particular image that they choose in a fullscreen view. The code seems to be streaming in the image and displaying it just fine, and the Xcode Preview would seem to be confirming that. However, my device will not, under any circumstances display the Image! I have tried with multiple images, and also building the app and running it independently of Xcode, which points to an issue with my code. But then why is the Xcode Preview displaying the Image just fine? I also tried adding a Text view just to make sure the view as whole was updating properly and it was, the Text view displayed just fine. I understand that I'm on beta software, so if this is a bug with Xcode itself, or iOS, then no complaints here! I'll just try and find a way to work around it. I'm really only posting this to make sure it's not user error! I'll also attach my code of course, as well as a couple of screenshots just so you know I'm not crazy. Thanks!
I tried to take a screenshot of the whole editor for you because usually in these cases, the more information, the better, but for some reason, when I tried to uploaded, it just gave me a generic error response and said try again later.
//
// ImageView.swift
// Akasha
//
// Created by Dylan on 6/20/23.
//
import SwiftUI
import AMSMB2
import Combine
struct ImageView: View {
@ObservedObject var imageLoader: ImageLoader
@State var image: UIImage = UIImage()
init(withUrl url: String) {
imageLoader = ImageLoader(urlString: url)
}
var body: some View {
VStack {
Image(uiImage: image)
.aspectRatio(contentMode: .fill)
.onReceive(imageLoader.didChange) { data in
self.image = UIImage(data: data) ?? UIImage()
}
Spacer()
Text("Hello World!")
}
}
}
class ImageLoader: ObservableObject {
var didChange = PassthroughSubject<Data, Never>()
var data = Data() {
didSet {
didChange.send(data)
}
}
let client = AMSMB2(url: URL(string: "smb://10.0.0.2/")!, credential: URLCredential(user: "user", password: "password", persistence: .forSession))
init(urlString:String) {
guard let url = URL(string: fetchImage(path: urlString).absoluteString) else { return }
let task = URLSession.shared.dataTask(with: url) { [weak self] data, response, error in
guard let data = data, self != nil else { return }
DispatchQueue.main.async { [weak self] in
self?.data = data
}
}
task.resume()
}
func fetchImage(path: String) -> URL {
do {
var cacheURLDirectory: URL
cacheURLDirectory = try FileManager.default.url(for: .cachesDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let fullCacheURLPath = cacheURLDirectory.absoluteString + path
let fullCacheURL = URL(string: fullCacheURLPath)!
client?.connectShare(name: "media") { error in
if error != nil {
print("connectShare Error: ")
print(error!)
}
self.client?.downloadItem(atPath: path, to: fullCacheURL, progress: AMSMB2.ReadProgressHandler(downloadProgressHandler(bytes:total:)), completionHandler: AMSMB2.SimpleCompletionHandler(downloadCompletionHandler(error:)))
}
return fullCacheURL
} catch {
print ("Error Setting Cache Directory for Image")
return URL(string: "")!
}
func downloadProgressHandler(bytes: Int64, total: Int64) -> Bool {
return true
}
func downloadCompletionHandler(error: Error?) -> Void {
}
}
}
#Preview {
ImageView(withUrl: "Old Hard Drive.webp")
}
And if this turns out of course to be a bug with Xcode itself and NOT user error, I will file it in the Feedback app (if there is a spot in there for Xcode... if not, I will find out where I need to go). Thanks everyone!