Use Image in SwiftUI with either URL or Data without UIKit - swift

I have downloaded an image in bytes (Data). I stored it with FileManager in the cache of the user's device. I was wondering if I could create an Image with either Data or a local URL, I am currently using UIImage but I want to support macOS.
Is there a full SwiftUI way of creating an Image with URL or Data without UIKit/UIImage?

if your question is about showing and image in macos, that you already have downloaded (and is in the cachesDirectory), then try something like this, to create an image from your image in bytes: (using NSImage for macos)
struct ContentView: View {
#State var img = NSImage()
var body: some View {
Image(nsImage: img)
.onAppear {
do {
// local file
let url = try FileManager.default
.url(for: .cachesDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
.appendingPathComponent("kat") // <--- your file name here
.appendingPathExtension("png")
print("----> url: \(url)")
// even from the net
// let url = URL(string: "https://upload.wikimedia.org/wikipedia/commons/e/ef/Red-billed_gull%2C_Red_Zone%2C_Christchurch%2C_New_Zealand.jpg")!
if let nsimg = NSImage(contentsOf: url) { img = nsimg }
} catch {
print("\(error)")
}
}
}
}

Related

Is there a way to cache images in swiftui in WidgetKit?

I realized you can display images in widget like this stack overflow answer.
https://stackoverflow.com/a/64163384/13476728
However, I was wondering if this keeps calling the url every time when it refreshes through timelineprovider? if it does, how do i store the image through cache and display it so it doesnt call the url every time. (In this example "https://www.test.com")
Group {
let tempUrl = URL(string: "https://www.test.com")!
if let url = tempUrl, let imageData = try? Data(contentsOf: tempUrl),
let uiImage = UIImage(data: imageData) {
if(uiImage != nil){
Image(uiImage: uiImage)
.resizable()
} else{
black
}
}
}

What will my PDF location be in local app files? - SwiftUI

I have sourced a function that converts a view to a PDF from another stack overflow post - https://stackoverflow.com/a/60753437/12969913. With this I am using another view to try and display the PDF inside a new view for the user to inevitably share and view as they wish.
How do I get my PDF to display, I can't figure out how the URL works and what I have to put into the new view.
The URL is created in the exportToPDF() function:
let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let outputFileURL = documentDirectory.appendingPathComponent("SwiftUI.pdf")
I have then sourced some code to display the PDF from another stack overflow post and have implemented that - https://stackoverflow.com/a/61480852/12969913, but in order for this to work I have to put in my file URL, how do I do that, and what will the file URL be?
My PDFKitView() Code - to display the new .pdf:
struct PDFKitView: View {
var url: URL
var body: some View {
PDFKitRepresentedView(url)
}
}
struct PDFKitRepresentedView: UIViewRepresentable {
let url: URL
init(_ url: URL) {
self.url = url
}
func makeUIView(context: UIViewRepresentableContext<PDFKitRepresentedView>) -> PDFKitRepresentedView.UIViewType {
let pdfView = PDFView()
pdfView.document = PDFDocument(url: self.url)
pdfView.autoScales = true
return pdfView
}
func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<PDFKitRepresentedView>) {
// Update the view.
}
}
I then go to display this using:
HStack{
PDFKitView(url: ????????)
Text("Hello World")
}
If you are droping the PDF file directly to your Xcode project, this is how you will be able to retrive the URL:
guard let path = Bundle.main.path(forResource: "SwiftUI", ofType: "pdf") else { return }
let url = URL(fileURLWithPath: path)

Load image from app's documents folder (iOS 14 widget)

I'd like to know if it's possible (and how!) to load a file saved in my main app's documents sandbox folder from a widget.
My main app (UIKit) saves images to FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]. as a .png. I have a function to load these images from my app but would like to know how to load them in my widget timeline.
Here's my code for loading the images in UIKit:
var documentsUrl: URL {
return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
}
private func loadImage(fileName: String) -> UIImage? {
let fileURL = documentsUrl.appendingPathComponent(fileName)
do {
let imageData = try Data(contentsOf: fileURL)
return UIImage(data: imageData)
} catch {
print("Error loading image : \(error)")
}
return nil
}
I've got app groups working as I'm using UserDefaults between targets fine.
Thanks!

How to save selected image from photo gallery to show any view controller in swift

I'm working on my app and i got stuck at one point.
There is one UIIMAGEVIEW and one UPLOAD button.
So when user click UPLOAD button he get to photo gallery to select image after selecting image I'm showing that image on UIIMAGEVIEW.
So my question is:-
after showing image on UIIMAGEVIEW i want to save that image on app to show that same image on different View Controller.
In this case you can try this code snippet:
func saveImgToDocumentDirectory(image: UIImage ) {
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileName = "image.png" // image name for identify particular image
let fileURL = documentsDirectory.appendingPathComponent(fileName)
if let data = UIImageJPEGRepresentation(image, 1.0),!FileManager.default.fileExists(atPath: fileURL.path){
do {
try data.write(to: fileURL)
print("file saved")
} catch {
print("error saving file:", error)
}
}
}
func loadImgFromDocumentDirectory(nameOfImage : String) -> UIImage {
let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
if let dirPath = paths.first{
let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent(nameOfImage)
let image = UIImage(contentsOfFile: imageURL.path)
return image!
}
return UIImage.init(named: "default.png")!
}
Image name is a unique identifier for the image, while storing you are required to specify the image name "imageName", so it would be easy to fetch that particular image using the same name.
You can put the image in a global variable. A global variable can be used through all the app. :
var imageSelected:UIImage? // Value will be nil if no image has been set
class ViewController1 {
// Puts your image inside a global variable
image = yourImage
}
class ViewController2 {
// Uses the image that was defined inside the global variable
#IBOutlet weak var imageView: UIView!
imageView.image = imageSelected
}

how to download pdf file in iOS?

I am converting base64 to pdf file in local.
func saveBase64StringToPDF(_ base64String: String)
{
guard
var documentsURL = (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)).last,
let convertedData = Data(base64Encoded: base64String)
else {
//handle error when getting documents URL
return
}
documentsURL.appendPathComponent("yourFileName.pdf")
do {
try convertedData.write(to: documentsURL)
} catch {
//handle write error here
}
print(documentsURL)
}
From above method I am getting a path pdf file
file:///Users/captivatesoft/Library/Developer/CoreSimulator/Devices/63D1814B-1010-4694-883E-D2EE75C386DD/data/Containers/Data/Application/1F39B567-F470-4B7E-9A9C-4723ADFDC428/Documents/yourFileName.pdf
Is there any way to download this pdf file or to show pdf in safari?
var pdfURL = (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)).last! as URL
pdfURL = pdfURL.appendingPathComponent( "example.pdf") as URL
let data = try! Data(contentsOf: pdfURL)
let webView = WKWebView(frame: CGRect(x:20,y:20,width:view.frame.size.width-40, height:view.frame.size.height-40))
webView.load(data, mimeType: "application/pdf", characterEncodingName:"", baseURL: pdfURL.deletingLastPathComponent())
view.addSubview(webView)
To open the PDF in Safari you could just do
UIApplication.shared.openURL(URL(string: <the link for the PDF>))
Now to download a PDF or anything from a URL, you could just do
let pdfData = try? Data(contentsOf: URL(string: <the link for the PDF>))
NOTE: try Data(contentsOf: url) will block the thread, so you might want to do it on a different thread like this :
DispatchQueue.global.async { [weak self] in
if let pdfData = try? Data(contentsOf: url) {
// Now you can do anything with the data
}
}
First, you can not download pdf file in iOS, it means you cannot save pdf file in iBook or Album.
You can fetch pdf file data from file URL then you can do follows:
Open in Safari browser from the app.
You can show pdf file in WKWebView within the app.
You can use "QuickLook" framework to show the pdf file.
Using WebView:
if let url = URL(string:string) {
webView.load(URLRequest(url: url))
}