Monday, 12 February 2018

PickerView With Button in Swift



PickerView With Button in Swift



Create NSObject ( DPPickerManager) : - 



import UIKit

public typealias DPPickerCompletion = (_ cancel: Bool) -> Void
public typealias DPPickerDateCompletion = (_ date: Date?, _ cancel: Bool) -> Void
public typealias DPPickerValueIndexCompletion = (_ value: String?, _ index: Int, _ cancel: Bool) -> Void

open class DPPickerManager: NSObject, UIPickerViewDelegate, UIPickerViewDataSource {
    
    static let shared = DPPickerManager()

    private typealias PickerCompletionBlock  = (_ cancel: Bool) -> Void

    private var alertView: UIAlertController?
    private var pickerValues: [String]?
    private var pickerCompletion: PickerCompletionBlock?
    
    @objc open var timeZone: TimeZone? = TimeZone(identifier: "EN")
    
    // MARK: - Show
    
    @objc open func showPicker(title: String?, selected: Date?, completion:DPPickerDateCompletion?) {
        let currentDate = Date()
        let gregorian = NSCalendar(calendarIdentifier: .gregorian)
        var components = DateComponents()
        
        components.year = -110
        let minDate = gregorian?.date(byAdding: components, to: currentDate, options: NSCalendar.Options(rawValue: 0))
        self.showPicker(title: title, selected: selected, min: minDate, max: currentDate, completion: completion)
    }
    
    @objc open func showPicker(title: String?, selected: Date?, min: Date?, max: Date?, completion:DPPickerDateCompletion?) {
        self.showPicker(title: title, picker: { (picker) in
            picker.date = selected ?? Date()
            picker.minimumDate = min
            picker.maximumDate = max
            picker.timeZone = self.timeZone
            picker.datePickerMode = .date
        }, completion: completion)
    }
    
    @objc open func showPicker(title: String?, picker:((_ picker: UIDatePicker) -> Void)?, completion:DPPickerDateCompletion?) {
        let datePicker = UIDatePicker()
        datePicker.timeZone = self.timeZone
        
        picker?(datePicker)
        
        self.showPicker(title: title, view: datePicker) { (cancel) in
            completion?(datePicker.date, cancel)
        }
    }
    
    @objc open func showPicker(title: String?, selected: String?, strings:[String], completion:DPPickerValueIndexCompletion?) {
        self.pickerValues = strings
        
        let picker = UIPickerView()
        picker.delegate = self
        picker.dataSource = self
        if let value = selected {
            picker.reloadAllComponents()
            if strings.count > 0 {
                OperationQueue.current?.addOperation {
                    let index = strings.index(of: value) ?? 0
                    picker.selectRow(index, inComponent: 0, animated: false)
                }
            }
        }

        self.showPicker(title: title, view: picker) { (cancel) in
            
            var index = -1
            var value: String? = nil
            
            if !cancel, strings.count > 0 {
                index = picker.selectedRow(inComponent: 0)
                if index >= 0 {
                    value = self.pickerValues?[index]
                }
            }
            
            completion?(value, index, cancel || index < 0)
        }
    }
    
    @objc open func showPicker(title: String?, view: UIView, completion:DPPickerCompletion?) {
        
        var center: CGFloat?
        var buttonX: CGFloat = 0
        
        let image = UIImage(named: "cancel_image")?.withRenderingMode(.alwaysTemplate)
        
        // trick
        let alertView = UIAlertController(title: title, message: "\n\n\n\n\n\n\n\n\n\n", preferredStyle: .actionSheet);
        alertView.view.addSubview(view)
        alertView.popoverPresentationController?.sourceView = UIViewController.top?.view
        alertView.popoverPresentationController?.sourceRect = view.bounds
        alertView.view.tintColor = .gray
        self.alertView = alertView

        // device orientation
        switch UIApplication.shared.statusBarOrientation {
        case .landscapeLeft, .landscapeRight:
            center = UIViewController.top?.view.center.y
            buttonX = alertView.view.frame.size.height - (image!.size.height * 2)
        case .portrait, .portraitUpsideDown:
            center = UIViewController.top?.view.center.x
            buttonX = alertView.view.frame.size.width - (image!.size.width * 2)
        default: break
        }
        
        view.center.x = center ?? 0
        view.transform = .init(translationX: -10, y: title != nil ? 35 : 0)
        
        self.pickerCompletion = completion
        
        // close button
        let close = UIButton(frame: CGRect(x: buttonX - 10 , y: 10, width: image!.size.width, height: image!.size.height))
        close.tintColor = .gray
        close.setImage(image!, for: .normal)
        close.addTarget(self, action: #selector(pickerClose(_:)), for: .touchUpInside)
        alertView.view.addSubview(close)

        // ok button
        let ok = UIAlertAction(title: "Ok", style: .default) { (action) in
            completion?(false)
        }
        alertView.addAction(ok)
        
        UIViewController.top?.present(alertView, animated: true, completion: nil)
        
    }
    
    // MARK: - Picker Delegates
    
    public func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return pickerValues?.count == 0 ? 0 : 1
    }
    
    public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return pickerValues?.count ?? 0
    }
    
    public func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return pickerValues?[row]
    }
    
    @objc internal func pickerClose(_ sender: UIButton) {
        alertView?.dismiss(animated: true, completion: {
            self.pickerCompletion?(true)
        })
    }
    
}

internal extension UIViewController {

    static var top: UIViewController? {
        get {
            return topViewController()
        }
    }

    static var root: UIViewController? {
        get {
            return UIApplication.shared.delegate?.window??.rootViewController
        }
    }

    static func topViewController(from viewController: UIViewController? = UIViewController.root) -> UIViewController? {
        if let tabBarViewController = viewController as? UITabBarController {
            return topViewController(from: tabBarViewController.selectedViewController)
        } else if let navigationController = viewController as? UINavigationController {
            return topViewController(from: navigationController.visibleViewController)
        } else if let presentedViewController = viewController?.presentedViewController {
            return topViewController(from: presentedViewController)
        } else {
            return viewController
        }
    }
    
}




ViewController.swift : -



import UIKit

class ViewController: UIViewController {

    @IBAction func didStringsPicker() {
        
        let values = ["Value 1", "Value 2", "Value 3", "Value 4"]
        DPPickerManager.shared.showPicker(title: "Strings Picker", selected: "Value 1", strings: values) { (value, index, cancel) in
            if !cancel {
                // TODO: you code here
                debugPrint(value as Any)
            }
        }
        
    }
    
    @IBAction func didDatePicker() {
        let min = Date()
        let max = min.addingTimeInterval(31536000) // 1 year
        DPPickerManager.shared.showPicker(title: "Date Picker", selected: Date(), min: min, max: max) { (date, cancel) in
            if !cancel {
                // TODO: you code here
                debugPrint(date as Any)
            }
        }
    }
    
    @IBAction func didTimePicker() {
        DPPickerManager.shared.showPicker(title: "Time Picker", picker: { (picker) in
            picker.date = Date()
            picker.datePickerMode = .time
        }) { (date, cancel) in
            if !cancel {
                // TODO: you code here
                debugPrint(date as Any)
            }
        }
    }


}

No comments:

Post a Comment