import UIKit
class DetailsViewController: UIViewController {
#IBOutlet weak var alpha3CodeLbl: UILabel!
#IBOutlet weak var regionLbl: UILabel!
#IBOutlet weak var flagImage: UIImageView!
var countrie:jsonStruct?
override func viewDidLoad() {
super.viewDidLoad()
alpha3CodeLbl.text = countrie?.alpha3Code
regionLbl.text = countrie?.region
let urlString = "http://restcountries.eu/rest/v2/all" + (countrie?.flag)!
flagImage.downloadedFrom(url: url!)
}
}
extension UIImageView {
func downloadedFrom(url: URL, contentMode mode: UIViewContentMode = .scaleAspectFit) {
contentMode = mode
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data)
else { return }
DispatchQueue.main.async() {
self.image = image
}
}.resume()
}
func downloadedFrom(link: String, contentMode mode: UIViewContentMode = .scaleAspectFit) {
guard let url = URL(string: link) else { return }
downloadedFrom(url: url, contentMode: mode)
}
}
I'm trying to get the flag image form this API http://restcountries.eu/rest/v2/all
There is no error but the image does not appear. But there is no result if there anyone here can fix this issue.
Please, not that everything is okay and try to get the image in too many ways but still no result.
Also, I try this
let urlString = "http[enter image description
here][1]://restcountries.eu" + (countrie?.flag)!
A few things to fix. You should test the url before using it.
let str = "yourURL"
guard let theUrl = URL(string: str) else { return }
As mentioned by #rmaddy in a comment above, UIImage isn't going to work with SVG files. Use a UIWebView instead
var request = URLRequest(url:theUrl)
webView.loadRequest(request)
Or try SVGKit to convert SVG as described here
Related
For anyone having this problem, who is not helped by this post, you may find the following use-full: Here.
Here is a copy of the error:
2018-08-29 18:39:59.458950-0400 proj[5319:3378682] NSURLConnection finished with error - code -1002
I have looked through these answer and not found anything to work. I believe its because the problem is happening for another reason for those. I am having the problem when fetching images from a database and trying to display them in on a image view.
Full code bellow:
import UIKit
import FirebaseStorage
import FirebaseDatabase
import FirebaseAuth
import Firebase
class PhaseOneViewController: UIViewController {
#IBOutlet weak var p1ImageView: UIImageView!
#IBAction func loadImages(_ sender: Any) {
//p1ImageView.image = nil
NKPlaceholderImage(image: UIImage(named: "placeholder"), imageView: p1ImageView, imgUrl: "\(Storage.storage().reference().child((Auth.auth().currentUser?.uid)!).child("post\(takePicViewController().finalPost + PhotoArray.sharedInstance.numberPost)").child(ImageUploadManager().imageName))") { (image) in }
}
func NKPlaceholderImage(image:UIImage?, imageView:UIImageView?,imgUrl:String,compate:#escaping (UIImage?) -> Void) {
if image != nil && imageView != nil {
imageView!.image = image!
}
var urlcatch = imgUrl.replacingOccurrences(of: "/", with: "#")
let documentpath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
urlcatch = documentpath + "/" + "\(urlcatch)"
let image = UIImage(contentsOfFile:urlcatch)
if image != nil && imageView != nil
{
imageView!.image = image!
compate(image)
}else{
if let url = URL(string: imgUrl){
DispatchQueue.global(qos: .background).async {
() -> Void in
let imgdata = NSData(contentsOf: url)
DispatchQueue.main.async {
() -> Void in
imgdata?.write(toFile: urlcatch, atomically: true)
let image = UIImage(contentsOfFile:urlcatch)
compate(image)
if image != nil {
if imageView != nil {
imageView!.image = image!
}
}
}
}
}
}
}
}
I have also asked These questions Link, Link, which may be of help to someone in my situation or to solve this problem.
Thanks!
I have been getting images from my API and in the past I have loaded them into a UIImage with the extension you will see below. However, now I am trying to get the images from the API and load them into UIButton image views. I don't know what to do to the extension and the other code to make it work. I appreciate the help!
Extension
Extension UIImageView {
func getURL2(url: URL, contentMode mode: UIViewContentMode = .scaleAspectFit) {
contentMode = mode
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data),
httpURLResponse.url == url
else { return }
DispatchQueue.main.async() {
self.image = image
}
}.resume()
}
func downloadedFrom2(link: String, contentMode mode: UIViewContentMode = .scaleAspectFit) {
guard let url = URL(string: link) else { return }
getURL2(url: url, contentMode: mode)
}
}
Other code
func loadProfilePhoto(image: UIButton, link: String) {
image.downloadedFrom2(link: link)
image.imageView!.clipsToBounds = true
image.imageView!.layer.cornerRadius = (image.imageView!.frame.height) / 2
image.imageView!.contentMode = .scaleAspectFill
}
func loadRandom8() {
if self.users.count == 8 {
let completelink1 = users[0].picture_url
//ex. https://api.adorable.io/avatars/200/AngelicAlling.png
let completelink2 = users[1].picture_url
let completelink3 = users[2].picture_url
let completelink4 = users[3].picture_url
let completelink5 = users[4].picture_url
let completelink6 = users[5].picture_url
let completelink7 = users[6].picture_url
let completelink8 = users[7].picture_url
loadProfilePhoto(image: p2Image, link: completelink1)
loadProfilePhoto(image: p2Image, link: completelink2)
loadProfilePhoto(image: p3Image, link: completelink3)
loadProfilePhoto(image: p4Image, link: completelink4)
loadProfilePhoto(image: p5Image, link: completelink5)
loadProfilePhoto(image: p6Image, link: completelink6)
loadProfilePhoto(image: p7Image, link: completelink7)
loadProfilePhoto(image: p8Image, link: completelink8)
Your current extension is for UIImageView but you want to load the image in a UIButton, so change the extension to UIButton and make sure the button's type is set to Custom and not System. You can do this from the storyboard.
extension UIButton {
func getURL2(url: URL, contentMode mode: UIViewContentMode = .scaleAspectFit) {
contentMode = mode
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data),
httpURLResponse.url == url
else { return }
DispatchQueue.main.async() {
self.setImage(image, for: .normal)
self.imageView?.contentMode = mode
}
}.resume()
}
public func downloadedFrom2(link: String, contentMode mode: UIViewContentMode = .scaleAspectFit) {
guard let url = URL(string: link) else { return }
getURL2(url: url, contentMode: mode)
}
}
If it didn't work for you read this
I'm having problems cacheing for images from JSON correctly with this UIImageView extension. The images load correctly when I first open the app and scroll down the page. However when I scroll back up, they don't reload and are completely gone. Can anyone see anything wrong with the code?
let imageCache = NSCache<AnyObject, AnyObject>()
extension UIImageView {
func loadImageUsingUrlString(urlString: String) {
let url = NSURL(string: urlString)
if let imageFromCache = imageCache.object(forKey: urlString as AnyObject) as? UIImage {
self.image = imageFromCache
return
}
URLSession.shared.dataTask(with: url! as URL) { (data, response, error) in
if error != nil {
print(error ?? "URLSession error")
return
}
DispatchQueue.main.async {
let imageToCache = UIImage(data: data!)
imageCache.setObject(imageToCache!, forKey: urlString as AnyObject)
self.image = imageToCache
}
}.resume()
}
}
Here is the snippet from the cell.swift file
let imageCache = NSCache<AnyObject, AnyObject>()
func setupThumbnailImage() {
if let thumbnailImageUrl = television?.poster_url {
let urlPrefix = "https://www.what-song.com"
let urlSuffix = thumbnailImageUrl
let urlCombined = urlPrefix + urlSuffix
thumbnailImageView.loadImageUsingUrlString(urlString: urlCombined)
}
}
I suggest using kingFisher, it is very easy to use and it manages all starting from cache threads etc.
let imageResource = ImageResource(downloadURL:URL(string: imagePath )!,cacheKey: imagePath )
viewImage.kf.indicatorType = .activity
viewImage.kf.setImage(with: resource)
where imagePath is the url of your image and viewImage is your imageView
Most probably you would be calling it in wrong way.
Remember that in tableView you reuse the cells.
By the time response comes back for the URLSessionTask you would have already scrolled up/down. In that case self.image would be assigned to the currently visible cell.
Please add your cellForRow code in question.
I am new to iOS i want download image to display it is working code but here lot of code duplication
let url = URL(string: iteminfo.imageUrl!)
let urlRequest = URLRequest(url: url!)
let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
if error != nil {
print(error)
}
if let data = data {
print(data)
self.imageViewItemPic.image = UIImage(data: data)
}
}
task.resume()
let url2 = URL(string: iteminfo.cookerProfilePicUrl!)
let urlRequest2 = URLRequest(url: url2!)
let task2 = URLSession.shared.dataTask(with: urlRequest2) { (data, response, error) in
if error != nil {
print(error)
}
if let data = data {
print(data)
self.imageViewCookerProfilePic.image = UIImage(data: data)
}
}
task2.resume()
So I want to reuse my code but i unfortunately i can not reach my goal. there have no error and url is correct . every time goes else statement . i am missing something but what is that ?
if let image = downlaodImage(urlImage: iteminfo.imageUrl){
print("first \(image)")
imageViewItemPic.image = image
}else{
print("first wrong......")
}
if let image = downlaodImage(urlImage: iteminfo.cookerProfilePicUrl){
print("second \(image)")
imageViewCookerProfilePic.image = image
}
else{
print("second wrong......")
}
Here is my method :
func downlaodImage(urlImage : String?) -> UIImage?{
var image : UIImage?
let url = URL(string: urlImage!)
let urlRequest = URLRequest(url: url!)
let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
if let data = data {
// print(data)
image = UIImage(data: data)
}
}
task.resume()
return image
}
note: I am not sure is it best way or not . if it is not best practice feel free to guide me .
There's no need of so much hassle. You have the URL of the image so you can simply download the image from the URL. For example:
func downloadImage(imageURL: String) {
DispatchQueue.global().async {
let data = NSData.init(contentsOf: NSURL.init(string: imageURL) as! URL)
DispatchQueue.main.async {
let image = UIImage.init(data: data as! Data)
imageView.image = image
}
}
}
Edit: To reuse this code I would suggest to use extension of UIImageView. Here's an example:
extension UIImageView {
func setImageFromURL(url: String) {
DispatchQueue.global().async {
let data = NSData.init(contentsOf: NSURL.init(string: url) as! URL)
DispatchQueue.main.async {
let image = UIImage.init(data: data as! Data)
self.image = image
}
}
}
}
Use this method whenever you want to set the image of an imageView from a url like this:
self.imageViewCookerProfilePic.setImageFromURL(url: "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcQNpKmjx1w3DRDZ9IXN81-uhSUA6qL6obkOthoUkb9RZkXf5pJ8")
Dude. You should learn some staff about async and sync code.
Here is the thing. Code in you downloadImage works synchronically, so it pass you URLTask and go straight to return, there you return you image variable, that is nil.
One of the solutions in to use callback block like this:
func downloadImage(urlImage : String?, complete: ((UIImage?)->Void)? = nil){
let url = URL(string: urlImage!)
let urlRequest = URLRequest(url: url!)
let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
if let data = data {
complete?(UIImage(data: data))
}
}
task.resume()
}
And then use it like this:
{ ...
downloadImage(urlImage: "", complete: { image in
if let image = image{
self.imageViewItemPic.image = image
}else{
print("no image")
}
})
...
}
You should read some tutorials about async code and web in swift. You could start with this site
downlaodImage() downloads an image asynchronously so
if let image = downlaodImage(...) { ... }
is always going to fail because program execution has continued before your response data has come back.
It would be easier just to set your images in the callback function closure of downlaodImage() as below by adding a UIImageView parameter to downlaodImage(). This way you can reduce the repetition of if else blocks by moving them to the downlaodImage function.
func downlaodImage(urlImage : String?, imageView: UIImageView) -> UIImage?{
var image : UIImage?
let url = URL(string: urlImage!)
let urlRequest = URLRequest(url: url!)
let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
if let data = data {
// print(data)
if let image = UIImage(data: data) {
imageView.image = image
} else {
print("failed to load image")
}
}
}
task.resume()
return image
}
Simplified code without if/else blocks
downlaodImage(urlImage: "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcQNpKmjx1w3DRDZ9IXN81-uhSUA6qL6obkOthoUkb9RZkXf5pJ8", imageView: imageViewItemPic)
downlaodImage(urlImage: "https://www.dominos.co.nz/ManagedAssets/OLO/eStore/all/Product/NZ/P015/P015_ProductImage_Small_en_Default_20140203_105245.png", imageView: imageViewCookerProfilePic)
I am following a tutorial about getting images from the web and storing them on the phone in Swift. For my purpose, I would like to know how I could only store them for one 'session', which means until the user stops using the app. The reason is that I want to change the image of the url every day.
Anyone any idea?
#IBOutlet var overLay: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let url = NSURL(string: "http://test.com")
// Update - changed url to url!
let urlRequest = NSURLRequest(URL: url!)
NSURLConnection.sendAsynchronousRequest(urlRequest, queue: NSOperationQueue.mainQueue(), completionHandler: {
response, data, error in
if error != nil {
println("There was an error")
} else {
let image = UIImage(data: data)
// self.overLay.image = image
var documentsDirectory:String?
var paths:[AnyObject] = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
if paths.count > 0 {
documentsDirectory = paths[0] as? String
var savePath = documentsDirectory! + "/overLay.jpg"
NSFileManager.defaultManager().createFileAtPath(savePath, contents: data, attributes: nil)
self.overLay.image = UIImage(named: savePath)
}
}
})
}
thank you so much!
Since you're only interested in keeping the image for the lifecycle of the app, it's perfectly viable to just hold a pointer to a UIImage object in memory, likely via some long-living object (AppDelegate would be a possible choice here).
Since you already have a UIImage from the data coming down the pipe, I'd simplify your code as such, or if you want to use some Singleton like the AppDelegate to manage the image state, see what happens when iWantToUseAppDelegate is set to true
#IBOutlet var overLay: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let iWantToUseAppDelegate = false // for demonstration purposes
let url = NSURL(string: "http://test.com")
// Update - changed url to url!
let urlRequest = NSURLRequest(URL: url!)
NSURLConnection.sendAsynchronousRequest(urlRequest, queue: NSOperationQueue.mainQueue(), completionHandler: {
response, data, error in
if error != nil {
println("There was an error")
} else {
let image = UIImage(data: data)
if iWantToUseAppDelegate {
let appDelegate = UIApplication.sharedApplication().delegate as! YourAppDelegateClass // YourAppDelegateClass has some property called "cachedImage"
appDelegate.cachedImage = image
self.overLay.image = appDelegate.cachedImage
} else {
self.overLay.image = image
}
}
})
}
You may need to tweak a few things but this code might work a little easier.
Used what mindfreek add to correct the code.
#IBOutlet var overLay: UIImageView!
var defaults: NSUserDefaults = NSUserDefaults()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let url = NSURL(string: "http://test.com")
// Update - changed url to url!
let urlRequest = NSURLRequest(URL: url!)
NSURLConnection.sendAsynchronousRequest(urlRequest, queue: NSOperationQueue.mainQueue(), completionHandler: {
response, data, error in
if error != nil {
println("There was an error")
} else {
let image = UIImage(data: data)
NSUserDefaults().setObject(NSKeyedArchiver.archivedDataWithRootObject(image!), forKey: "image")
if let imagedSaved: AnyObject = defaults.valueForKey("image")
{ overLay.image = image }
else { NSKeyedUnarchiver.unarchiveObjectWithData(NSUserDefaults().dataForKey("image")!) as UIImage }
}
})