Browse Month: September 2017

Download PDF file using Alamofire in Swift3

Almofire is a very popular library for networking related coding(eg. API call, Downloading Stuffs etc) and totally developed in swift which is replacement of AFNetworking library of ObjectiveC. It has multiple features like Image cacheing, API call integration,File downloading etc. Today we are going to dive into Download PDF file using Alamofire in Swift.

Pods are available for almofire on GitHub for integration of this library into your own project, some steps are explained as follows:- 

  • First create a pod file for implementing the Alamofire and MBProgressHUD

pod ‘Alamofire’ // Download PDF file
pod ‘MBProgressHUD’ //Downloading Progress Bar

  • We have to create Webview Object for open downloaded PDF url.
  • Use following function in view controller and pass the url string to the function.

 

 func downloadPDFFile(urlString:String)

{

    let hud = MBProgressHUD.showAdded(to: self.view, animated: true)

    hud.mode = MBProgressHUDMode.annularDeterminate

    hud.label.text = “Loading…”

    

    let destination: DownloadRequest.DownloadFileDestination = { _, _ in

      let documentsURL:NSURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! as    NSURL

      print(“***documentURL: “,documentsURL)

      let PDF_name : String = “Downloded_PDF_Name”

      let fileURL = documentsURL.appendingPathComponent(PDF_name)

      print(“***fileURL: “,fileURL ?? “”)

       return (fileURL!,[.removePreviousFile, .createIntermediateDirectories])

    }

    Alamofire.download(urlString, to: destination).downloadProgress(closure: { (prog) in

      hud.progress = Float(prog.fractionCompleted)

    }).response { response in

      

      hud.hide(animated: true)

      if response.error == nil, let filePath = response.destinationURL?.path    {

        print(“File Path”,filePath)

      

        //Open this filepath in Webview Object

        

        let fileURL = URL(fileURLWithPath: filePath)

        let request = URLRequest(url: fileURL)

        webView.loadRequest(request)

      }

    }

  }

One fantastic way to Load ‘CollectionView’ inside ‘TableViewCell’ using Two ‘Extensions’ in swift3, iOS

As We know we, Often, we assign a collection view’s data source to its view controller. But here the problem is that we have only one view controller and many collection views.

As I have taken number of ‘Sections’ inside table view. so following is the Solution to distinguish between a collection view on the first section , and one on the second , third and fourth…

So here is a way to store which table view cell a collection view is in.

 

  • TableView : I have taken multiple sections And Only One Row.
  • Collection View : I have Only one Section And Multiple Items.

 

In ViewController.swift Use Following –

  • Extension :

extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource {

     func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int   {

          return 3

     }

     func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell   {

          let cell = collectionView.dequeueReusableCell(withReuseIdentifier: “UploadCell”, for: indexPath) as!                 UploadCollectionViewCell

          //Code

    return cell

     }

     func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath  {       

          print(“Collection view at row \(collectionView.tag) selected index path \(indexPath)”)

     }

}

 

 

In TableViewCell.swift Use Following –

  • Extension :

  extension TableViewCell  {

          func setCollectionViewDataSourceDelegate<D: UICollectionViewDataSource & UICollectionViewDelegate>(_ dataSourceDelegate: D, forRow row: Int) {

               collectionView.delegate = dataSourceDelegate

               collectionView.dataSource = dataSourceDelegate

               collectionView.tag = row

               collectionView.setContentOffset(collectionView.contentOffset, animated:false) // Stops collection view if it was scrolling.

               collectionView.reloadData()

          }

          var collectionViewOffset: CGFloat {

               set { collectionView.contentOffset.x = newValue }

               get { return collectionView.contentOffset.x }

          }

     }

 

*******  One IMP addition in ‘willDisplay’ method of tableView in ViewController.swift  *******

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {

          guard let tableViewCell = cell  else { return }

          tableViewCell.setCollectionViewDataSourceDelegate(self, forRow: indexPath.section)

     }

 

 

Thanks.

iOS – Tap to zoom and share image using Apple’s QuickLook framework

QuickLook framework is one of the best framework by Apple. It can be used to preview files such as iWork, MS Office, RTF, CSV documents, pdf, text files, Images.

You can use this framework to implement image zooming and sharing feature. We don’t need to write this zooming and sharing code ourself. QuickLook framework provides this all awesome functionality.

Let’s start implementing this powerful and easy framework.
(I have used Swift 3 and XCode 8.3.2)

*  Use Single View application template and give a name to your project(App). Select Swift language.

* On Storyboard make your view controller UI like this :  Check this image.
Take 2 UIImageViews  and take 1 UIButton on each UIImageView. Create necessary IBOutlets and IBActions.

* Your final ViewController Code should look like below.


import UIKit
import QuickLook   // Import QuickLook to use it’s functionalities.

let imageURLs =  [“https://static2.hdwallpapers.net/wallpapers/2015/03/24/574/thumb_steve-jobs-typographic-portrait.jpg”, “http://www.planetware.com/photos-large/F/france-paris-eiffel-tower.jpg”]

class Downloader  {    // This is Image Downloader helper class
        class func downloadImageWithURL(_ url:String) -> UIImage? {
               let data = try? Data(contentsOf: URL(string: url)!)

if
let imgData = data {
                   return UIImage(data: imgData)
               }

              else {
                  print(“\n\nThis image url may be wrong : \n \(url)”)
                  return nil
               }

    }

}


class iOSConcurrencyViewController: UIViewController, QLPreviewControllerDataSource

    // Connect this 2 imageView outlets with your imageViews.
    @IBOutlet weak var imageView1: UIImageView!  
    @IBOutlet weak var imageView2: UIImageView!

   // Connect this outlet with Bar button named – Start
    @IBOutlet
weak var barButton_Start: UIBarButtonItem!

   let quickLookController = QLPreviewController()
   var myQLimageURL: URL?

    override func viewDidLoad() {

        super.viewDidLoad()

       // Add QuickLook dataSource to  self
       quickLookController.dataSource =
self

    }

@IBAction func didClickOnStart(_ sender: AnyObject) {  // Connect this IBAction with Bar button item – Start

        // Here we will start downloading images and then disable the start button.
        barButton_Start.isEnabled = false

        //   ##################  Dispatch Queues ##################

         // Default(System provided) global Dispatch queue

        // It can download any image in any order at any time once started.

        let imgDownloader_DefaultConcurrentQueue = DispatchQueue.global(qos: .default)

        //img1

        downloadUsingGCD_AndShowImage(in: imageView1, index: 0, with: imgDownloader_DefaultConcurrentQueue)

        //img2

        downloadUsingGCD_AndShowImage(in: imageView2, index: 1, with: imgDownloader_DefaultConcurrentQueue)

}

 

// For GCD – Dispatch Queues

    func downloadUsingGCD_AndShowImage(in imageView: UIImageView, index imageIndex: Int, with Queue: DispatchQueue) {

            Queue.async {  // To avoid blocking UI, download images in background.

            let img = Downloader.downloadImageWithURL(imageURLs[imageIndex])

            let fileParts = imageURLs[imageIndex].components(separatedBy: “/”)

            DispatchQueue.main.async { // UI update code should be on main thread.

                imageView.image = img

                self.saveImageToDirectory(imageName: fileParts.last!, img: img!)

            }

        }

    }


// You have used a button on each imageView. Give 0 tag for button1 and 1 for button2. Then connect both buttons IBAction to this.
@IBAction func button_ZoomImage_Tapped(_ sender: UIButton) {

        var index = Int()

        switch sender.tag {

        case 0:

            index = 0

        case 1:

            index = 1

        default:

            break

        }

        // Get image name with extension from image url
        let fileParts = imageURLs[index].components(separatedBy: “/”)

        myQLimageURL = getImageFromDirectory(imageName: fileParts.last!) 

        if let QLImgURL = myQLimageURL {

            if QLPreviewController.canPreview(QLImgURL as QLPreviewItem) { 

                // This line refreshes current preview otherwise you will see only 1 image for both image views.
                quickLookController.refreshCurrentPreviewItem() 

                //navigationController?.pushViewController(quickLookController, animated: true)

                            present(quickLookController, animated: true, completion: {

                                print(“completion block”)

                            })

            }

        }

    }

 

    // Get Documents Directory helper function

    func getDocumentsDirectory() -> URL {

        let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)

        let documentsDirectory = paths[0]

        return documentsDirectory

    }

    

    // Save Image to Directory

    func saveImageToDirectory(imageName: String, img: UIImage) {

        //if let image = UIImage(named: imageName) {

            if let data = UIImageJPEGRepresentation(img, 0.8) {

                let filename = getDocumentsDirectory().appendingPathComponent(imageName)

                try? data.write(to: filename)

            }

        //}

    }

    

    // Get Image from Directory

    func getImageFromDirectory(imageName: String) -> URL? {

        let imageURL = getDocumentsDirectory().appendingPathComponent(imageName)

        let imagePath = (getDocumentsDirectory().appendingPathComponent(imageName)).path

        if FileManager.default.fileExists(atPath: imagePath) {

            return imageURL

        }

        else {

            return nil

        }

    }

    

    // QuickLook Datasource
    func numberOfPreviewItems(in controller: QLPreviewController) -> Int {

        return 1    // This will return only 1 image at a time

    }

    func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {

        return myQLimageURL! as QLPreviewItem

    }

 

Have fun… 🙂

Let me know if you have any queries or problems implementing this feature. Enjoy … 🙂

 

Animated Launch Screen

Basically when we want to set an image for LaunchScreen then we use LaunchScreen.storyboard for setting an image, but as this file does not have any class file (eg .swift or .h & .m) so we can not write code for animating that image at runtime. To achieve this we need to use main.storyboard

Steps to implement animated Launch Screen : –

1) Click on project name on ProjectNavigatorPanel -> go to Target.

2) Scroll down  to “Main Interface” -> click down arrow -> change  LaunchScreen.storyboard to Main.

3) Go to Main.storyboard -> Select your view controller for which you want to set animated Launch Screen.

4) Select your view controller -> click on Editor on top menu bar -> Embed In -> select Navigation Controller

5) Set Navigation Controller as Initial ViewController of your project.

Now create a class for writing code of animation and connect it to view controller on Main.storyboard , Once the animation is done you can push a view controller to next view controller programmatically.

 

NOTE : You can write any type of animation code in that class file (eg .swift) as per your requirements. I have used .gif image for LaunchScreen using code from “Swift+Gif.swift” file.Have a fun with animation Code Here

NSSortDescriptor in swift 3

To sort an json array using NSSortDescriptor in swift3

 

NSSortDescriptor :

A sort descriptor describes a comparison used to sort a collection of objects. You create an instance of NSSortDescriptor that specifies the property key to be sorted, and whether the comparison should be in ascending, or descending order. A sort descriptor can also specify a method to use when comparing the property key values, rather than the default of compare:.

It is important to remember that NSSortDescriptor does not sort objects. It provides the description of how to sort objects. The actual sorting is done by other classes, often NSArray or NSMutableArray.

NSSortDescriptor objects are constructed with the following parameters:

  • key: for a given collection, the key for the corresponding value to be sorted on for each object in the collection.
  • ascending: a boolean specifying whether the collection should be sorted in ascending (YES) or descending (NO) order.

 

// replace the urlname

let task = URLSession.shared.dataTask(with: NSURL(string: “urlname”)! as URL, completionHandler: { (data, response, error) -> Void in

       if (data != nil || error == nil)

                {

                let dict: AnyObject? = try! JSONSerialization.jsonObject(with: data!, options: []) as AnyObject?

                 if (dict is NSArray)

                {

                    let dictArray : NSArray = dict as! NSArray

                    let aArray : NSMutableArray = NSMutableArray(array: dictArray)

                     //replace keyname whatever you want an array should be sort ,for example , json array contain “id” key 

                     //you want array should be sort using that “id” , keyname should be “id”

                   // if you want array ascending then set value  “true” for key ascending, otherwise set to “false”

                    let descriptor: NSSortDescriptor = NSSortDescriptor(key: “keyname”, ascending: true)

                    // sortedResult is an result array which is sorted using key defined in NSSortDescriptor

                     sortedResults = aArray.sortedArray(using: [descriptor]) as NSArray

                   print(sortedResults)

                    }

                   }

        })

        task.resume()

iOS – Image Downloader helper class (Swift 3)

Image Downloader Class written in Swift 3 to download images.

class Downloader {

        class func downloadImageWithURL(_ url:String) -> UIImage? {

           let data = try? Data(contentsOf: URL(string: url)!)

         if let imgData = data {

            return UIImage(data: imgData)

        }

        else {

            print(“\n\nThis image url may be wrong : \n \(url)”)

            return nil

        }

    }

} // class end

You can then use this class to download and show image in your UIImage  as below:

        let image  =  Downloader.downloadImageWithURL(“http://images.freeimages.com/images/premium/small-comps/3352/33528960-palouse-waterfall-washington.jpg”)

yourImageView.image = image

Then you are done. Enjoy… 🙂