{"id":2459,"url":"https://github.com/dillidon/alerts-and-pickers","last_synced_at":"2025-05-14T14:07:42.674Z","repository":{"id":37359695,"uuid":"117243061","full_name":"dillidon/alerts-and-pickers","owner":"dillidon","description":"Advanced usage of UIAlertController and pickers based on it: Telegram, Contacts, Location, PhotoLibrary, Country, Phone Code, Currency, Date...","archived":false,"fork":false,"pushed_at":"2024-02-18T14:40:25.000Z","size":41651,"stargazers_count":5751,"open_issues_count":90,"forks_count":712,"subscribers_count":103,"default_branch":"new","last_synced_at":"2025-04-11T18:21:48.888Z","etag":null,"topics":["alert","color-picker","contacts","country-picker","currency-picker","datepicker","image-picker","location","login","map","phonecode","picker","pickerview","signin","swift","telegram","telegram-picker","textfield","uialertcontroller","uitextfield"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dillidon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-01-12T13:16:07.000Z","updated_at":"2025-04-11T14:01:31.000Z","dependencies_parsed_at":"2024-11-28T08:30:58.384Z","dependency_job_id":null,"html_url":"https://github.com/dillidon/alerts-and-pickers","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dillidon%2Falerts-and-pickers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dillidon%2Falerts-and-pickers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dillidon%2Falerts-and-pickers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dillidon%2Falerts-and-pickers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dillidon","download_url":"https://codeload.github.com/dillidon/alerts-and-pickers/tar.gz/refs/heads/new","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254159194,"owners_count":22024558,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["alert","color-picker","contacts","country-picker","currency-picker","datepicker","image-picker","location","login","map","phonecode","picker","pickerview","signin","swift","telegram","telegram-picker","textfield","uialertcontroller","uitextfield"],"created_at":"2024-01-05T20:16:14.264Z","updated_at":"2025-05-14T14:07:37.663Z","avatar_url":"https://github.com/dillidon.png","language":"Swift","funding_links":[],"categories":["UI","Libs","Swift","UI [🔝](#readme)","OOM-Leaks-Crash","Content"],"sub_categories":["Alert \u0026 Action Sheet","UI","Other free courses","Picker","Action Sheet"],"readme":"\u003cdiv align = \"center\"\u003e\n\u003cimg src=\"Assets/Logo.png\" width=\"700\" /\u003e\n\u003c/div\u003e\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://img.shields.io/badge/Swift-4.0-orange.svg\" alt=\"Swift 4.0\"/\u003e\n\u003cimg src=\"https://img.shields.io/badge/platform-iOS-brightgreen.svg\" alt=\"Platform: iOS\"/\u003e\n\u003cimg src=\"https://img.shields.io/badge/Xcode-9%2B-brightgreen.svg\" alt=\"XCode 9+\"/\u003e\n\u003cimg src=\"https://img.shields.io/badge/iOS-11%2B-brightgreen.svg\" alt=\"iOS 11\"/\u003e\n\u003cimg src=\"https://img.shields.io/badge/licence-MIT-lightgray.svg\" alt=\"Licence MIT\"/\u003e\n\u003c/a\u003e\n\u003c/p\u003e\n\n# Alerts \u0026 Pickers\n\nAdvanced usage of native UIAlertController with TextField, TextView, DatePicker, PickerView, TableView, CollectionView and MapView.\n\n\n\n### Features\n- [x] Custom pickers based on UITextField, UITextView, UIDatePicker, UIPickerView, UITableView, UICollectionView and MKMapView.\n- [x] Example using a Storyboard.\n- [x] Easy contentViewController placement.\n- [x] Attributed title label and message label.\n- [x] Button customization: image and title color.\n- [x] Understandable action button placement.\n- [x] Easy presentation.\n- [x] Pure Swift 4.\n\n\u003cdiv align = \"center\"\u003e\n\u003cimg src=\"Assets/gifs/actionSheet-.gif\" width=\"400\" /\u003e\n\u003cimg src=\"Assets/gifs/alert-.gif\" width=\"400\" /\u003e\n\u003c/div\u003e\n\n## Usage\n\n\u003cdiv align = \"center\"\u003e\n\u003cimg src=\"Assets/gifs/actionSheet-simple.gif\" width=\"350\" /\u003e\n\u003cimg src=\"Assets/gifs/alert-simple.gif\" width=\"350\" /\u003e\n\u003c/div\u003e\n\n- New Alert\n\n```swift\nlet alert = UIAlertController(style: .alert, title: \"Title\", message: \"Message\")\n// or\nlet alert = UIAlertController(style: .alert)\n```\n\n- Set and styling title\n\n```swift\nalert.set(title: \"Title\", font: .systemFont(ofSize: 20), color: .black)\n// or\nalert.setTitle(font: .systemFont(ofSize: 20), color: .black)\n```\n\n- Set and styling message\n\n```swift\nalert.set(message: \"Message\", font: .systemFont(ofSize: 16), color: .black)\n// or\nalert.setMessage(font: .systemFont(ofSize: 16), color: .black)\n```\n- Add button with image\n\n```swift\nalert.addAction(image: image, title: \"Title\", color: .black, style: .default) { action in\n    // completion handler\n}\n```\n\n* Show Alert\n\n```swift\n// show alert\nalert.show()\n\n// or show alert with options\nalert.show(animated: true, vibrate: true) {\n    // completion handler\n}\n```\n\u003cdiv align = \"center\"\u003e\n\u003cimg src=\"Assets/gifs/actionSheet-simple-image.gif\" width=\"350\" /\u003e\n\u003cimg src=\"Assets/gifs/alert-simple-image.gif\" width=\"350\" /\u003e\n\u003c/div\u003e\n\n\n## Set Content ViewController\n\nWhen 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`.\n\n```swift\nlet alert = UIAlertController(style: .alert, title: \"Title\")\nlet vc = CustomViewController()\nvc.preferredContentSize.height = height\nalert.setValue(vc, forKey: \"contentViewController\")\nalert.show()\n\n// or\nlet alert = UIAlertController(style: .alert, title: \"Title\")\nlet vc = CustomViewController()\nalert.set(vc: vc, height: height)\nalert.show()\n```\n\n## Pickers\nFor 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.\n\n**UITextField**\nIn 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.\n\n## One TextField Picker\n\nYou can use both styles `.alert` and `.actionSheet` of `UIAlertController`.\n\n\u003cdiv align = \"center\"\u003e\n\u003cimg src=\"Assets/gifs/actionSheet-textField-1.gif\" width=\"350\" /\u003e\n\u003cimg src=\"Assets/gifs/alert-textField-1.gif\" width=\"350\" /\u003e\n\u003c/div\u003e\n\n```swift\nlet alert = UIAlertController(style: self.alertStyle, title: \"TextField\")                  \nlet config: TextField.Config = { textField in\n    textField.becomeFirstResponder()\n    textField.textColor = .black\n    textField.placeholder = \"Type something\"\n    textField.left(image: image, color: .black)\n    textField.leftViewPadding = 12\n    textField.borderWidth = 1\n    textField.cornerRadius = 8\n    textField.borderColor = UIColor.lightGray.withAlphaComponent(0.5)\n    textField.backgroundColor = nil\n    textField.keyboardAppearance = .default\n    textField.keyboardType = .default\n    textField.isSecureTextEntry = true\n    textField.returnKeyType = .done\n    textField.action { textField in\n        // validation and so on\n    }\n}              \nalert.addOneTextField(configuration: config)\nalert.addAction(title: \"OK\", style: .cancel)\nalert.show()\n```\n\n## Two TextFields Picker\n\nYou can use both styles `.alert` and `.actionSheet` of `UIAlertController`.\n\n\u003cdiv align = \"center\"\u003e\n\u003cimg src=\"Assets/gifs/actionSheet-textField-2.gif\" width=\"350\" /\u003e\n\u003cimg src=\"Assets/gifs/alert-textField-2.gif\" width=\"350\" /\u003e\n\u003c/div\u003e\n\n```swift\nlet alert = UIAlertController(style: .alert, title: \"Login\")\n\nlet configOne: TextField.Config = { textField in\n    textField.left(image: user), color: .black)\n    textField.leftViewPadding = 16\n    textField.leftTextPadding = 12\n    textField.becomeFirstResponder()\n    textField.backgroundColor = nil\n    textField.textColor = .black\n    textField.placeholder = \"Name\"\n    textField.clearButtonMode = .whileEditing\n    textField.keyboardAppearance = .default\n    textField.keyboardType = .default\n    textField.returnKeyType = .done\n    textField.action { textField in\n        // action with input\n    }\n}\n\nlet configTwo: TextField.Config = { textField in\n    textField.textColor = .black\n    textField.placeholder = \"Password\"\n    textField.left(image: lock, color: .black)\n    textField.leftViewPadding = 16\n    textField.leftTextPadding = 12\n    textField.borderWidth = 1\n    textField.borderColor = UIColor.lightGray.withAlphaComponent(0.5)\n    textField.backgroundColor = nil\n    textField.clearsOnBeginEditing = true\n    textField.keyboardAppearance = .default\n    textField.keyboardType = .default\n    textField.isSecureTextEntry = true\n    textField.returnKeyType = .done\n    textField.action { textField in\n        // action with input\n    }\n}\n// vInset - is top and bottom margin of two textFields   \nalert.addTwoTextFields(vInset: 12, textFieldOne: configOne, textFieldTwo: configTwo)\nalert.addAction(title: \"OK\", style: .cancel)\nalert.show()\n```\n\n## DatePicker\n\n`UIDatePicker` does not look very much in `.alert` style.\n\n\u003cdiv align = \"center\"\u003e\n\u003cimg src=\"Assets/gifs/actionSheet-datePicker.gif\" width=\"350\" /\u003e\n\u003cimg src=\"Assets/gifs/alert-datePicker.gif\" width=\"350\" /\u003e\n\u003c/div\u003e\n\n```swift\nlet alert = UIAlertController(style: .actionSheet, title: \"Select date\")\nalert.addDatePicker(mode: .dateAndTime, date: date, minimumDate: minDate, maximumDate: maxDate) { date in\n    // action with selected date\n}\nalert.addAction(title: \"OK\", style: .cancel)\nalert.show()\n```\n\n## PickerView\n\nExample how to use `UIPickerView` as `contentViewController` and change height of the `UIAlertController`.\n\n\u003cdiv align = \"center\"\u003e\n\u003cimg src=\"Assets/gifs/actionSheet-pickerView.gif\" width=\"350\" /\u003e\n\u003cimg src=\"Assets/gifs/alert-pickerView.gif\" width=\"350\" /\u003e\n\u003c/div\u003e\n\n```swift\nlet alert = UIAlertController(style: .actionSheet, title: \"Picker View\", message: \"Preferred Content Height\")\n\nlet frameSizes: [CGFloat] = (150...400).map { CGFloat($0) }\nlet pickerViewValues: [[String]] = [frameSizes.map { Int($0).description }]\nlet pickerViewSelectedValue: PickerViewViewController.Index = (column: 0, row: frameSizes.index(of: 216) ?? 0)\n\nalert.addPickerView(values: pickerViewValues, initialSelection: pickerViewSelectedValue) { vc, picker, index, values in\n    DispatchQueue.main.async {\n        UIView.animate(withDuration: 1) {\n            vc.preferredContentSize.height = frameSizes[index.row]\n        }\n    }\n}\nalert.addAction(title: \"Done\", style: .cancel)\nalert.show()\n```\n\n## Locale Pickers\n\n* #### Country Picker\n\n\u003cdiv align = \"center\"\u003e\n\u003cimg src=\"Assets/gifs/actionSheet-countryPicker.gif\" width=\"350\" /\u003e\n\u003cimg src=\"Assets/gifs/alert-countryPicker.gif\" width=\"350\" /\u003e\n\u003c/div\u003e\n\n```swift\nlet alert = UIAlertController(style: .actionSheet, message: \"Select Country\")\nalert.addLocalePicker(type: .country) { info in\n    // action with selected object\n}\nalert.addAction(title: \"OK\", style: .cancel)\nalert.show()\n```\n\n* #### Phone Code Picker\n\n\u003cdiv align = \"center\"\u003e\n\u003cimg src=\"Assets/gifs/actionSheet-phoneCodePicker.gif\" width=\"350\" /\u003e\n\u003cimg src=\"Assets/gifs/alert-phoneCodePicker.gif\" width=\"350\" /\u003e\n\u003c/div\u003e\n\n```swift\nlet alert = UIAlertController(style: .actionSheet, title: \"Phone Codes\")\nalert.addLocalePicker(type: .phoneCode) { info in\n    // action with selected object\n}\nalert.addAction(title: \"OK\", style: .cancel)\nalert.show()\n```\n\n* #### Currency Picker\n\n\u003cdiv align = \"center\"\u003e\n\u003cimg src=\"Assets/gifs/actionSheet-currencyPicker.gif\" width=\"350\" /\u003e\n\u003cimg src=\"Assets/gifs/alert-currencyPicker.gif\" width=\"350\" /\u003e\n\u003c/div\u003e\n\n```swift\nlet alert = UIAlertController(style: .actionSheet, title: \"Currencies\")\nalert.addLocalePicker(type: .currency) { info in\n    alert.title = info?.currencyCode\n    alert.message = \"is selected\"\n    // action with selected object\n}\nalert.addAction(title: \"OK\", style: .cancel)\nalert.show()\n```\n\n## Image Picker\n\n\u003cdiv align = \"center\"\u003e\n\u003cimg src=\"Assets/gifs/actionSheet-imagePicker-h.gif\" width=\"350\" /\u003e\n\u003cimg src=\"Assets/gifs/actionSheet-imagePicker-v.gif\" width=\"350\" /\u003e\n\u003c/div\u003e\n\n* Horizontal Image Picker with paging and single selection:\n\n```swift\nlet alert = UIAlertController(style: .actionSheet)\nlet photos: [UIImage] = images\nalert.addImagePicker(\n    flow: .horizontal,\n    paging: true,\n    images: photos,\n    selection: .single(action: { [unowned self] image in\n        // action with selected image\n    }))\nalert.addAction(title: \"OK\", style: .cancel)\nalert.show()\n```\n\n* Vertical Image Picker w/o paging and with multiple selection:\n\n```swift\nlet alert = UIAlertController(style: .actionSheet)\nlet photos: [UIImage] = images\nalert.addImagePicker(\n    flow: .vertical,\n    paging: false,\n    height: UIScreen.main.bounds.height,\n    images: photos,\n    selection: .multiple(action: { [unowned self] images in\n        // action with selected images\n    }))\nalert.addAction(title: \"OK\", style: .cancel)\nalert.show()\n```\n\n## PhotoLibrary Picker\n\n\u003cdiv align = \"center\"\u003e\n\u003cimg src=\"Assets/gifs/actionSheet-photoLibraryPicker.gif\" width=\"350\" /\u003e\n\u003c/div\u003e\n\n```swift\nlet alert = UIAlertController(style: .actionSheet)\nalert.addPhotoLibraryPicker(\n    flow: .horizontal,\n    paging: true,\n    selection: .single(action: { image in\n        // action with selected image\n    }))\nalert.addAction(title: \"Cancel\", style: .cancel)\nalert.show()\n```\n\n## ColorPicker\n\nExample how to use UIViewController instantiated from Storyboard with Autolayout as `contentViewController` in the `UIAlertController`.\n\n\u003cdiv align = \"center\"\u003e\n\u003cimg src=\"Assets/gifs/actionSheet-colorPicker.gif\" width=\"350\" /\u003e\n\u003cimg src=\"Assets/gifs/alert-colorPicker.gif\" width=\"350\" /\u003e\n\u003c/div\u003e\n\n```swift\nlet alert = UIAlertController(style: .actionSheet)\nalert.addColorPicker(color: color) { color in\n    // action with selected color\n}\nalert.addAction(title: \"Done\", style: .cancel)\nalert.show()\n```\n\n## Contacts Picker\n\n\u003cdiv align = \"center\"\u003e\n\u003cimg src=\"Assets/gifs/actionSheet-contactsPicker.gif\" width=\"350\" /\u003e\n\u003cimg src=\"Assets/gifs/alert-contactsPicker.gif\" width=\"350\" /\u003e\n\u003c/div\u003e\n\n```swift\nlet alert = UIAlertController(style: .actionSheet)\nalert.addContactsPicker { contact in\n    // action with contact\n}\nalert.addAction(title: \"Cancel\", style: .cancel)\nalert.show()\n```\n\n## Location Picker\n\n\u003cdiv align = \"center\"\u003e\n\u003cimg src=\"Assets/gifs/actionSheet-locationPicker.gif\" width=\"350\" /\u003e\n\u003c/div\u003e\n\n```swift\nlet alert = UIAlertController(style: .actionSheet)\nalert.addLocationPicker { location in\n    // action with location\n}\nalert.addAction(title: \"Cancel\", style: .cancel)\nalert.show()\n```\n\n## Telegram Picker\n\n\u003cdiv align = \"center\"\u003e\n\u003cimg src=\"Assets/gifs/actionSheet-telegramPicker.gif\" width=\"350\" /\u003e\n\u003c/div\u003e\n\n```swift\nlet alert = UIAlertController(style: .actionSheet)\nalert.addTelegramPicker { result in\n    switch result {\n      case .photo(let assets):\n        // action with assets\n      case .contact(let contact):\n        // action with contact\n      case .location(let location):\n        // action with location\n    }\n}\nalert.addAction(title: \"Cancel\", style: .cancel)\nalert.show()\n```\n\n## TextViewer\n\n\u003cdiv align = \"center\"\u003e\n\u003cimg src=\"Assets/gifs/actionSheet-textViewer.gif\" width=\"350\" /\u003e\n\u003cimg src=\"Assets/gifs/alert-textViewer.gif\" width=\"350\" /\u003e\n\u003c/div\u003e\n\n```swift\nlet alert = UIAlertController(style: .actionSheet)\nalert.addTextViewer(text: .attributedText(text))\nalert.addAction(title: \"OK\", style: .cancel)\nalert.show()\n```\n\n\n## Alerts vs. Action Sheets\n\nThere are some things to keep in mind when using `.actionSheet` and `.alert` styles:\n\n* Pickers better to use in `.actionSheet` style.\n* `UITextField` can be used in both styles.\n\n## Installing\n\n#### Manually\n\nDownload and drop `/Source` folder in your project.\n\n## Requirements\n\n* Swift 4\n* iOS 11 or higher\n\n## Authors\n\n* **Roman Volodko** -  [dillidon](https://github.com/dillidon)\n\n## Communication\n\n* If you **found a bug**, open an issue.\n* If you **have a feature request**, open an issue.\n* If you **want to contribute**, submit a pull request.\n\n## License\n\nThis project is licensed under the MIT License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdillidon%2Falerts-and-pickers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdillidon%2Falerts-and-pickers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdillidon%2Falerts-and-pickers/lists"}