Browse Tag: ios

Move View/ScrollView to keep TextField visible when keyboard appears!

There is a very common but tricky part comes while handling textfields position when keyboard appears. Its sometimes become headache for developers to handle such small but tricky issue. When keyboard appears then some textfields get covered and user can’t see while editing it.

There are some solutions to handle this but many of them works only for the first time. And then doesn’t work.
I have found one best solution and it works great always and I have modified this code to work on Swift 4. I have used XCode 9.1 for this tutorial code.

Lets do it.

You will have to create new project to try this. Design your storyboard like the image from below link.

https://drive.google.com/a/nanostuffs.com/file/d/1KXJV49BP07T2q8nca4vKlz3eMU7xtkNG/view?usp=sharing

And set delegate of all textFields to ViewController.


Now in your ViewController class you can use it like below


 

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

     @IBOutlet weak var myScrollView: UIScrollView!

     @IBOutlet weak var constraintContentHeight: NSLayoutConstraint!

     override func viewDidLoad() {

          super.viewDidLoad()

}

override func viewWillAppear(_ animated:Bool) {

     super.viewWillAppear(animated)

//1  Add this observers to observe keyboard shown and hidden events
      NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(aNotification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)

     NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(aNotification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)

}

override func viewWillDisappear(_ animated: Bool) {

     super.viewWillDisappear(animated)

//2  Remove the observers added for keyboard from your ViewController

     NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)

     NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)

}

var activeField: UITextField?

// MARK: – UITextField Delegates

//3  ViewController activeField is an object of UITextField which will be used to manage and resign current active textField 

func textFieldShouldReturn(_ textField: UITextField) -> Bool {

     textField.resignFirstResponder()

     return true

}

func textFieldDidBeginEditing(_ textField: UITextField) {

     activeField = textField

}

func textFieldDidEndEditing(_ textField: UITextField) {

     activeField = nil

}

// Called when the UIKeyboardWillHide is sent

//4  This method is called from selector. So it requires @objc keyword and this method will adjust your scrollView (here myScrollView  😉)  and textFields to show as original.

@objc func keyboardWillBeHidden(aNotification: NSNotification) {

     let contentInsets: UIEdgeInsets = .zero

     self.myScrollView.contentInset = contentInsets

     self.myScrollView.scrollIndicatorInsets = contentInsets

}

// Called when the UIKeyboardWillShow is sent

//5
This method will adjust your scrollView
and will show textFields above the keyboard.
@objc
func
keyboardWillShow(aNotification: NSNotification) {

     var info = aNotification.userInfo!

     let kbSize: CGSize = ((info[“UIKeyboardFrameEndUserInfoKey”] as? CGRect)?.size)!

     print(“kbSize = \(kbSize)”)

     let contentInsets: UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0)

     myScrollView.contentInset = contentInsets

     myScrollView.scrollIndicatorInsets = contentInsets

     var aRect: CGRect = self.view.frame

     aRect.size.height -= kbSize.height

     if !aRect.contains(activeField!.frame.origin) {

          self.myScrollView.scrollRectToVisible(activeField!.frame, animated: true)

     }

  }

} // Class End

Alternative for xib in swift3 iOS

Hi all,

Lets see the simplest and best way to replace or avoid use of xib by using UIView on storyboard.

 

  1.  Go on storyboard ,select Viewcontroller Drag UIView and drop it between FirstResponder and exit button on that.
  2.  Add IBOutlet of that UIView on ViewController.swift file.
  3.  set the center, width, height for that UIView
  4.  Refer Following code :

 

——– IBOutlet ——–

@IBOutlet var View_alternativeForXib: UIView!

var view_BGDimmer = UIView()

    

——– Set the center , width, height for that UIView as well as add transperent Background view ———

 

       View_alternativeForXib.center = (UIApplication.shared.keyWindow?.center)!

          view_BGDimmer.frame = (UIApplication.shared.keyWindow?.frame)!

         View_alternativeForXib.frame.size.width = (UIApplication.shared.keyWindow?.frame.width)! – 40

         View_alternativeForXib.frame.origin.x = (UIApplication.shared.keyWindow?.frame.origin.x)! + 20

          view_BGDimmer.backgroundColor =  colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)

          view_BGDimmer.alpha = 0.3

          UIApplication.shared.keyWindow?.addSubview(view_BGDimmer)

          UIApplication.shared.keyWindow?.insertSubview(self.View_alternativeForXib, aboveSubview: self.view_BGDimmer)

          UIView.animate(withDuration: 0.1, animations: {

          }) { (completed) in

          }

 

——-  To dismiss view ——

   func dimissPopUp() {

        UIView.animate(withDuration: 0.2, animations: {

            self.view_BGDimmer.alpha = 0.0

            self.View_alternativeForXib.removeFromSuperview()

            self.view.layoutIfNeeded()

        }) { (completed) in

            self.view_BGDimmer.removeFromSuperview()

        }

    }

 

 

Thanks,

 

 

UserDefaults with NSCoding and Codable to save any kind of Data… Part – 1 😎

 UserDefaults  is one of the good and handy storage you can use. You can use UserDefaults to store any basic data type for as long as the app is installed. For example, you can use basic types as BoolFloatDoubleIntString, or URL, but you can also write more complex types such as arrays, dictionaries and Date – and even Data values.

Advantage: After writing data to UserDefaults, when you run the app the UserDefaults data gets automatically loaded. Its very easy to use it.

Disadvantage:  Its a bad idea to use UserDefaults to save lot of data as it slows down your app loading and increases app load time.

You can use it making an instance of the UserDefaults like below:

let defaults = UserDefaults.standard

Now you can save your data like below:

defaults.set(26, forKey: "Age")

defaults.set(true, forKey: “is_iOS_Best”)

defaults.set(CGFloat.pi, forKey: “Pi”)

defaults.set(Date(), forKey: "CurrentDate")
let myArray = ["iOS", "macOS"]
defaults.set(myArray, forKey: "SavedArray")
let myDict = ["Name": "Sagar", "Hobby": "Coding"]
defaults.set(dict, forKey: "SavedDict")

You can get the stored values/data back using below methods:

  • integer(forKey:) returns an integer if the key existed, or 0 if not.
  • bool(forKey:) returns a boolean if the key existed, or false if not.
  • float(forKey:) returns a float if the key existed, or 0.0 if not.
  • double(forKey:) returns a double if the key existed, or 0.0 if not.
  • object(forKey:) returns Any? so you need to conditionally typecast it to your data type.You can save a complex kind of data too in UserDefaults using NSCoding and Codable protocols.
    NSCoding is available for both Objective-C and Swift developers but Codable is only for Swift developers.We will see the usage of first one : NSCoding


     NSCoding

    Your class must confirm to NSCoding before using it, like you use other protocols : UITableViewDataSource and UITableViewDataDelegate.

    Then you can implement it using below method which changes the object graph to Data, so that it becomes able to save in UserDefaults.

    archivedData(withRootObject:) method of NSKeyedArchiver

    There are many Apple’s own classes that support NSCoding like: UIColorUIImageUIViewUILabelUIImageViewUITableViewSKSpriteNode
    but your custom classes don’t support it by default.

    You can also refer HackingWithSwift blog for free and good coding tutorials.

    Let us have a look at below example for its use.

    For example:

    Consider your custom class is MySelf in which you are using name and image properties.


    import UIKit

    class MySelf: NSObject, NSCoding { //Here NSObject is required to use NSCoding.

         func encode(with aCoder: NSCoder)  {    // this method is required and used to encode data

             aCoder.encode(name, forKey: name)

             aCoder.encode(image, forKey: image)

         }

        required init?(coder aDecoder: NSCoder) {   // this method is required and used to decode data

             name = aDecoder.decodeObject(forKey: name) as! String

            image = aDecoder.decodeObject(forKey: image) as! String

       }


    var
    name: String

       var image: String


    init
    (name: String, image: String) {

             self.name = name

            self.image = image

       }

    }

     


    Now in your ViewController class you can use it like below


     

    import UIKit

    class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UICollectionViewDataSource {

        var people = [MySelf]()          // array of MySelf type data

        @IBOutlet weak var myCollectionView: UICollectionView!

        override func viewDidLoad() {

              super.viewDidLoad()

              let defaults = UserDefaults.standard

              if let savedPeople = defaults.object(forKey: people) as? Data {

                      // Get saved values using below method
    people
    = NSKeyedUnarchiver.unarchiveObject(with: savedPeople) as! [MySelf]
    }

          }

        @IBAction func barButton_addPersonTapped(_ sender: Any) {

               addPerson()    

        }

        func addPerson() {      // Show ImagePickerController

               let imagePicker = UIImagePickerController()

              imagePicker.allowsEditing = true

             imagePicker.delegate = self

             present(imagePicker, animated: true) {

                 //  completion block

              }

          }

        func getDocumentsDirectory() -> URL {   // // Get DocumentsDirectory

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

              let documentsDirectory = paths[0]

              return documentsDirectory

        }

    // UICollectionViewController Delegates


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

         return people.count

    }

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

          let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PersonCollectionViewCell, for: indexPath) as! PersonCollectionViewCell

         let aPerson = people[indexPath.item]

         cell.name.text = aPerson.name

         let path = getDocumentsDirectory().appendingPathComponent(aPerson.image)

         cell.imageView.image = UIImage(contentsOfFile: path.path)

         cell.imageView.layer.cornerRadius = 3

         cell.imageView.layer.borderWidth = 2

         cell.imageView.layer.borderColor = UIColor(displayP3Red: 0, green: 0, blue: 0, alpha: 0.3).cgColor

         cell.layer.cornerRadius = 7

        return cell

     }

    // UIImagePickerController Delegates

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {

         guard let image = info[UIImagePickerControllerEditedImage] as? UIImage else { return }

         let imageName = UUID().uuidString

         let imagePath = getDocumentsDirectory().appendingPathComponent(imageName)

         if let jpegData = UIImageJPEGRepresentation(image, 80) {

               try? jpegData.write(to: imagePath)  // Write your image jpeg data to imagePath

         }

         let aPerson = MySelf(name: Img, image: imageName)

         people.append(aPerson)

         myCollectionView.reloadData()

         dismiss(animated: true) {

               //

         }

         self.save()  // Save newly added Image with name.

      }


    func
    save() {  // Save image and name using archivedData method of  NSKeyedArchiver

            let saveData = NSKeyedArchiver.archivedData(withRootObject: people)

            let defaults = UserDefaults.standard

          defaults.set(saveData, forKey: people)

       }

    }


    Your custom collectionViewCell class: PersonCollectionViewCell 


     

    import UIKit

    class PersonCollectionViewCell: UICollectionViewCell {

           @IBOutlet weak var imageView: UIImageView!

           @IBOutlet weak var name: UILabel!

    }


    Have fun… 🙂

    I will show the usage of Codable in my next post.

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

Push Notification displayed when application in foreground in iOS 10

Introduction: 

The new framework called “UserNotifications” is introduced with iOS 10 SDK. The UserNotifications framework (UserNotifications.framework) supports the delivery and handling of local and remote notifications when application is in foreground

Steps for implement code to handle push notifications in iOS 10

Import UserNotifications.framework in your AppDelegate file :                                                                              import UserNotifications  and Also add UNUserNotificationCenterDelegate.

Register for Notification :

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
registerForRemoteNotification()
return true
}
func registerForRemoteNotification() {
if #available(iOS 10.0, *) {
let center  = UNUserNotificationCenter.current()
center.delegate = self
center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in
if error == nil{
UIApplication.shared.registerForRemoteNotifications()
}
}
}
else {
UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.sound, .alert, .badge], categories: nil))
UIApplication.shared.registerForRemoteNotifications()

}

}

 Handling delegate methods for UserNotifications :
//MARK: UNUserNotificationCenter Delegate  >= iOS 10
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter willPresent notification: UNNotification, withCompletionHandler   completionHandler: @escaping (_ UNNotificationPresentationOptions) -> Void) {

       //Called when a notification is delivered to a foreground app.

        let userInfo = notification.request.content.userInfo as? NSDictionary

         completionHandler([.alert, .badge, .sound])

        print(\(userInfo)”)

       }

  @available(iOS 10.0, *)

    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

        // Called to let your app know which action was selected by the user for a given notification.

        let userInfo = response.notification.request.content.userInfo as? NSDictionary
print(“\(userInfo)”)
}

      Add Push Notifications Entitlements :  Go to your project target’s Capabilities tab and add Push Notifications Entitlements. If it’s available in your     certificates then it will enable directly else configure your profile with the certificates and you can enable this capability by that.

For Detail refer the this link :
http://ashishkakkad.com/2016/09/push-notifications-in-ios-10-swift/

Animation like floating Buttons.

Hi all, today we will check out simple but cool floating buttons using UIViewAnimations methods. So, in this we are going to show 4 buttons which came out upside from another button. Here we are using constraints of  buttons, button and UIViewAnimations. Let’s start with  adding constraint to each buttons.
1) Setting constraints for buttons:-    

Add constraint such that bottom constraint of 2nd button to 1st bottom similarly do for 3rd to 4th and 4th to 5th button. I am doing this because when i am going to update value for constraint is same and due to that i can manage spacing between them.
I have set my button’s size to 45*45 and other constraints to ZERO. After setting constraint you should see only single button which overlaps other buttons.  And I need IBActions of  all 4 buttons. 

2) Adding Animations to IBAction methods:-    

Add Following line code in your application

if !flag{
  UIView.animate(withDuration: 0.20, animations: {
     self.btn1bottomCons.constant = 55
}, completion: { (isTrue) in
  if isTrue{
     UIView.animate(withDuration: 0.15, animations: {
     self.btn2bottomCons.constant = 55
}, completion: { (isTrue) in
        if isTrue{
UIView.animate(withDuration: 0.10, animations: {
            self.btn3bottomCons.constant = 55
})
}
})
}
})
}else{
UIView.animate(withDuration: 0.5, animations: {
     self.view.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
})
  btn1bottomCons.constant = 0
  btn2bottomCons.constant = 0
  btn3bottomCons.constant = 0
UIView.animate(withDuration: 0.10, animations: {
})
}
flag = !flag

Here flag is Bool value used to toggle the buttons. btn1bottomCons, btn2bottomCons, btn3bottomCons and btn4bottomCons are the constraint which we have created initially. When flag is false set constraint value to 55 otherwise set 0. Please observer that i have set value in the completion block of other button and duration of animation 0.20, 0.15, 0.10. So that at end animation must be fast.
If you like to create your own custom completion handle here is one example given below,….


func yourFunctionName(isFlag:Bool,str:String,isCompleted:(_ success: String)-> Void){
for _ in 01000 {
//make delay
}
var str2 = “Hi “
str2 += “Shashi!, Yours String is—> “
str2 += str
isCompleted(str2)// Pass your result to completion block at the end😎
}

Now call the function as below,

yourFunctionName(isFlag: true, str: “😜“) { (str_temp) in
print(“—-===>***”,str_temp,”***<===—-“)
}

 

3) Run the App:-    

Run the code and click the button and observe there and say “there is no animation happening here😡” .

To solve this issue you need to update layout which is single line of code more powerful because I observer that due to that viewDidload() call again😵 yes.

So you need to add the following line of code

self.view.layoutIfNeeded()

So final code will be,——>        

        if !flag{

            UIView.animate(withDuration: 0.20, animations: {

                self.btn1bottomCons.constant = 55

                self.view.layoutIfNeeded()

            }, completion: { (isTrue) in

                if isTrue{

                    UIView.animate(withDuration: 0.15, animations: {

                        self.btn2bottomCons.constant = 55

                        self.view.layoutIfNeeded()

                    }, completion: { (isTrue) in

                        if isTrue{

                            UIView.animate(withDuration: 0.10, animations: {

                                self.btn3bottomCons.constant = 55

                                self.view.layoutIfNeeded()

                            })

                        }

                    })

                }

            })

        }else{

            UIView.animate(withDuration: 0.5, animations: {

                self.view.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)

            })

            btn1bottomCons.constant = 0

            btn2bottomCons.constant = 0

            btn3bottomCons.constant = 0

            UIView.animate(withDuration: 0.10, animations: {

                self.view.layoutIfNeeded()

            })

        }

        flag = !flag

 

And my original project is on this Link:—–>https://github.com/ShashikantBhadke/ADMobs

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 … 🙂

 

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… 🙂

 

  • 1
  • 2

Need more help?

Hi there, was your problem or query resolved? If not & need more assistance, please do reach out to us at info@nanostuffs.com, we'll be more than delighted to help. Nanostuffs has 7+ years of extensive Salesforce & iOS/Android experience.
Holler Box