Search code examples
iosjsonswiftuiimageviewnsurl

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


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.

Here is what I have so far and it works too but there is no link to the path and the image:

    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));
        }
    }
}

Solution

  • 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.