Swift / iOS / Kanna / parse image from html using xpath - ios

I'm using the Kanna framework to use xpath parsing.
I'm successfully getting text from my desired url using the following code:
#IBAction func getSource(sender: AnyObject) {
if let doc = Kanna.HTML(url: (NSURL(string: "http://qwertz.com")!), encoding: NSUTF8StringEncoding) {
// Search for nodes by XPath
for link in doc.xpath(".//*[#id='bday_form']/div[1]/img[1]") {
print(link.text)
print(link["href"])
self.testLabel.text = link.text
}
}
print("test22")
}
How can I parse images and put them into my imageView Outlet #IBOutlet weak var imageViewOutlet: UIImageView!
Help is very appreciated.
self.imageViewOutlet.image = link
throws: Cannot assign value of type 'XMLElement' to type 'UIImage?'

You have to download the image before assign to UIImageView. There is really good library to download image from the web. It has swift support also.
Here is :https://github.com/rs/SDWebImage
Here is an example:
NSURL *url = [NSURL URLWithString:link]
[self.imageView sd_setImageWithURL:url];

you need to download the image from the url first, and then create the UIImage
Here's an example of how to do this
Loading/Downloading image from URL on Swift where the shortest approach (from #Lucas Eduardo) looks like this
let url = NSURL(string: image.url)
let data = NSData(contentsOfURL: url!)
imageURL.image = UIImage(data: data!)

Related

xCode error:- Cannot assign value of type 'URL?' to type 'UIImage?'

I am attempting to pull an image url from Firebase Users profile.
When I call:-
#IBOutlet weak var profileImage: UIImageView?
profileImage?.image = Auth.auth().currentUser?.photoURL
I get the following error appear:-
Cannot assign value of type 'URL?' to type 'UIImage?'
I try to use the fixes that xcode provides but these only lead to further issues.
When I print:-
print(Auth.auth().currentUser?.photoURL as Any)
I get the following output, so I know there is an image there.
Optional(https://graph.facebook.com/10X60X70X35X101X5/picture)
How am I able to pull this image in, or is it possible to convert it to a string so I am able to use it?
Thanks in advance.
You can't assign url to image , use SDWebImage to download it asynchronously to not block main thread
if let url = Auth.auth().currentUser?.photoURL {
self.profImageV.sd_setImage(with: url , placeholderImage: UIImage(named: "edit2.png"))
}
The error message is very clear, you're trying to assign a URL? type to UIImage? type. Since it's a URL? you should first unwrap it, and download the image with this url. When you have your UIimage then you can assign it.
Actually you are converting URL type to UIImage type, that is not possible. You need to download image from url and set in an image view or wherever you want to use.
DispatchQueue.global(qos: .background).async {
if let url = URL(string: <#imageUrl#>) {
do {
let imgData = try Data(contentsOf: url)
if let image = UIImage(data: imgData) {
DispatchQueue.main.async {
self.imageView.image = image
}
}
} catch {
debugPrint("From catch block: Image could not be downloaded !!")
}
}
}
You need to download the image and then set the imageView's image to the downloaded image. You can do this using URLSession's dataTask:
// Playground code
import UIKit
import PlaygroundSupport
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
let session = URLSession.shared
let url = URL(string: "http://via.placeholder.com/400x400")!
_ = session.dataTask(with: url) { data, response, error in
guard error == nil else {
print(error)
return
}
guard let data = data else {
print("[DEBUG] - No data returned")
return
}
DispatchQueue.main.async {
imageView.image = UIImage(data: data)
}
}.resume()
PlaygroundPage.current.liveView = imageView
Or you can use a library such as KingFisher to handle it for you, then you just call it like so:
let url = URL(string: "url_of_your_image")
imageView.kf.setImage(with: url)

How to add GIF images to Assets folder and load them in UIImageView programmatically

I am trying to put my #2x and #3x GIF images into the Assets folder in Xcode. I have tried the following links but it didn't work for me.
Link 1 and Link 2.
I am currently loading the GIF files by adding them to my project bundle and accessing it using this
let bundleURL = NSBundle.mainBundle()
.URLForResource("phone_animation", withExtension: "gif")
But I want to load them from my Assets folder. Is there a way I can do it? And how do I load them into my imageview after adding it to Assets?
According to your comment, this is the solution that you are searching:
make an extension of UIImage which uses SwiftGif:
extension UIImage {
public class func gif(asset: String) -> UIImage? {
if let asset = NSDataAsset(name: asset) {
return UIImage.gif(data: asset.data)
}
return nil
}
}
Then tuning #Ganesh suggestion with the extension you might do something like:
imageView.image = UIImage.gif(asset: "YOUR_GIF_NAME_FROM_ASSET")
To load gif into UIImage I suggest two libraries
1) you can use this library
simply you can load it into UIImageView
let imageData = try! Data(contentsOf: Bundle.main.url(forResource: "logo-animation", withExtension: "gif")!)
let gifImage = UIImage.gif(data: data!)
imageView.image = gifImage
2) Or you can use this library
import FLAnimatedImage
then add outlet
#IBOutlet weak var fashImage: FLAnimatedImageView!
then use this code
let imageData = try! Data(contentsOf: Bundle.main.url(forResource: "logo-animation", withExtension: "gif")!)
fashImage.animatedImage = FLAnimatedImage(animatedGIFData: imageData)
Hope this will help you

NSData init?(contentsOf url: URL) migration from Swift 2 to Swift 3

New to iOS/Swift. I am trying to migrate a project (that simply fetches contents from a URL via the NSData init() method) from Swift 2 to Swift 3. The original code looks like this:
let loadedImageData = NSData(contentsOfURL: imageURL)
dispatch_async(dispatch_get_main_queue()) {
if imageURL == user.profileImageURL {
if let imageData = loadedImageData {
self.profileImageView?.image = UIImage(data: imageData)
}
}
}
Swift 3 migration:
let loadedImageData = NSData(contentsOf: imageURL as URL)
DispatchQueue.main.async {
if imageURL == user.profileImageURL {
if let imageData = loadedImageData {
self.profileImageView?.image = UIImage(data: imageData as Data)
}
}
}
I am not sure as to why we need to cast the NSData return value as a URL and then cast that return again to a Data type while loading the image within Swift 3. We are assigning the raw data to a variable loadedImageData in both the version. Why the casting then? It seems that the UIImage init() method needs a data object within Swift 3. However for Swift 2 there is no casting for the same. Why is that?
Thanks for the help.
The migration consists of some changes in those methods' signatures, namely, the types they accept.
In Swift 2, NSData(contentsOfURL:) and UIImage(data:) take NSURL and NSData, respectively.
Currently, they have been changed to NSData(contentsOf:) and UIImage(data:) that accept, respectively, URL (struct) and Data (instead of NSData); as a result, the casts are necessary unless you constructed your URL from type URL instead of NSURL.
You could use, instead, Data(contentsOf: URL) to avoid the cast as well.

Why can't I upload images to Parse? Anybody know of a different way to do this?

I just need to upload some images, and I feel like my simple code should work, but for some reason it isn't. I'm getting an error saying that my object exceeds the Parse.com limit of 128kb... And I'm sure it doesn't actually exceed that. Code is here.
override func viewDidLoad() {
super.viewDidLoad()
func addCards(urlString:String) {
var newCard = PFObject(className: "Cards")
let url = NSURL(string: urlString)
let urlRequest = NSURLRequest(URL: url!)
NSURLConnection.sendAsynchronousRequest(urlRequest, queue: NSOperationQueue.mainQueue(), completionHandler: {
response, data, error in
newCard["image"] = data
newCard.save()
})
}
addCards("http://image.com/image")
You shouldn't just be pushing the image data direct into the object. Instead, create a PFFile instance with the data and set that. Then, save the file and the card at the same time (using saveAll).
See the following link from Parse documentations which has a code snippet and also the reason for using PFFile as suggested by Wain:
https://www.parse.com/docs/ios/guide#files
According to Parse documentation: You can easily store images by converting them to NSData and then using PFFile. Suppose you have a UIImage named image that you want to save as a PFFile:
let imageData = UIImagePNGRepresentation(image)
let imageFile = PFFile(name:"image.png", data:imageData)
var userPhoto = PFObject(className:"UserPhoto")
userPhoto["imageName"] = "My trip to Hawaii!"
userPhoto["imageFile"] = imageFile
userPhoto.saveInBackground()

How can I upload images to Parse.com programatically?

I have a very large set of images to upload, and the best way to do that is to let my app do it for me. But after copy and pasting the code from Parse's docs, it doesn't work.
var image = NSData(contentsOfURL: NSURL(string: "XY1_EN_1.jpg")!)!
#IBAction func xyButton1(sender: AnyObject) {
for var i = 1; i < 147; i++ {
let imageData = UIImageJPEGRepresentation(image)
//ERROR on line above: Missing argument for parameter #2 in call
let imageFile = PFFile(name:"image.png", data:imageData)
var userPhoto = PFObject(className:"Cards")
userPhoto["imageName"] = "XY1_EN_1"
userPhoto["imageFile"] = imageFile
userPhoto.save()
}
}
What am I doing wrong?
There are two problems with the code. UIImageJPEGRepresentation(::) takes two parameters, a UIImage and a float. Right now you are calling UIImageJPEGRepresentation(_:) and giving it NSData. If you want to use that method to get NSData from an Image, you need to make self.image of UIImage type instead of NSData. Maybe init your variable image with UIImage(named: "imageName") if the image is bundled.

Resources