Advanced usage of UIAlertController and pickers based on it: Telegram, Contacts, Location, PhotoLibrary, Country, Phone Code, Currency, Date...

Overview

Swift 4.0 Platform: iOS XCode 9+ iOS 11 Licence MIT

Alerts & Pickers

Advanced usage of native UIAlertController with TextField, TextView, DatePicker, PickerView, TableView, CollectionView and MapView.

Features

  • Custom pickers based on UITextField, UITextView, UIDatePicker, UIPickerView, UITableView, UICollectionView and MKMapView.
  • Example using a Storyboard.
  • Easy contentViewController placement.
  • Attributed title label and message label.
  • Button customization: image and title color.
  • Understandable action button placement.
  • Easy presentation.
  • Pure Swift 4.

Usage

  • New Alert
let alert = UIAlertController(style: .alert, title: "Title", message: "Message")
// or
let alert = UIAlertController(style: .alert)
  • Set and styling title
alert.set(title: "Title", font: .systemFont(ofSize: 20), color: .black)
// or
alert.setTitle(font: .systemFont(ofSize: 20), color: .black)
  • Set and styling message
alert.set(message: "Message", font: .systemFont(ofSize: 16), color: .black)
// or
alert.setMessage(font: .systemFont(ofSize: 16), color: .black)
  • Add button with image
alert.addAction(image: image, title: "Title", color: .black, style: .default) { action in
    // completion handler
}
  • Show Alert
// show alert
alert.show()

// or show alert with options
alert.show(animated: true, vibrate: true) {
    // completion handler
}

Set Content ViewController

When setting your own custom UIViewController into UIAlertController keep in mind to set prefferedContentSize.height of the controller otherwise it will no effect. You can not set prefferedContentSize.width.

let alert = UIAlertController(style: .alert, title: "Title")
let vc = CustomViewController()
vc.preferredContentSize.height = height
alert.setValue(vc, forKey: "contentViewController")
alert.show()

// or
let alert = UIAlertController(style: .alert, title: "Title")
let vc = CustomViewController()
alert.set(vc: vc, height: height)
alert.show()

Pickers

For UX better to use .actionSheet style in UIAlertController when set picker into contentViewController. If you like you can use .alert style as well, buy .actionSheet style is wider and User can see more as well as action button is placing at bottom that also more convenience for User to touch it.

UITextField In native UIAlertController you can only add UITextField to .alert style with default style and you can not change such properties as .borderColor, .borderWidth, .frame.size and so on. But if you make your own UIViewController with UITextField, it will solve all these problems.

One TextField Picker

You can use both styles .alert and .actionSheet of UIAlertController.

let alert = UIAlertController(style: self.alertStyle, title: "TextField")                  
let config: TextField.Config = { textField in
    textField.becomeFirstResponder()
    textField.textColor = .black
    textField.placeholder = "Type something"
    textField.left(image: image, color: .black)
    textField.leftViewPadding = 12
    textField.borderWidth = 1
    textField.cornerRadius = 8
    textField.borderColor = UIColor.lightGray.withAlphaComponent(0.5)
    textField.backgroundColor = nil
    textField.keyboardAppearance = .default
    textField.keyboardType = .default
    textField.isSecureTextEntry = true
    textField.returnKeyType = .done
    textField.action { textField in
        // validation and so on
    }
}              
alert.addOneTextField(configuration: config)
alert.addAction(title: "OK", style: .cancel)
alert.show()

Two TextFields Picker

You can use both styles .alert and .actionSheet of UIAlertController.

let alert = UIAlertController(style: .alert, title: "Login")

let configOne: TextField.Config = { textField in
    textField.left(image: user), color: .black)
    textField.leftViewPadding = 16
    textField.leftTextPadding = 12
    textField.becomeFirstResponder()
    textField.backgroundColor = nil
    textField.textColor = .black
    textField.placeholder = "Name"
    textField.clearButtonMode = .whileEditing
    textField.keyboardAppearance = .default
    textField.keyboardType = .default
    textField.returnKeyType = .done
    textField.action { textField in
        // action with input
    }
}

let configTwo: TextField.Config = { textField in
    textField.textColor = .black
    textField.placeholder = "Password"
    textField.left(image: lock, color: .black)
    textField.leftViewPadding = 16
    textField.leftTextPadding = 12
    textField.borderWidth = 1
    textField.borderColor = UIColor.lightGray.withAlphaComponent(0.5)
    textField.backgroundColor = nil
    textField.clearsOnBeginEditing = true
    textField.keyboardAppearance = .default
    textField.keyboardType = .default
    textField.isSecureTextEntry = true
    textField.returnKeyType = .done
    textField.action { textField in
        // action with input
    }
}
// vInset - is top and bottom margin of two textFields   
alert.addTwoTextFields(vInset: 12, textFieldOne: configOne, textFieldTwo: configTwo)
alert.addAction(title: "OK", style: .cancel)
alert.show()

DatePicker

UIDatePicker does not look very much in .alert style.

let alert = UIAlertController(style: .actionSheet, title: "Select date")
alert.addDatePicker(mode: .dateAndTime, date: date, minimumDate: minDate, maximumDate: maxDate) { date in
    // action with selected date
}
alert.addAction(title: "OK", style: .cancel)
alert.show()

PickerView

Example how to use UIPickerView as contentViewController and change height of the UIAlertController.

let alert = UIAlertController(style: .actionSheet, title: "Picker View", message: "Preferred Content Height")

let frameSizes: [CGFloat] = (150...400).map { CGFloat($0) }
let pickerViewValues: [[String]] = [frameSizes.map { Int($0).description }]
let pickerViewSelectedValue: PickerViewViewController.Index = (column: 0, row: frameSizes.index(of: 216) ?? 0)

alert.addPickerView(values: pickerViewValues, initialSelection: pickerViewSelectedValue) { vc, picker, index, values in
    DispatchQueue.main.async {
        UIView.animate(withDuration: 1) {
            vc.preferredContentSize.height = frameSizes[index.row]
        }
    }
}
alert.addAction(title: "Done", style: .cancel)
alert.show()

Locale Pickers

  • Country Picker

let alert = UIAlertController(style: .actionSheet, message: "Select Country")
alert.addLocalePicker(type: .country) { info in
    // action with selected object
}
alert.addAction(title: "OK", style: .cancel)
alert.show()
  • Phone Code Picker

let alert = UIAlertController(style: .actionSheet, title: "Phone Codes")
alert.addLocalePicker(type: .phoneCode) { info in
    // action with selected object
}
alert.addAction(title: "OK", style: .cancel)
alert.show()
  • Currency Picker

let alert = UIAlertController(style: .actionSheet, title: "Currencies")
alert.addLocalePicker(type: .currency) { info in
    alert.title = info?.currencyCode
    alert.message = "is selected"
    // action with selected object
}
alert.addAction(title: "OK", style: .cancel)
alert.show()

Image Picker

  • Horizontal Image Picker with paging and single selection:
let alert = UIAlertController(style: .actionSheet)
let photos: [UIImage] = images
alert.addImagePicker(
    flow: .horizontal,
    paging: true,
    images: photos,
    selection: .single(action: { [unowned self] image in
        // action with selected image
    }))
alert.addAction(title: "OK", style: .cancel)
alert.show()
  • Vertical Image Picker w/o paging and with multiple selection:
let alert = UIAlertController(style: .actionSheet)
let photos: [UIImage] = images
alert.addImagePicker(
    flow: .vertical,
    paging: false,
    height: UIScreen.main.bounds.height,
    images: photos,
    selection: .multiple(action: { [unowned self] images in
        // action with selected images
    }))
alert.addAction(title: "OK", style: .cancel)
alert.show()

PhotoLibrary Picker

let alert = UIAlertController(style: .actionSheet)
alert.addPhotoLibraryPicker(
    flow: .horizontal,
    paging: true,
    selection: .single(action: { image in
        // action with selected image
    }))
alert.addAction(title: "Cancel", style: .cancel)
alert.show()

ColorPicker

Example how to use UIViewController instantiated from Storyboard with Autolayout as contentViewController in the UIAlertController.

let alert = UIAlertController(style: .actionSheet)
alert.addColorPicker(color: color) { color in
    // action with selected color
}
alert.addAction(title: "Done", style: .cancel)
alert.show()

Contacts Picker

let alert = UIAlertController(style: .actionSheet)
alert.addContactsPicker { contact in
    // action with contact
}
alert.addAction(title: "Cancel", style: .cancel)
alert.show()

Location Picker

let alert = UIAlertController(style: .actionSheet)
alert.addLocationPicker { location in
    // action with location
}
alert.addAction(title: "Cancel", style: .cancel)
alert.show()

Telegram Picker

let alert = UIAlertController(style: .actionSheet)
alert.addTelegramPicker { result in
    switch result {
      case .photo(let assets):
        // action with assets
      case .contact(let contact):
        // action with contact
      case .location(let location):
        // action with location
    }
}
alert.addAction(title: "Cancel", style: .cancel)
alert.show()

TextViewer

let alert = UIAlertController(style: .actionSheet)
alert.addTextViewer(text: .attributedText(text))
alert.addAction(title: "OK", style: .cancel)
alert.show()

Alerts vs. Action Sheets

There are some things to keep in mind when using .actionSheet and .alert styles:

  • Pickers better to use in .actionSheet style.
  • UITextField can be used in both styles.

Installing

Manually

Download and drop /Source folder in your project.

Requirements

  • Swift 4
  • iOS 11 or higher

Authors

Communication

  • If you found a bug, open an issue.
  • If you have a feature request, open an issue.
  • If you want to contribute, submit a pull request.

License

This project is licensed under the MIT License.

Comments
  • Silly picker logic

    Silly picker logic

    Picker returns a lot of params on each click/scroll action - even when it is not necessary. And in the same time it returns NOTHING on custom actions! What if an user selects something and presses "Done" button and only thenI want to get the data? For example - when picking of the value should cause network requests. According to your silly logic I must cache the data user selects on each scroll action and get them at the end. Of course you could provide values, index and etc properties/methods but you declared them private

    fixed 
    opened by Gargo 8
  • Cocoapods spec

    Cocoapods spec

    If you are ok with the cocoapods file you can just pusblish on cocoapods spec repos but before you do so, create a tag 1.0 of the repo

    pod trunk push NAME.podspec

    opened by loicgriffie 7
  • Error: init(coder:) has not been implemented

    Error: init(coder:) has not been implemented"

    App works fine when this is in app delegate: window?.rootViewController = UINavigationController(rootViewController: ViewController())

    When it's not and I try to present it, I get these errors:

    1. Fatal error: init(coder:) has not been implemented

    2. Warning: Attempt to present <UIAlertController: 0x108839200> on <MainVC: 0x105055e00> whose view is not in the window hierarchy!

    opened by kentonraiford 4
  • Storyboard?

    Storyboard?

    This is a superb control! Perhaps you could add an example using a Storyboard? I have a large project, where Alerts-Pickers would need to be incorporated.

    todo 
    opened by daviddelmonte 3
  • 👨🏻‍💻 👏 Fixed up contact picker for Xcode 10

    👨🏻‍💻 👏 Fixed up contact picker for Xcode 10

    Summary:

    • String extension would crash on empty contact name
      • [✅]subscript will take min(length | upperBound)
    • UIGraphicsGetCurrentContext would fail to get current context for CGZise.zero
      • [✅] Give it a size

    ezgif-4-e000ab6e6cf6 edit: updated screenshot

    opened by theyongdai 2
  • Issue with VerticalScrollFlowLayout

    Issue with VerticalScrollFlowLayout

    Hi, I am using 'VegaScrollFlowLayout' class to add animation to collectionView items. This works like a charm if I use a fixed itemSize for CollectionView cell with no section header. But If I use any (section header or dynamic itemSize). The CollectionView displayed item with some weird way. I face these 2 issues while using this class:

    1. When adding section header, and use default FlowLayout. Everything works well. When using 'VerticalScrollFlowLayout', Section Header doesn't display anymore.

    2. If use 'estimatedItemSize' instead of 'itemSize' for dynamic item size. The animation doesn't work properly. Let me know If you can help me on this. Thanks

    opened by surjeet-singh 2
  • Reasons for minimum target iOS 11?

    Reasons for minimum target iOS 11?

    Hello, Thanks for this Marvelous library.

    Can you tell the reason, why we require to set minimum target to iOS 11?

    And, the Alert/ActionSheet are default one? with modified?

    opened by Rashesh-Bosamiya 2
  • AlertController with textfield not showing

    AlertController with textfield not showing

    Hi,

    Thank you for making this beautiful library available for developpers. Actually I am trying to use the One TextField Picker, but the alert is not showing and I am getting this error: Attempt to present <UIAlertController: 0x7fa2b21d2400> on <Project.SplashViewController: 0x7fa2b140c560> whose view is not in the window hierarchy!

    When I add self.present(alert, animated: true, completion: nil) before alert.show() to solve the problem I am getting another exception: Application tried to present modally an active controller

    Did I miss something? Can you help me please

    Thank you.

    opened by najoua 1
  • vInset - is top and bottom margin of two textFields ?

    vInset - is top and bottom margin of two textFields ?

    Hi, thanks for this awesome helper!

    But how to remove bottom & top borders on textfields on login view?!

    I found that comments on title but I cound't figure it out !

    opened by HappyIosDeveloper 1
  • Crash in ipad

    Crash in ipad

    *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Your application has presented a UIAlertController (<UIAlertController: 0x105020200>) of style UIAlertControllerStyleActionSheet from UINavigationController (<UINavigationController: 0x104801000>). The modalPresentationStyle of a UIAlertController with this style is UIModalPresentationPopover. You must provide location information for this popover through the alert controller's popoverPresentationController. You must provide either a sourceView and sourceRect or a barButtonItem. If this information is not known when you present the alert controller, you may provide it in the UIPopoverPresentationControllerDelegate method -prepareForPopoverPresentation.'

    opened by icefox57 0
  • is it available in iPad ?

    is it available in iPad ?

    i got this error

    2018-08-07 15:13:45.663030+0700 playsound[20334:1138125] Error loading /Library/Audio/Plug-Ins/HAL/Digidesign CoreAudio.plugin/Contents/MacOS/Digidesign CoreAudio:  dlopen(/Library/Audio/Plug-Ins/HAL/Digidesign CoreAudio.plugin/Contents/MacOS/Digidesign CoreAudio, 262): no suitable image found.  Did find:
    	/Library/Audio/Plug-Ins/HAL/Digidesign CoreAudio.plugin/Contents/MacOS/Digidesign CoreAudio: mach-o, but not built for iOS simulator
    2018-08-07 15:13:45.663232+0700 playsound[20334:1138125] Cannot find function pointer NewDigiCoreAudioPlugIn for factory <CFUUID 0x600000239c00> B8A063B5-2F3D-444A-88CB-D0B8F1B22042 in CFBundle/CFPlugIn 0x7fd33ff071e0 </Library/Audio/Plug-Ins/HAL/Digidesign CoreAudio.plugin> (bundle, not loaded)
    2018-08-07 15:13:46.157918+0700 playsound[20334:1138125] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Your application has presented a UIAlertController (<UIAlertController: 0x7fd34400b200>) of style UIAlertControllerStyleActionSheet. The modalPresentationStyle of a UIAlertController with this style is UIModalPresentationPopover. You must provide location information for this popover through the alert controller's popoverPresentationController. You must provide either a sourceView and sourceRect or a barButtonItem.  If this information is not known when you present the alert controller, you may provide it in the UIPopoverPresentationControllerDelegate method -prepareForPopoverPresentation.'
    *** First throw call stack:
    (
    	0   CoreFoundation                      0x0000000106f731e6 __exceptionPreprocess + 294
    	1   libobjc.A.dylib                     0x0000000102db8031 objc_exception_throw + 48
    	2   UIKit                               0x0000000104779043 -[UIPopoverPresentationController presentationTransitionWillBegin] + 3168
    	3   UIKit                               0x0000000103c0c4f4 __71-[UIPresentationController _initViewHierarchyForPresentationSuperview:]_block_invoke + 2537
    	4   UIKit                               0x0000000103c09c69 __56-[UIPresentationController runTransitionForCurrentState]_block_invoke + 436
    	5   UIKit                               0x0000000103aa04b3 _runAfterCACommitDeferredBlocks + 318
    	6   UIKit                               0x0000000103a8f71e _cleanUpAfterCAFlushAndRunDeferredBlocks + 388
    	7   UIKit                               0x0000000103abdea5 _afterCACommitHandler + 137
    	8   CoreFoundation                      0x0000000106f15607 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
    	9   CoreFoundation                      0x0000000106f1555e __CFRunLoopDoObservers + 430
    	10  CoreFoundation                      0x0000000106ef9b81 __CFRunLoopRun + 1537
    	11  CoreFoundation                      0x0000000106ef930b CFRunLoopRunSpecific + 635
    	12  GraphicsServices                    0x000000010c07aa73 GSEventRunModal + 62
    	13  UIKit                               0x0000000103a95057 UIApplicationMain + 159
    	14  playsound                           0x00000001020680d7 main + 55
    	15  libdyld.dylib                       0x0000000109ad1955 start + 1
    	16  ???                                 0x0000000000000001 0x0 + 1
    )
    libc++abi.dylib: terminating with uncaught exception of type NSException
    (lldb) 
    
    
    

    my code in swift

    //
    //  Chapter1_25.swift
    //  playsound
    //
    //  Created by student on 8/7/18.
    //  Copyright © 2018 harvestidea. All rights reserved.
    //
    
    import UIKit
    import AVFoundation
    import RLBAlertsPickers
    
    class Chapter1_25: UIViewController, AVAudioPlayerDelegate {
    
        var conversationSound: AVAudioPlayer = AVAudioPlayer()
        var currentColor = UIColor.black
        
        var color = UIColor.black
        
        func audioPlay() {
            
            let path = Bundle.main.path(forResource: "p4highnote.mp3", ofType: nil)!
            let url = URL(fileURLWithPath: path)
            do {
                conversationSound = try AVAudioPlayer(contentsOf: url)
                conversationSound.delegate = self
                conversationSound.play()
            } catch {
                print(error)
            }
            
        }
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            audioPlay()
            
            let alert = UIAlertController(style: .actionSheet, message: "Select Country")
            alert.addLocalePicker(type: .country) { info in
                // action with selected object
            }
            alert.addAction(title: "OK", style: .cancel)
            alert.show()
            
        }
    }
    
    
    opened by nattaaek 0
  • A custom searchable list?

    A custom searchable list?

    Hello,

    You have a great library here, however I was wondering if it would be possible to have a string array that can be searched like the country or phone number views, can I create a view with my own custom list that is searchable?

    opened by hamzabinamin 0
  • Support for L10n

    Support for L10n

    I needed to change de default locale to spanish in a DatePicker and I found no way to do this using alert.addDatePicker. I thought changing the device language it will work, but at least in simulator it didn't work. I didn't install the library with Cocoapods, so I added a modification to DatePickerViewController init

    `required public init(mode: UIDatePicker.Mode, date: Date? = nil, minimumDate: Date? = nil, maximumDate: Date? = nil, action: Action?) { super.init(nibName: nil, bundle: nil) datePicker.datePickerMode = mode

        //changing to spanish only for date selection
       //so September 13, 2021 becomes 13 Septiembre 2021 
        if mode == .date{
            datePicker.locale = Locale(identifier: "es_ES")
        }
        
        datePicker.date = date ?? Date()
        datePicker.minimumDate = minimumDate
        datePicker.maximumDate = maximumDate
        self.action = action
    }`
    

    It would be nice if there were an option to set the locale of the picker

    opened by geclick 0
  • Install pod not working

    Install pod not working

    I tried to install pod by terminal but it required username and password about github and after I put them i recived this error. [!] Error installing RLBAlertsPickers [!] /usr/bin/git clone https://github.com/loicgriffie/Alerts-Pickers.git /var/folders/y4/xr3pb5h914l8h8q7qnhmwkp00000gn/T/d20210331-85365-1roomk8 --template= --single-branch --depth 1 --branch 1.1.2

    Cloning into '/var/folders/y4/xr3pb5h914l8h8q7qnhmwkp00000gn/T/d20210331-85365-1roomk8'... remote: Repository not found. fatal: repository 'https://github.com/loicgriffie/Alerts-Pickers.git/' not found

    HELP ME!!!

    opened by leinadav 1
Owner
RV
UI/UX Designer & Swift Developer skype: roman_v.
RV
This is an iOS control for selecting a date using UIDatePicker in an UIAlertController like manner

RMDateSelectionViewController This framework allows you to select a date by presenting an action sheet. In addition, it allows you to add actions arro

Roland Moers 1.2k Dec 13, 2022
Swift library to manage in app notification in swift language, like WhatsApp, Telegram, Frind, ecc.

InAppNotify - Manage in App notifications During develop of my app Frind, I needed to manage in app notifications like whatsapp or telegram, but i did

Luca Becchetti 438 Nov 20, 2022
💬 A tiny extension for UIAlertController that makes working with it very simple. Only 150 lines of code.

AlertController ?? A tiny extension for UIAlertController that makes working with it very simple. Only 150 lines of code. Alert let alert = UIAlertCon

Mezhevikin Alexey 9 Nov 2, 2022
PMAlertController is a great and customizable alert that can substitute UIAlertController

PMAlertController is a small library that allows you to substitute Apple's uncustomizable UIAlertController, with a beautiful and totally customizable

Paolo Musolino 2.5k Jan 3, 2023
PMAlertController is a great and customizable alert that can substitute UIAlertController

PMAlertController is a small library that allows you to substitute Apple's uncustomizable UIAlertController, with a beautiful and totally customizable

Paolo Musolino 2.5k Jan 3, 2023
Simple and elegant way to handle UIAlertController.

SwiftyAlert SwiftAlert is simple and elegant way to handle UIAlertController. Feature Handle action with async/await Method chain Support UITextField

Jaesung Jung 2 Oct 30, 2022
Swifty, modern UIAlertController wrapper.

Alertift Alertift.alert(title: "Alertift", message: "Alertift is swifty, modern, and awesome UIAlertController wrapper.") .action(.default("❤️"))

Suguru Kishimoto 287 Jan 7, 2023
An easier constructor for UIAlertController. Present an alert from anywhere.

ALRT An easier constructor for UIAlertController. Present an alert from anywhere like this. ALRT.create(.alert, title: "Alert?").addOK().addCancel().s

Masahiro Watanabe 97 Nov 11, 2022
Easy Swift UIAlertController

EZAlertController Easy Swift UIAlertController One line setup for all UIAlertControllers Button action with closures instead of selectors Easily custo

Kan Yilmaz 366 Sep 14, 2022
Simple UIAlertController builder class in Swift.

Kamagari Simple UIAlertController builder class in Swift. Features AlertBuilder class to simply build UIAlertController by using method chaining UIAle

Kazunobu Tasaka 78 Nov 29, 2022
A simple, customizable popup dialog for iOS written in Swift. Replaces UIAlertController alert style.

Introduction Popup Dialog is a simple, customizable popup dialog written in Swift. Features Easy to use API with hardly any boilerplate code Convenien

Orderella Ltd. 3.8k Dec 20, 2022
A customizable, full-feature, lightweight iOS framework to be used instead of UIAlertController.

A customizable, full-feature, lightweight iOS framework to be used instead of UIAlertController.

Ali Samaiee 11 Jun 6, 2022
This is an iOS control for presenting any UIView in an UIAlertController like manner

RMActionController This framework allows you to present just any view as an action sheet. In addition, it allows you to add actions around the present

Roland Moers 542 Dec 5, 2022
This is an iOS control for selecting something using UIPickerView in an UIAlertController like manner

RMPickerViewController This framework allows you to pick something with a picker presented as an action sheet. In addition, it allows you to add actio

Roland Moers 382 Dec 19, 2022
Simple Alert View written in Swift, which can be used as a UIAlertController. (AlertController/AlertView/ActionSheet)

DOAlertController Simple Alert View written in Swift, which can be used as a UIAlertController replacement. It supports from iOS7! It is simple and ea

Daiki Okumura 406 Sep 5, 2022
An easy to use UIAlertController builder for swift

LKAlertController An easy to use UIAlertController builder for swift Features Short and simple syntax for creating both Alerts and ActionSheets from U

Lightning Kite 97 Feb 8, 2022
Customizable replacement for UIAlertController

ActionSheet Customizable replacement for UIAlertController. Requirements Installation Swift Package Manager The Swift Package Manager is a tool for au

Horizontal Systems 0 Oct 6, 2022
UIAlertController with continuity.

CuckooAlert Allow multiple use of presentViewController to UIAlertController. You may be disappointed from this. Do you imagine that cuckoo spit out s

Jay Choi 5 Feb 2, 2020
Use UIAlertController like a boss.

Description Requirements Installation CocoaPods Carthage Usage License Description CatAlertController is a high level manager object that with chainin

Kcat 8 Feb 8, 2022