Caching JSON - Haneke get fetch values - ios

I am not able assign the values for var backgroundArray and var newsArray, as the fetch method returns nil. Within the fetch the values are available though. Also, is it a good way to refresh the cache by removing it such way in the commented section?
init(update: Bool){
let dataurl = "http://example.com"
let imgurl = "http://example.com"
let newsDataURL = NSURL(string: dataurl)!
let backgroundURL = NSURL(string: imgurl)!
var backgroundArray = [JSON]()
var newsArray = [JSON]()
let cache = Shared.JSONCache
// if update{
// cache.remove(key: dataurl)
// cache.remove(key: imgurl)
// }
cache.fetch(URL: newsDataURL).onSuccess { json in
let data = json.asData()
newsArray = JSON(data: data).arrayValue
}
cache.fetch(URL: backgroundURL).onSuccess{ json in
let data = json.asData()
backgroundArray = JSON(data: data).arrayValue
}
populateStories(newsArray, backgroundArray: backgroundArray)
}

Related

How to parse partial link in swift 4?

I am trying to show an image into my table cell view from an API. But it has given a partial link there, as a result, I am getting NSURL connection error code -1002.
Here is my API link: https://api.opendota.com/api/heroStats
I am trying to parse "icon" among them:
"img": "/apps/dota2/images/heroes/antimage_full.png?",
"icon": "/apps/dota2/images/heroes/antimage_icon.png",
My code:
// Generating imageview
if let imageURL = URL(string: heroes[indexPath.row].icon){
print (imageURL)
DispatchQueue.global().async {
let data = try? Data (contentsOf: imageURL)
if let data = data {
let image = UIImage(data: data)
DispatchQueue.main.async {
cell.charIcon.image = image
} //end of 2nd dispatch
}//end of if
}//end of 1st dispatch
}// end of imageURL
How can I solve this problem? Any easy way for swift 4?
You can get the url components of your api link and use your icon "partial link" to set the path property of the URL components. After that you just need to get the resulting url of the url components:
let apiLink = "https://api.opendota.com/api/heroStats"
let apiURL = URL(string: apiLink)!
if var urlComponents = URLComponents(url: apiURL, resolvingAgainstBaseURL: false) {
let iconString = "/apps/dota2/images/heroes/antimage_icon.png"
urlComponents.path = iconString
if let iconURL = urlComponents.url {
print(iconURL.absoluteString)
}
}
This will print
https://api.opendota.com/apps/dota2/images/heroes/antimage_icon.png
You can create a custom method to return a new URL based on the new path string as follow:
extension URL {
var urlComponents: URLComponents? {
return URLComponents(url: self, resolvingAgainstBaseURL: false)
}
func bySettingNew(path: String) -> URL? {
guard var urlComponents = urlComponents else { return nil }
urlComponents.path = path
return urlComponents.url
}
}
let apiLink = "https://api.opendota.com/api/heroStats"
let apiURL = URL(string: apiLink)!
let iconString = "/apps/dota2/images/heroes/antimage_icon.png"
if let iconURL = apiURL.bySettingNew(path: iconString) {
print(iconURL.absoluteString)
}
You can also add this helper to your project to make it easier for you to download an image asynchronously into your image view:
extension UIImageView {
func downloaded(from url: URL, contentMode mode: UIView.ContentMode = .scaleAspectFit) {
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() { [weak self] in
self?.contentMode = mode
self?.image = image
}
}.resume()
}
}
if let imageURL = apiURL.bySettingNew(path: heroes[indexPath.row].icon) {
cell.charIcon.downloaded(from: imageURL)
}

How would I access all values in my array?

I have appended an array with URL's like so
[FirebaseTest.storiesContent(storyUrl: https://firebasestorage.googleapis.com/v0/b/motive-73352.appspot.com/o/Content%2F20170525130622.jpg?alt=media&token=1e654c60-2f47-43c3-9298-b0282d27f66c), FirebaseTest.storiesContent(storyUrl: https://firebasestorage.googleapis.com/v0/b/motive-73352.appspot.com/o/20170525131400.mp4?alt=media&token=30fd962d-c305-4fa4-955d-dbb06ef91623), FirebaseTest.storiesContent(storyUrl: nil)]
In order to create this array, I am using a structure as a basis in order to append the content
struct storiesContent {
var storyUrl : String!
}
However, I am unsure how I would grab these URL's from this array in order to repeatedly download each image with SDWebImage in order to append each image to an array of UIImage's. I'm very new to Swift so my understanding is limited.
I really haven't used Firebase, but for what I understand here, you want to download the image from each link and save all the images in an array. You can achieve that by doing this:
//Get all URLS in an NSArray
let urlsArray:NSArray = ["https://firebasestorage.googleapis.com/v0/b/motive-73352.appspot.com/o/Content%2F20170525130622.jpg?alt=media&token=1e654c60-2f47-43c3-9298-b0282d27f66c","https://firebasestorage.googleapis.com/v0/b/motive-73352.appspot.com/o/20170525131400.mp4?alt=media&token=30fd962d-c305-4fa4-955d-dbb06ef91623"]
//Create a NSMutableArray where the final images will be saved.
let imagesArray:NSMutableArray! = NSMutableArray()
//Create a for that checks every link in the urlsArray.
for x in 0..<urlsArray.count
{
//Set the urlsArray content at position x as a URL
let imageUrl:URL = URL(string: urlsArray.object(at: x) as! String)!
//Generate a request with the current imageUrl.
let request:URLRequest = URLRequest.init(url: imageUrl)
//Start a NSURLConnection and get a Data that represents your image.
NSURLConnection.sendAsynchronousRequest(request, queue: OperationQueue.main, completionHandler: { (response, imageDta, error) in
//Store the received data as an UIImage.
let imageReceived:UIImage = UIImage(data: imageDta!)!
//Save the image to our imagesArray.
imagesArray.add(imageReceived)
})
//The Process loops until you get all the images.
}
UPDATE
Sure you can, the only thing here is that I removed your last object from your array because it contains a nil object and Swift can't candle nil objects:
//Using the NSArray style you're using.
let yourFireBaseArray = [FirebaseTest.storiesContent(storyUrl: https://firebasestorage.googleapis.com/v0/b/motive-73352.appspot.com/o/Content%2F20170525130622.jpg?alt=media&token=1e654c60-2f47-43c3-9298-b0282d27f66c), FirebaseTest.storiesContent(storyUrl: https://firebasestorage.googleapis.com/v0/b/motive-73352.appspot.com/o/20170525131400.mp4?alt=media&token=30fd962d-c305-4fa4-955d-dbb06ef91623)]
//Create a NSMutableArray where the final images will be saved.
let imagesArray:NSMutableArray! = NSMutableArray()
//Create a for that checks every link in the yourFireBaseArray.
for x in 0..<yourFireBaseArray.count
{
//Get your current array position string as a storiesContent object
let fireBaseString:storiesContent = yourFireBaseArray.object(at: x) as! storiesContent
//Use your fireBaseString object, get the storyURL string and set it in an URL.
let imageUrl:URL = URL(string: fireBaseString.storyURL)!
//Generate a request with the current imageUrl.
let request:URLRequest = URLRequest.init(url: imageUrl)
//Start a NSURLConnection and get a Data that represents your image.
NSURLConnection.sendAsynchronousRequest(request, queue: OperationQueue.main, completionHandler: { (response, imageDta, error) in
//Store the received data as an UIImage.
let imageReceived:UIImage = UIImage(data: imageDta!)!
//Save the image to our imagesArray.
imagesArray.add(imageReceived)
})
//The Process loops until you get all the images.
}
UPDATE 2
Okay, this is my example project, copy and paste and it will give you the resulted image.
import UIKit
class ViewController: UIViewController {
#IBOutlet var image:UIImageView!
var urlArray:NSMutableArray! = NSMutableArray()
var imagesArray:NSMutableArray! = NSMutableArray()
override func viewDidLoad() {
super.viewDidLoad()
urlArray = NSMutableArray.init(array: ["https://firebasestorage.googleapis.com/v0/b/motive-73352.appspot.com/o/Content%2F20170525130622.jpg?alt=media&token=1e654c60-2f47-43c3-9298-b0282d27f66c"])
// Do any additional setup after loading the view, typically from a nib.
}
override func viewDidAppear(_ animated: Bool) {
for x in 0..<urlArray.count
{
let imageUrl:URL = URL(string: "\(urlArray.object(at: x) as! String)")!
let request:URLRequest = URLRequest.init(url: imageUrl)
NSURLConnection.sendAsynchronousRequest(request, queue: OperationQueue.main, completionHandler: { (response, imageDta, error) in
if (error == nil)
{
self.imagesArray.add(UIImage(data: imageDta!)!)
if self.imagesArray.count > 0
{
self.image.image = self.imagesArray.object(at: 0) as! UIImage
}
}else{
print("ERROR - \(error!)")
}
})
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
To retrive Data from Firebase add propertylist file to your project it will hold the reference to your data base in firbase.
//Declare an array of string
var myArray = [String]()
//call this when your view load or in viewDidLoad()
ref = FIRDatabase.database().reference()
ref?.child("path").observe(.value, with: { (snapshot) in
if let snap = snapshot.value as? [String]{
self.myArray = snap
}
})
Then menupulate your array as you like.

Applying Base64 String to UIImageView not working in iOS Swift 2

I have a Base64 string saved from Swift into mysql db. When it comes back, it does not display an image.
How it looks in the db:
LzlqLzRBQVFTa1pKUmdBQkFRQUFTQUJJQUFELzRRQk1SWGhwWmdBQVRVMEFLZ0FBQUFnQUFnRVNBQU1BQUFBQg0KQUFFQUFJZHBBQVFBQUFBQkFBQUFKZ0FBQUFBQUFxQUNBQEZMUlUlJSUUFVVVVVQUZGRkZBQlJSUlFBVVVVVUFGRkZGQUJSUlJRQVVVVVVBRkZGRkFCUlJSUUFVVQ0KVVVBRkZGaWdBcEtXaWdBcEtXaw0Kb0FLS0tLQUNpaWlnQW9vb29BS0tLS0FDaWlpZ0Fvb29vQVNpbG9vQVNpbG9vQVNpaWlnQW9vb29BS0tLS0FDaQ0KaWlnQW9vb29BS0tLS0FDaWlpZ0Fvb29vQUtLS0tB
and this is how I am attempting to receive it but its not working:
let partUrl = "data:image/jpg;base64,";
let appndd = partUrl.stringByAppendingString(baseStringNew!)
let urlWeb = appndd
let requestURL: NSURL = NSURL(string: urlWeb)!
let urlRequest: NSMutableURLRequest = NSMutableURLRequest(URL: requestURL)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(urlRequest) {
(data, response, error) -> Void in
if error == nil {
NSLog("Success!")
dispatch_async(dispatch_get_main_queue(), {
imageNewView.layer.cornerRadius = 10.0
imageNewView.clipsToBounds = true
// Adding a border to the image profile
imageNewView.layer.borderWidth = 1.0
imageNewView.layer.borderColor = UIColor.grayColor().CGColor
imageNewView.image = UIImage(data:data!)
})
} else {
NSLog("Fail")
}
} //end of task
task.resume()
This displays a blank image in the UIImageView. How do I get this string to show up as an image?
Make sure that you prepend your data with data:image/png;base64.
Here is an q&a about this, How to display a base64 image within a UIImageView?
You might want to check the base64 string you stored and retrieved from your MySQL DB. Try using BLOB data type.
Then converting base64 string to NSData then UIImage is pretty easy and straightforward.
let rawData = NSData.init(contentsOfURL: NSURL(string: "http://cdn.sstatic.net/stackoverflow/company/img/logos/so/so-logo.png")!)!
let base64String = rawData.base64EncodedStringWithOptions(.Encoding64CharacterLineLength)
let imageData = NSData(base64EncodedString: base64String, options: .IgnoreUnknownCharacters)
let image = UIImage(data: imageData!)

Loop through xml NSData variable and get values in swift 2.1

I'm new to swift programming.
I wrote a code which gets xml output from rss feed and parse it into NSDATA type,
then I want to get title and image src values from it in a loop and send them to a table view to create a list.
when I get those values manually I mean like :
let appName = xml["rss"]["channel"]["item"][0]["title"].element!.text!
let appUrl = xml["rss"]["channel"]["item"][0]["description"]["img"].element!.attributes["src"]
my code works ok and one item creates in table view correctly.
but the problem is when I want to get all values from xml file.
I couldn't create and array of the xml which is NSDATA type, not a string to be able to loop through it.
all I could manage to work is the below code which returns all xml tags value which I don't want that :
func enumerate(indexer: XMLIndexer, level: Int) {
for child in indexer.children {
let appName = child.element!.text
let appUrl = child.element!.attributes["src"]
let ap = Apps(name: appName , img : appUrl)
self.tableData.append(ap)
self.tableView.reloadData()
enumerate(child, level: level + 1)
}
}
enumerate(xml, level: 0)
Any Idea how to get those values in a loop without mistaking or getting other values?
here is my code :
let url = NSURL(string: "http://razavitv.aqr.ir/index/rss/2")
let task = NSURLSession.sharedSession().dataTaskWithURL(url!) {(data, response, error) in
let dataString = NSString(data: data!, encoding: NSUTF8StringEncoding) as! String
let processedString = (dataString as NSString).stringByReplacingOccurrencesOfString("<![CDATA[", withString: "").stringByReplacingOccurrencesOfString("]]", withString: "") as String
let data: NSData = processedString.dataUsingEncoding(NSUTF8StringEncoding)!
let xml = SWXMLHash.parse(data)
// let appName = xml["rss"]["channel"]["item"][0]["title"].element!.text!
// let appUrl = xml["rss"]["channel"]["item"][0]["description"]["img"].element!.attributes["src"]
//
// let ap = Apps(name: appName , img : appUrl)
// self.tableData.append(ap)
//
// self.tableView.reloadData()
func enumerate(indexer: XMLIndexer, level: Int) {
for child in indexer.children {
let appName = child.element!.text
let appUrl = child.element!.attributes["src"]
let ap = Apps(name: appName , img : appUrl)
self.tableData.append(ap)
self.tableView.reloadData()
enumerate(child, level: level + 1)
}
}
enumerate(xml, level: 0)
}
task.resume()
very simple solution : just need to create a for loop with indexer inside.
here is the code :
//one root element
let count = xml["rss"]["channel"]["item"].all.count
for var i = 0; i < count; i++ {
let appName = xml["rss"]["channel"]["item"][i]["title"].element!.text!
let appUrl = xml["rss"]["channel"]["item"][i]["description"]["img"].element!.attributes["src"]
let ap = Apps(name: appName , img : appUrl)
self.tableData.append(ap)
self.tableView.reloadData()
}

SwiftyJSON - issues with parsing

I try to parse json with SwiftyJSON. One of the fields have url to image and i try to save it as NSData but I face crash and console errors. Crash appears when compiler comes to object creation
code it the following
var JSONStorage : [Article?]?
var objects = [Article?]()
override func viewDidLoad() {
super.viewDidLoad()
let number = arc4random_uniform(1000)
let urlString = "http://wirehead.ru/article.json?\(number)"
if let url = NSURL(string: urlString) {
if let data = try? NSData(contentsOfURL: url, options: []) {
let json = JSON(data: data)
for element in json["article"].arrayValue {
let id = Int(element["id"].stringValue)
let title = element["title"].stringValue
let subtitle = element["subtitle"].stringValue
let body = element["body"].stringValue
let img = element["images"]["main"].rawValue
let obj:Article = Article(id: id!, title: title, subtitle: subtitle, body: body, mainImage: img as! NSData)
objects.append(obj)
print("We are inside if let")
}
}
}
print(objects)
}
Link to JSON is http://wirehead.ru/article.json and here is with highlight http://pastebin.com/AAEFjsQN
Error that I get is
Any advice ?
["images"]["main"] contains an URL represented by a String
To get the image data, use something like this
let imgURLString = element["images"]["main"].stringValue
if let url = NSURL(string:imgURLString) {
let img = NSData(contentsOfURL:url)
}

Resources