How can I show Stickers from Document directory in Swift - ios

DispatchQueue.main.async
{
var x : Int = 0
for item in self.arrGifs
{
let gif : GIF = item as! GIF
let gifName = URL(string: gif.gifImage)?.lastPathComponent
// let ur
let pathUrl = URL.urlInDocumentsDirectory(with: "\(gifName!)").path
print("image path is =====>", pathUrl)
//RawImages.xcassets
// if let url = Bundle.main.url(forResource:"3", withExtension: "gif")
// {
print("url is ------>>>> ",url)
do
{
let sticker = try
// MSSticker(contentsOfFileURL: url,localizedDescription: "")
MSSticker(contentsOfFileURL: URL(string:pathUrl)!,localizedDescription: "")
self.arrSticker.append(sticker)
}
catch
{
print(error.localizedDescription)
}
// }
}
self.createStickerBrowser()
}
Well for the above " MSSticker(contentsOfFileURL: url,localizedDescription: "")" I can get stickers which are saved in Bundle. But If I give path of document directry, no sticker are shown.
I am downloading the imges from api, saving in my sqlite(image name) and images in document directry so that user can view it Offline. I find no solutions . Need help what is wrong and how to do it right.
Thank you.
file:///private/var/containers/Bundle/Application/F8FF754B-F012-4B75-AA2E-9FA71846E6AB/Migos%20Lingo.app/PlugIns/MigosLingo.appex/3.gif === this from Bundle and I can view as Sticker
/var/mobile/Containers/Data/PluginKitPlugin/DE11FB0E-89F9-4A65-917E-B4FEB8CA5470/Documents/111111-1508763742.gif ===> Document directry and I cannot view as Stickers

Can you try this.
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
After this make url because MSSticker create sticker with url path.Don't forget to append your image name with document path. after getting image path just do this.
let pathurl = URL(fileURLWithPath: imagePath!)
now you can creat sticker.
MSSticker(contentsOfFileURL: pathurl, localizedDescription: "hello world")

Related

How to prevent constantly downloading an image from Firebase and show the image even if there is no internet connection?

Every time I show the profile picture, the UIImageView flashes to signify that the image was just downloaded from the Firebase Storage URL. This download speed differs based on the device type, some times it is unnoticeable while other times there is a significant delay.
I have attempted to cache the image with NSCache and the Kingfisher library but I still see the UIImageView flash rather than remain there every time I reopen the app.
My last attempt was to save the image to the document directory and then retrieve it from there but I still see the image flash. I would also like the profile picture to remain there even if the application is opened without any internet connection.
func saveImageDocumentDirectory(imgUrl: URL){
let fileManager = FileManager.default
let paths = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("proPic.png")
let data = (try? Data(contentsOf: imgUrl))
let image = UIImage(data: data!)
print("\n\(paths)\n")
let imageData = image!.pngData()
fileManager.createFile(atPath: paths as String, contents: imageData, attributes: nil)
}
func getDirectoryPath() -> String {
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDirectory = paths[0]
return documentsDirectory
}
func getImage(){
let fileManager = FileManager.default
let imagePAth = (self.getDirectoryPath() as NSString).appendingPathComponent("proPic.png")
if fileManager.fileExists(atPath: imagePAth){
self.profilePic.image = UIImage(contentsOfFile: imagePAth)
}else{
print("\nNo Image\n")
}
}
func createDirectory(){
let fileManager = FileManager.default
let paths = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("customDirectory")
if !fileManager.fileExists(atPath: paths){
try! fileManager.createDirectory(atPath: paths, withIntermediateDirectories: true, attributes: nil)
}else{
print("\nAlready dictionary created.\n")
}
}
And I would call the function by:
func getEmailPic(){
guard let uid = Auth.auth().currentUser?.uid else {return}
//receive the location of the profile pic
let storageRef = Storage.storage().reference().child(uid).child("profilePic.png");
//how to access the downloadURL
_ = storageRef.downloadURL(completion: { (URLe, error) in
if let error = error{
//error handling
print("\nCould not download user's profile image from url.
Error: \(error.localizedDescription)\n");
return;
}
self.createDirectory()
self.saveImageDocumentDirectory(imgUrl: URLe!)
print("\nThis is the URL: \(URLe)\n")
self.getImage()
})
}
in viewDidLoad.
Using kingfisher for image caching, Try this and feel free to ask if facing any issue
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// set profile image if you have url saved in userdefaults
let imageUrl = getUrlImageFromUserDefaults()
let placeholderImage = UIImage(named: "placeholder")
profileImageView.kf.setImage(with: imageUrl, placeholder: placeholderImage)
getEmailPic()
}
func getUrlImageFromUserDefaults() -> URL?{
// save image URL to userdefault and fetch here
let userdefaults = UserDefaults.standard
return userdefaults.url(forKey: "profileURL")
}
func getEmailPic(){
guard let uid = Auth.auth().currentUser?.uid else {return}
//receive the location of the profile pic
let storageRef = Storage.storage().reference().child(uid).child("profilePic.png");
//how to access the downloadURL
_ = storageRef.downloadURL(completion: { (URLe, error) in
if let error = error{
//error handling
print("\nCould not download user's profile image from url.
Error: \(error.localizedDescription)\n");
return;
}
if URLe == getUrlImageFromUserDefaults() {
// if url is same no need to set again
}else{
// set profile image
let placeholderImage = UIImage(named: "placeholder")
profileImageView.kf.setImage(with: URLe, placeholder: placeholderImage)
// and again save this new URL to userdefaults
}
})
}

Unable to display Stickers from Documents directory in iMessage extension

In my app users are able to create images and then use them as stickers in iMessages.
My problem is that I can't display created images that are stored in the Documents Directory.
My issue is very similar to this question - SO Question but in my case the solution stated there didn't help.
Here's my code for fetching images:
func getImages(finished: () -> Void) {
imageData.removeAll()
let imageNames = keyboardUserDefaults!.stringArray(forKey: "Created stickers")
for imageName in imageNames! {
// let imagePath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let filePath = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent(imageName)
// imageData.append(imagePath + "/" + imageName)
imageData.append(filePath)
}
print("Image Data - ", imageData)
finished()
}
And here is how I apply it to StickerView:
func configure(usingImageName imagePath: String) {
let urlToImage = URL(fileURLWithPath: imagePath)
do {
let description = NSLocalizedString("", comment: "")
let sticker = try MSSticker(contentsOfFileURL: urlToImage, localizedDescription: description)
print("Sicker is here - ", sticker)
stickerView.sticker = sticker
}
catch {
fatalError("Failed to create sticker: \(error)")
}
}
But I'm getting a blank view with no stickers.
Print inside cell shows:
Sicker is here - <MSSticker-<0x280393640> imageFileURL file:///var/mobile/Containers/Data/PluginKitPlugin/32AF9E44-F2F1-4FD1-80B5-E8E4B6C6E338/Documents/F54067B8-18DA-4737-8ED3-B716E368AF6E.png localizedDescription >
Images are showing when I set them from my folder inside Xcode project using Bundle.main.path, but not from the Documents Directory.
I have found source of my problem:
Application Extensions can't access default Documents Directory folder.
Solution:
Use App Groups and make path for image when saving and retrieving it like this:
let url = fileManager.containerURL(forSecurityApplicationGroupIdentifier: "YOUR_APP_GROUP_NAME")?.appendingPathComponent("image.png")
After that you can easily access your images in Application Extensions.
Hope this helps someone in future!

Can not get proper firebase image save in document directory in swift 4 iOS

i'm saving firebase image in document directory !! For uniqueness my Document Directory name is firebase image name ! i have check with a condition that if firebase image name is not exists in my document directory then save that image in Document Directory !!
i'm checking if that firebase name means it save in document directory then it get document directory image if not then it get image from Firebase !!
Issue is when i try to get image :-
(1) For example :- Firebase Image name is 1.jpg .
(2) Document Directory save image with firebase name like 1.jpg .
(3) now i change firebase image to other but it save with name 1.jpg .
(4) when i try to get image because already 1.jpg is in Document Directory that's why it not return me updated image it show me previous 1.jpg image !!
how can i solved this issue. Thank You
Save And Get Image Code :-
func saveImageDocumentDirectory(imageName: String){
let documentPath = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let imgURL = documentPath.appendingPathComponent(imageName, isDirectory: true)
if !FileManager.default.fileExists(atPath: imgURL.path){
do{
let image = UIImage(named: imgURL.path)
try image?.pngData()?.write(to: imgURL)
}catch let err{
print("error in save:\(err.localizedDescription)")
}
}
}
func getDocumentImage(imageName: String, firebaseImgURL: URL, imgView:UIImageView){
let documentPath = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let imgURL = documentPath.appendingPathComponent(imageName, isDirectory: true)
let image = UIImage(contentsOfFile: imgURL.path)
if image != nil{
imgView.image = image
}else{
imgView.kf.setImage(with: firebaseImgURL)
}
}
Please try with like below code
Save Data
let placeholderURL: URL =
getDocumentDirectoryPath()!.appendingPathComponent("\(imageName.JPG)/",
isDirectory: true)
let fileExists: Bool = FileManager.default.fileExists(atPath: placeholderURL.path )
if !fileExists {
let thumbnailImageURL = URL(string: firebaseURL)
var placeholderData: Data? = nil
if let url = url {
do {
placeholderData = try Data(contentsOf: (thumbnailImageURL ?? nil)!)
} catch {
print("Unable to load data: \(error)")
}
}
if urlData != nil {
do {
//saving is done on main thread
try placeholderData?.write(to: URL(fileURLWithPath: placeholderURL.path) , options: .atomic)
} catch {
print(error)
}
}
}
Retrive image
let thumbnailURL: URL = getDocumentDirectoryPath()!.appendingPathComponent("\("imageName.JPG")/", isDirectory: true)
let fileExists: Bool = FileManager.default.fileExists(atPath: thumbnailURL.path)
var urlThumbnail:URL? = nil
if fileExists {
urlThumbnail = URL(fileURLWithPath: thumbnailURL.path)
} else {
urlThumbnail = URL(string: firebaseURL)
}
Sat image in image view
self.imgtemp.sd_setImage(with: urlThumbnail, placeholderImage: UIImage(named: "placeholder.png"))

Swift: can't get array of images from url of folder?

Alright, Im fairly new to the url locating process (I always just use explicit names) and everyone is new to MSMessageStickers. However. I need to pull in an array of image urls to use as MSStickers from a folder of images I have copied into my MessagesExtension target in my project here (it is starterPack):
It may the Swift 3 syntax screwing this up or something else, but I CANT find any way to just get the right url of this folder and get all the images inside of it. The following is successful in making stickers out of PNGS with specific names:
for i in (1..<2) {
if let url = Bundle.main.url(forResource: "test\(i)", withExtension: "png") {
do {
//let sticker = try MSSticker(contentsOfFileURL: url, localizedDescription: "")
let sticker = try MSSticker(contentsOfFileURL: url, localizedDescription: "")
//print("SUCCESS", url)
stickers.append(sticker)
} catch {
print(error)
}
}
}
And I have adapted the following to Swift 3 from similar question How to get array of UIImage, from folder, in Swift? :
if let path = NSBundle.mainBundle().resourcePath {
let imagePath = path + "/images"
let url = NSURL(fileURLWithPath: imagePath)
let fileManager = NSFileManager.defaultManager()
let properties = [NSURLLocalizedNameKey,
NSURLCreationDateKey, NSURLLocalizedTypeDescriptionKey]
do {
let imageURLs = try fileManager.contentsOfDirectoryAtURL(url, includingPropertiesForKeys: properties, options:NSDirectoryEnumerationOptions.SkipsHiddenFiles)
print("image URLs: \(imageURLs)")
// Create image from URL
var myImage = UIImage(data: NSData(contentsOfURL: imageURLs[0])!)
} catch let error1 as NSError {
print(error1.description)
}
}
But because the folder is not technically in my project folder but rather in the messagesExtension folder as you can see, I think that is why it cant find it.
I need to bring in and get the url of all the images contained in my stickers folder. What am I doing wrong?

Rename file in DocumentDirectory

I have a PDF file in my DocumentDirectory.
I want the user to be able to rename this PDF file to something else if they choose to.
I will have a UIButton to start this process. The new name will come from a UITextField.
How do I do this? I'm new to Swift and have only found Objective-C info on this and am having a hard time converting it.
An example of the file location is:
/var/mobile/Containers/Data/Application/39E030E3-6DA1-45FF-BF93-6068B3BDCE89/Documents/Restaurant.pdf
I have this code to see check if the file exists or not:
var name = selectedItem.adjustedName
// Search path for file name specified and assign to variable
let getPDFPath = paths.stringByAppendingPathComponent("\(name).pdf")
let checkValidation = NSFileManager.defaultManager()
// If it exists, delete it, otherwise print error to log
if (checkValidation.fileExistsAtPath(getPDFPath)) {
print("FILE AVAILABLE: \(name).pdf")
} else {
print("FILE NOT AVAILABLE: \(name).pdf")
}
To rename a file you can use NSFileManager's moveItemAtURL.
Moving the file with moveItemAtURL at the same location but with two different file names is the same operation as "renaming".
Simple example:
Swift 2
do {
let path = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
let documentDirectory = NSURL(fileURLWithPath: path)
let originPath = documentDirectory.URLByAppendingPathComponent("currentname.pdf")
let destinationPath = documentDirectory.URLByAppendingPathComponent("newname.pdf")
try NSFileManager.defaultManager().moveItemAtURL(originPath, toURL: destinationPath)
} catch let error as NSError {
print(error)
}
Swift 3
do {
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let documentDirectory = URL(fileURLWithPath: path)
let originPath = documentDirectory.appendingPathComponent("currentname.pdf")
let destinationPath = documentDirectory.appendingPathComponent("newname.pdf")
try FileManager.default.moveItem(at: originPath, to: destinationPath)
} catch {
print(error)
}
The modern way is (url is the file URL of a file in your sandbox):
var rv = URLResourceValues()
rv.name = newname
try? url.setResourceValues(rv)
There is an easier way to rename item at any given NSURL.
url.setResourceValue(newName, forKey: NSURLNameKey)
Edit - Swift4
url.setTemporaryResourceValue(newName, forKey: .nameKey)

Resources