How can I convert an SDWebImage to a UIImage? - ios

I need to convert an image I downloaded from Firebase using SDWebImage to a UIImage. How can I do this? Here is my code so far:
Database.database().reference().child("movies").child(movieNumString).observeSingleEvent(of: .value, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let UrlString: String? = ((dictionary["posterPhotoURL"] as? String))
let Url = URL(string: (UrlString)!)
self.moviePosterImageView.sd_setImage(with: Url, placeholderImage: #imageLiteral(resourceName: "PImage"))
}

You can try this callBack method
self.moviePosterImageView.sd_setImage(with:Url,
placeholderImage: #imageLiteral(resourceName: "PImage"),
options: [],
completed: { (image, error,cacheType, url) in
// here image is the UIImage
self.moviePosterImageView.image = image?.roundedWithBorder(width: 2, color: .red)
})

Related

swift Kingfisher and MPMediaItemArtwork

I am currently printing out the image for now playing using the following code.
if var strUrl = nowplaying.data.first?.track.imageurl {
strUrl = strUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
self.imageurl.kf.setImage(with: URL(string: strUrl), placeholder: nil)
}
I want to send that image to
MPMediaItemPropertyArtwork
which is in the following function
func nowplaying(artist: String, song: String, artwork: String){
MPNowPlayingInfoCenter.default().nowPlayingInfo = [
MPMediaItemPropertyTitle:song,
MPMediaItemPropertyArtist:artist,
MPMediaItemPropertyArtwork:artwork
]
}
Currently I have MusicPlayer.shared.nowplaying(artist: $0.track.artist, song: $0.track.title, artwork: $0.track.imageurl) which sends the data correctly but then crashes - and I know it is because you can't have a remote image in the artwork section for MPMediaItemProperty...
So I am wondering how do I cache the image and send it?
code tried
let artwork = MPMediaItemArtwork(boundsSize: CGSize(width: 100, height: 100)) { size -> UIImage in
KingfisherManager.shared.retrieveImage(with: cover, options: nil, progressBlock: nil, completionHandler: { image, error, cacheType, imageURL in
print(image)
})
return UIImage()
}
it prints in the console log
Optional(<UIImage:0x280a4e0a0 anonymous {500, 500}>)
but seems not to print it to the
MPMediaItemPropertyArtwork
You can save an image in the cache and can retrieve it whenever you need.
let resource = ImageResource(downloadURL: url, cacheKey: "my_cache_key")
imageView.kf.setImage(with: resource)
You can retrieve an image from the cache by using
cache.retrieveImage(forKey: "cacheKey") { result in
//Your code
)}
For more information, you can check this link https://github.com/onevcat/Kingfisher/wiki/Cheat-Sheet
Hope this works...
The value of MPMediaItemPropertyArtwork should be MPMediaItemArtwork class, not URL or String. In those class you can load UIImage async and set as an artwork in Command Center
Here is a working example with Kingfisher (please update it according your model structure):
ImageDownloader.default.downloadImage(
with: artworkUrl,
options: nil,
progressBlock: nil) { (result) in
guard let image = try? result.get().image else { return }
DispatchQueue.main.async {
MPNowPlayingInfoCenter.default().nowPlayingInfo = [
MPMediaItemPropertyTitle: song,
MPMediaItemPropertyArtist: artist,
MPMediaItemPropertyArtwork: image
]
}
}

Cannot load images from Twitter app within share extension

I'm implementing a share extension that sends images to a server for computation.
In addition to my progress bar issues, I'm not able to use the images from Twitter app. Here is the code I'm using which is working in many other third party apps.
if let inputItem = extensionContext!.inputItems.first as? NSExtensionItem {
if let itemProvider = inputItem.attachments?.first as? NSItemProvider {
if itemProvider.hasItemConformingToTypeIdentifier(kUTTypeImage as String) {
itemProvider.loadItem(forTypeIdentifier: kUTTypeImage as String) { [unowned self] (imageData, error) in
let url = imageData as! URL
self.sendToServer(localUrl: url)
}
}
}
}
The error I have is the following: Could not cast value of type 'NSConcreteData' (0x1a8d45700) to 'NSURL' (0x1a8d36a10) and occurs for this part of the code let url = imageData as! URL.
It seems that the item is of type image. Any idea why that is happening while it works for the other apps?
Thanks for your help.
I managed to fix that by using the following code, which takes into account different ways the photo is passed by the itemProvider.
itemProvider.loadItem(forTypeIdentifier: kUTTypeImage as String){ [unowned self] (data, error) in
let myImage: UIImage?
switch data {
case let image as UIImage:
myImage = image
case let data as Data:
myImage = UIImage(data: data)
case let url as URL:
let imageData = NSData(contentsOf: url.absoluteURL)
myImage = UIImage(data: imageData! as Data)
default:
//There may be other cases...
print("Unexpected data:", type(of: data))
myImage = nil
}
self.sendToServer(imageData: myImage!, imageName: myImageName)
}

Importing an image using Action Extension - URL to a local Image works but not with actual image data

My iOS app (Swift 3) needs to important images from other apps using an Action Extension. I'm using the standard Action Extension template code which works just fine for apps like iOS Mail and Photos where the image shared is a URL to a local file. But for certain apps where the image being shared is the actual image data itself, my action extension code isn't getting the image.
for item: Any in self.extensionContext!.inputItems {
let inputItem = item as! NSExtensionItem
for provider: Any in inputItem.attachments! {
let itemProvider = provider as! NSItemProvider
if itemProvider.hasItemConformingToTypeIdentifier(kUTTypeImage as String) { //we'll take any image type: gif, png, jpg, etc
// This is an image. We'll load it, then place it in our image view.
weak var weakImageView = self.imageView
itemProvider.loadItem(forTypeIdentifier: kUTTypeImage as String, options: nil, completionHandler: { (imageURL,
error) in
OperationQueue.main.addOperation {
if let strongImageView = weakImageView {
if let imageURL = imageURL as? NSURL {
strongImageView.image = UIImage(data: NSData(contentsOf: imageURL as URL)! as Data)
let imageData = NSData(contentsOf: imageURL as URL)! as Data
self.gifImageView.image = UIImage.gif(data: imageData)
let width = strongImageView.image?.size.width
let height = strongImageView.image?.size.height
.... my custom logic
}
}
For reference, I reached out to the developer for one of the apps where things aren't working and he shared this code on how he is sharing the image to the Action Extension.
//Here is the relevant code. At this point the scaledImage variable holds a UIImage.
var activityItems = Array<Any?>()
if let pngData = UIImagePNGRepresentation(scaledImage) {
activityItems.append(pngData)
} else {
activityItems.append(scaledImage)
}
//Then a little later it presents the share sheet:
let activityVC = UIActivityViewController(activityItems: activityItems,applicationActivities: [])
self.present(activityVC, animated: true, completion: nil)
Figured it out thanks to this post which explains the challenge quite well https://pspdfkit.com/blog/2017/action-extension/ . In summary, we don't know if the sharing app is giving us a URL to an existing image or just raw image data so we need to modify the out of the box action extension template code to handle both cases.
for item: Any in self.extensionContext!.inputItems {
let inputItem = item as! NSExtensionItem
for provider: Any in inputItem.attachments! {
let itemProvider = provider as! NSItemProvider
if itemProvider.hasItemConformingToTypeIdentifier(kUTTypeImage as String) { //we'll take any image type: gif, png, jpg, etc
// This is an image. We'll load it, then place it in our image view.
weak var weakImageView = self.imageView
itemProvider.loadItem(forTypeIdentifier: kUTTypeImage as String, options: nil, completionHandler: { (imageURL,
error) in
OperationQueue.main.addOperation {
if let strongImageView = weakImageView {
if let imageURL = imageURL as? NSURL {
strongImageView.image = UIImage(data: NSData(contentsOf: imageURL as URL)! as Data)
let imageData = NSData(contentsOf: imageURL as URL)! as Data
self.gifImageView.image = UIImage.gif(data: imageData)
let width = strongImageView.image?.size.width
let height = strongImageView.image?.size.height
.... my custom logic
}
else
guard let imageData = imageURL as? Data else { return } //can we cast to image data?
strongImageView_.image = UIImage(data: imageData_)
//custom logic
}

Why are my images are not being cached in AlamofireImage?

I am clueless at the moment, I dont know why I am getting nil each time when I am trying to retrieve. I am passing the correct image data and identifier. Here's a little code
let photoCache = AutoPurgingImageCache(
memoryCapacity: 100 * 1024 * 1024,
preferredMemoryUsageAfterPurge: 60 * 1024 * 1024
)
func cacheImage(image: Image, urlString: String) {
print("Image size: \(image.size) and string as identifier: \(urlString)")
self.photoCache.addImage(image, withIdentifier: urlString)
}
func cachedImage(urlString: String) -> Image? {
print("What is url? : \(urlString)")
print("What we are actually returning? : \(self.photoCache.imageWithIdentifier(urlString))")
return self.photoCache.imageWithIdentifier(urlString)
}
Print for the cacheImage function: Image size: (2826.0, 3722.0) and string as identifier: http:www.somelink.com/DT199.jpg
Print for the cachedImage when I am trying retrieving it: what is the URL? : http:www.somelink.com/DT199.jpg What we are actually returning is : nil
I don't know why it is happening I tried it several times before and it worked perfectly. I also read about these functions, they don't return any boolean response through which we can get to know whether the image is in cache or not.
Later on, i tried using the download manager as well nothing happen still clueless. If any one can help me? here's the code
let imageDownloader = ImageDownloader(
configuration: ImageDownloader.defaultURLSessionConfiguration(),
downloadPrioritization: .FIFO,
maximumActiveDownloads: 15,
imageCache: AutoPurgingImageCache()
)
let downloader = imageDownloader
Alamofire.request(.GET, request, headers: headers)
.responseJSON { response in
if let JSON = response.result.value {
self.imagesArray = NSMutableArray()
self.imagesArray = JSON["results"] as! NSMutableArray
for results in self.imagesArray{
let URLRequest = NSURLRequest(URL: NSURL(string:results["url"] as! String)!)
downloader.downloadImage(URLRequest: URLRequest, filter: nil, completion: { response in
if response.response?.statusCode == 200{
print("In the house fetching url: \(results["url"] as! String)")
let image = response.result.value
print("Size of image: \(image?.size)")
let returnValue = downloader.imageCache?.addImage(image!, withIdentifier: results["url"] as! String)
print("return status: \(returnValue)")
if results .isEqual(self.imagesArray.lastObject){
self.activityIndicatorView.stopAnimating()
self.activityIndicatorView.hidden = true
let fic = self.imagesArray.firstObject
print("getting image for this url : \(fic!["url"] as! String)")
var imageC = UIImage()
imageC = (downloader.imageCache?.imageWithIdentifier(fic!["url"] as! String))!
self.ssImage.image = imageC
print("Image : \(imageC.size))")
}
}
})
}
}
}
Maybe you have to initialize your imageDownloader with the photoCache you used before to cache the images manually. The AutoPurgingImageCache isn't a shared instance. Only the UIImageView+AlamofireImage.swift extension has a af_sharedImageDownloader which keeps one AutoPurgingImageCache.
In dependence on your code example it should look like this:
let imageDownloader = ImageDownloader(
configuration: ImageDownloader.defaultURLSessionConfiguration(),
downloadPrioritization: .FIFO,
maximumActiveDownloads: 15,
imageCache: self.photoCache
)

UIImage not fetching

I'm having issues with the UIImage crashing my app whenever I run it. I think there is a possibility the images are somehow currupt perhaps. I ran debug and everything seems to run fine up until this line below:
let image = UIImage(named: photo!)?.decompressedImage
The image key is showing up and everything is running as it should. It is the next line that seems to make the app crash:
self.init(caption: caption!, comment: comment!, image: image!)
I know I am force unwrapping the image, however I know that the image exists. Do you also agree that maybe the image is corrupt? Is there a way to double check this or perhaps fix it? The images are JPG form.
Code:
import UIKit
class Photo {
class func allPhotos() -> [Photo] {
var photos = [Photo]()
if let URL = NSBundle.mainBundle().URLForResource("Photos", withExtension: "plist") {
if let photosFromPlist = NSArray(contentsOfURL: URL) {
for dictionary in photosFromPlist {
let photo = Photo(dictionary: dictionary as! NSDictionary)
photos.append(photo)
}
}
}
return photos
}
var caption: String
var comment: String
var image: UIImage
init(caption: String, comment: String, image: UIImage) {
self.caption = caption
self.comment = comment
self.image = image
}
convenience init(dictionary: NSDictionary) {
let caption = dictionary["Caption"] as? String
let comment = dictionary["Comment"] as? String
let photo = dictionary["Photo"] as? String
let image = UIImage(named: photo!)?.decompressedImage
self.init(caption: caption!, comment: comment!, image: image!)
}
func heightForComment(font: UIFont, width: CGFloat) -> CGFloat {
let rect = NSString(string: comment).boundingRectWithSize(CGSize(width: width, height: CGFloat(MAXFLOAT)), options: .UsesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
return ceil(rect.height)
}
}

Resources