MNM MNM - 4 months ago 14
JSON Question

Load a NSURL from a json file swift and link it to an imageView

Ok so I am trying to get a "path" which is a url from a json file and link it to a imageView in my project. The image and the path come in one json line like this

{image:"http//www.something.com", path:"http://www.godbsdahb.com" }


I managed to download and fill in a scrollview with the images but now I want to click on the images and then redirect to another url. I manage the redirection, but not the linking of the path to the image. I am lost in how to do that. Any help will be appreciated.
Here is what I have so far and it works too but there is no link to the path and the image.

Thank for any help with this:

Here is the code for it:

var numOfPromo = 0;

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}

private func loadPromo() {
numOfPromo = 0;
PromoMan.sharedInstance.getAllPromoFromServer({
promotions in
for (_,promotion) in promotions {
self.downloadImage(NSURL(string: promotion.picture)!)
//The path for the promo is promotion.path
}},
onFail: { error_code, detail in Utility.log(self.dynamicType, msg: "Get All Promotions Fail, error_code: \(error_code), detail: \(detail)",
function: "viewDidLoad")})
}

//Add paths to the promtion images
func imageTapped(gesture: UIGestureRecognizer)
{
let url = NSURL(string: "http://google.com/")
UIApplication.sharedApplication().openURL(url!)
}

func downloadImage(url: NSURL){
getDataFromUrl(url) { (data, response, error) in
dispatch_async(dispatch_get_main_queue()) { () -> Void in
guard let data = data where error == nil else { return }

let tapGesture = UITapGestureRecognizer(target: self, action: #selector(PromotionViewController.imageTapped))
let imageView = UIImageView(image: UIImage(data: data));
imageView.addGestureRecognizer(tapGesture)
imageView.userInteractionEnabled = true

imageView.frame = CGRect(x: 0,
y: Int(self.numOfPromo * 230), width: Int(self.pScrollView.frame.size.width), height: 200)
self.pScrollView.addSubview(imageView)
self.numOfPromo = self.numOfPromo + 1;

//Make sure the images will all fit into the scrollview

self.pScrollView.contentSize = CGSizeMake(self.pScrollView.frame.size.width,
CGFloat(self.numOfPromo * 230));
}
}
}

func getDataFromUrl(url:NSURL, completion: ((data: NSData?, response: NSURLResponse?, error: NSError? ) -> Void)) {
NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) in
completion(data: data, response: response, error: error)
}.resume()
}


UPDATE:

Here is the http calls for the images and data

public func getAllPromotionsFromServer(
onSuccess: (promotions: [String: Promotion])->(),
onFail: (error_code: APIErrorCode, detail: String)->()){

let url = Config.getBaseUrl() + "/promotions"

Utility.log(self.dynamicType, msg: "Get All Promotions from Server", function: "getAllPromotionsFromServer")

APIManager.sharedInstance.get(url,params: nil,completion: { response in
//Change back to global queue
dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), {
switch response {

case APIResult.Failure(let error):

let msg = "Get Promotions Fail"
Utility.log(self.dynamicType, msg: msg, function: "getAllPromotionsFromServer")

let code = Utility.getAPIErrorCode(error)
onFail(error_code: code.error_code, detail: code.detail)
return

case APIResult.Success(let response):

if response.HTTP_Status == 200
{
let promotions = APIJSONParser.parsePromotions(response.jsonData)
print("Json response")
print(response.jsonData)
Utility.log(self.dynamicType, msg: "Get Promotions Success: no. \(promotions.count)", function: "getAllPromotionsFromServer")
onSuccess(promotions: promotions)
return

}
else{
let code = Utility.getAPIErrorCode(response)
onFail(error_code: code.error_code, detail: code.detail)
return
}

}
})
})

}


}

Update:

New Code block

private func loadPromotions() {
numberPromotions = 0;
PromotionManager.sharedInstance.getAllPromotionsFromServer({
promotions in
for (_,promotion) in promotions {
Utility.log(self.dynamicType, msg: promotion.picture, function: "viewDidLoad")

let p = (picture: promotion.picture, path: promotion.path)
self.promos.append(p)
self.downloadImage(NSURL(string: promotion.picture)!, index: self.promos.count)
//The path for the promo is promotion.path
}},
onFail: { error_code, detail in Utility.log(self.dynamicType, msg: "Get All Promotions Fail, error_code: \(error_code), detail: \(detail)",
function: "viewDidLoad")})
}

//Add paths to the promtion images
func imageTapped(gesture: UITapGestureRecognizer)
{
//let url = NSURL(string: "http://google.com/")
//UIApplication.sharedApplication().openURL(url!)
if let imageView = gesture as? UIImageView
{
if let url = NSURL(string: self.promos[imageView.tag].path)
{
UIApplication.sharedApplication().openURL(url)
}
}


}

func downloadImage(url: NSURL, index : Int){
getDataFromUrl(url) { (data, response, error) in
dispatch_async(dispatch_get_main_queue()) { () -> Void in
guard let data = data where error == nil else { return }

let tapGesture = UITapGestureRecognizer(target: self, action: #selector(PromotionViewController.imageTapped))
let imageView = UIImageView(image: UIImage(data: data));
imageView.addGestureRecognizer(tapGesture)
imageView.userInteractionEnabled = true
imageView.tag = index
//get images with a space between them
//200 = no space
//230 = black space
imageView.frame = CGRect(x: 0,
y: Int(self.numberPromotions * 230), width: Int(self.promotionsScrollView.frame.size.width), height: 200)
self.promotionsScrollView.addSubview(imageView)
self.numberPromotions = self.numberPromotions + 1;

//Make sure the images will all fit into the scrollview

self.promotionsScrollView.contentSize = CGSizeMake(self.promotionsScrollView.frame.size.width,
CGFloat(self.numberPromotions * 230));
}
}
}

Answer

When you get the promotions object (the parsed JSON data), you have there picture and path.

You are already using picture to show the pictures in the scrollview.

Now what you need to do is to tell the gesture recognizer to go to the specific path that belongs to that image. As you have one gesture recognizer for all the images (which is perfect), you need to associate "somehow" the pictures with the paths.

To do this, you can create a variable in the scope of the class, an dictionary for example, where you will save all the promotions with its pictures and paths.

I will use an array of tuples, but you can use any data type you want (dictionary, array, etc).

private var promos = Array<(picture: String, path: String)>()

Inside you for loop, save the data to the variable just created:

for (_, promotion) in promotions {
    let p = (picture: promotion.picture, path: promotion.path)
    self.promos.append(p)
    self.downloadImage(NSURL(string: promotion.picture)!, index: self.promos.count - 1)
}

Now you need to tell each UIImageView to what index of the promos array it belongs, just before adding it to the scrollview (It could be after setting userInteractionEnabled:

imageView.tag = index

And you need to add that index as a parameter of the function:

func downloadImage(url: NSURL, index: Int) { ... }

And now you can access it from the gesture recognizer action:

func imageTapped(gesture: UIGestureRecognizer)
{
    if let imageView = gesture.view as? UIImageView {
        if let url = NSURL(string: self.promos[imageView.tag].path) {
            UIApplication.sharedApplication().openURL(url)
        }
    }
}

I suggest changing gesture to sender as it would make more sense.