[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-6811":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":17,"stars7d":17,"stars30d":18,"stars90d":16,"forks30d":16,"starsTrendScore":19,"compositeScore":20,"rankGlobal":10,"rankLanguage":10,"license":21,"archived":22,"fork":22,"defaultBranch":23,"hasWiki":24,"hasPages":22,"topics":25,"createdAt":10,"pushedAt":10,"updatedAt":46,"readmeContent":47,"aiSummary":48,"trendingCount":16,"starSnapshotCount":16,"syncStatus":49,"lastSyncTime":50,"discoverSource":51},6811,"alerts-and-pickers","dillidon\u002Falerts-and-pickers","dillidon","Advanced usage of UIAlertController and pickers based on it: Telegram, Contacts, Location, PhotoLibrary, Country, Phone Code, Currency, Date...","",null,"Swift",5763,705,100,71,0,1,6,3,39.55,"MIT License",false,"new",true,[26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45],"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","2026-06-12 02:01:30","\u003Cdiv align = \"center\">\n\u003Cimg src=\"Assets\u002FLogo.png\" width=\"700\" \u002F>\n\u003C\u002Fdiv>\n\n\u003Cp align=\"center\">\n\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FSwift-4.0-orange.svg\" alt=\"Swift 4.0\"\u002F>\n\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fplatform-iOS-brightgreen.svg\" alt=\"Platform: iOS\"\u002F>\n\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FXcode-9%2B-brightgreen.svg\" alt=\"XCode 9+\"\u002F>\n\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FiOS-11%2B-brightgreen.svg\" alt=\"iOS 11\"\u002F>\n\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Flicence-MIT-lightgray.svg\" alt=\"Licence MIT\"\u002F>\n\u003C\u002Fa>\n\u003C\u002Fp>\n\n# Alerts & 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\">\n\u003Cimg src=\"Assets\u002Fgifs\u002FactionSheet-.gif\" width=\"400\" \u002F>\n\u003Cimg src=\"Assets\u002Fgifs\u002Falert-.gif\" width=\"400\" \u002F>\n\u003C\u002Fdiv>\n\n## Usage\n\n\u003Cdiv align = \"center\">\n\u003Cimg src=\"Assets\u002Fgifs\u002FactionSheet-simple.gif\" width=\"350\" \u002F>\n\u003Cimg src=\"Assets\u002Fgifs\u002Falert-simple.gif\" width=\"350\" \u002F>\n\u003C\u002Fdiv>\n\n- New Alert\n\n```swift\nlet alert = UIAlertController(style: .alert, title: \"Title\", message: \"Message\")\n\u002F\u002F 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\u002F\u002F 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\u002F\u002F 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    \u002F\u002F completion handler\n}\n```\n\n* Show Alert\n\n```swift\n\u002F\u002F show alert\nalert.show()\n\n\u002F\u002F or show alert with options\nalert.show(animated: true, vibrate: true) {\n    \u002F\u002F completion handler\n}\n```\n\u003Cdiv align = \"center\">\n\u003Cimg src=\"Assets\u002Fgifs\u002FactionSheet-simple-image.gif\" width=\"350\" \u002F>\n\u003Cimg src=\"Assets\u002Fgifs\u002Falert-simple-image.gif\" width=\"350\" \u002F>\n\u003C\u002Fdiv>\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\u002F\u002F 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\">\n\u003Cimg src=\"Assets\u002Fgifs\u002FactionSheet-textField-1.gif\" width=\"350\" \u002F>\n\u003Cimg src=\"Assets\u002Fgifs\u002Falert-textField-1.gif\" width=\"350\" \u002F>\n\u003C\u002Fdiv>\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        \u002F\u002F 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\">\n\u003Cimg src=\"Assets\u002Fgifs\u002FactionSheet-textField-2.gif\" width=\"350\" \u002F>\n\u003Cimg src=\"Assets\u002Fgifs\u002Falert-textField-2.gif\" width=\"350\" \u002F>\n\u003C\u002Fdiv>\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        \u002F\u002F 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        \u002F\u002F action with input\n    }\n}\n\u002F\u002F 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\">\n\u003Cimg src=\"Assets\u002Fgifs\u002FactionSheet-datePicker.gif\" width=\"350\" \u002F>\n\u003Cimg src=\"Assets\u002Fgifs\u002Falert-datePicker.gif\" width=\"350\" \u002F>\n\u003C\u002Fdiv>\n\n```swift\nlet alert = UIAlertController(style: .actionSheet, title: \"Select date\")\nalert.addDatePicker(mode: .dateAndTime, date: date, minimumDate: minDate, maximumDate: maxDate) { date in\n    \u002F\u002F 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\">\n\u003Cimg src=\"Assets\u002Fgifs\u002FactionSheet-pickerView.gif\" width=\"350\" \u002F>\n\u003Cimg src=\"Assets\u002Fgifs\u002Falert-pickerView.gif\" width=\"350\" \u002F>\n\u003C\u002Fdiv>\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\">\n\u003Cimg src=\"Assets\u002Fgifs\u002FactionSheet-countryPicker.gif\" width=\"350\" \u002F>\n\u003Cimg src=\"Assets\u002Fgifs\u002Falert-countryPicker.gif\" width=\"350\" \u002F>\n\u003C\u002Fdiv>\n\n```swift\nlet alert = UIAlertController(style: .actionSheet, message: \"Select Country\")\nalert.addLocalePicker(type: .country) { info in\n    \u002F\u002F action with selected object\n}\nalert.addAction(title: \"OK\", style: .cancel)\nalert.show()\n```\n\n* #### Phone Code Picker\n\n\u003Cdiv align = \"center\">\n\u003Cimg src=\"Assets\u002Fgifs\u002FactionSheet-phoneCodePicker.gif\" width=\"350\" \u002F>\n\u003Cimg src=\"Assets\u002Fgifs\u002Falert-phoneCodePicker.gif\" width=\"350\" \u002F>\n\u003C\u002Fdiv>\n\n```swift\nlet alert = UIAlertController(style: .actionSheet, title: \"Phone Codes\")\nalert.addLocalePicker(type: .phoneCode) { info in\n    \u002F\u002F action with selected object\n}\nalert.addAction(title: \"OK\", style: .cancel)\nalert.show()\n```\n\n* #### Currency Picker\n\n\u003Cdiv align = \"center\">\n\u003Cimg src=\"Assets\u002Fgifs\u002FactionSheet-currencyPicker.gif\" width=\"350\" \u002F>\n\u003Cimg src=\"Assets\u002Fgifs\u002Falert-currencyPicker.gif\" width=\"350\" \u002F>\n\u003C\u002Fdiv>\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    \u002F\u002F action with selected object\n}\nalert.addAction(title: \"OK\", style: .cancel)\nalert.show()\n```\n\n## Image Picker\n\n\u003Cdiv align = \"center\">\n\u003Cimg src=\"Assets\u002Fgifs\u002FactionSheet-imagePicker-h.gif\" width=\"350\" \u002F>\n\u003Cimg src=\"Assets\u002Fgifs\u002FactionSheet-imagePicker-v.gif\" width=\"350\" \u002F>\n\u003C\u002Fdiv>\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        \u002F\u002F action with selected image\n    }))\nalert.addAction(title: \"OK\", style: .cancel)\nalert.show()\n```\n\n* Vertical Image Picker w\u002Fo 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        \u002F\u002F action with selected images\n    }))\nalert.addAction(title: \"OK\", style: .cancel)\nalert.show()\n```\n\n## PhotoLibrary Picker\n\n\u003Cdiv align = \"center\">\n\u003Cimg src=\"Assets\u002Fgifs\u002FactionSheet-photoLibraryPicker.gif\" width=\"350\" \u002F>\n\u003C\u002Fdiv>\n\n```swift\nlet alert = UIAlertController(style: .actionSheet)\nalert.addPhotoLibraryPicker(\n    flow: .horizontal,\n    paging: true,\n    selection: .single(action: { image in\n        \u002F\u002F 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\">\n\u003Cimg src=\"Assets\u002Fgifs\u002FactionSheet-colorPicker.gif\" width=\"350\" \u002F>\n\u003Cimg src=\"Assets\u002Fgifs\u002Falert-colorPicker.gif\" width=\"350\" \u002F>\n\u003C\u002Fdiv>\n\n```swift\nlet alert = UIAlertController(style: .actionSheet)\nalert.addColorPicker(color: color) { color in\n    \u002F\u002F action with selected color\n}\nalert.addAction(title: \"Done\", style: .cancel)\nalert.show()\n```\n\n## Contacts Picker\n\n\u003Cdiv align = \"center\">\n\u003Cimg src=\"Assets\u002Fgifs\u002FactionSheet-contactsPicker.gif\" width=\"350\" \u002F>\n\u003Cimg src=\"Assets\u002Fgifs\u002Falert-contactsPicker.gif\" width=\"350\" \u002F>\n\u003C\u002Fdiv>\n\n```swift\nlet alert = UIAlertController(style: .actionSheet)\nalert.addContactsPicker { contact in\n    \u002F\u002F action with contact\n}\nalert.addAction(title: \"Cancel\", style: .cancel)\nalert.show()\n```\n\n## Location Picker\n\n\u003Cdiv align = \"center\">\n\u003Cimg src=\"Assets\u002Fgifs\u002FactionSheet-locationPicker.gif\" width=\"350\" \u002F>\n\u003C\u002Fdiv>\n\n```swift\nlet alert = UIAlertController(style: .actionSheet)\nalert.addLocationPicker { location in\n    \u002F\u002F action with location\n}\nalert.addAction(title: \"Cancel\", style: .cancel)\nalert.show()\n```\n\n## Telegram Picker\n\n\u003Cdiv align = \"center\">\n\u003Cimg src=\"Assets\u002Fgifs\u002FactionSheet-telegramPicker.gif\" width=\"350\" \u002F>\n\u003C\u002Fdiv>\n\n```swift\nlet alert = UIAlertController(style: .actionSheet)\nalert.addTelegramPicker { result in\n    switch result {\n      case .photo(let assets):\n        \u002F\u002F action with assets\n      case .contact(let contact):\n        \u002F\u002F action with contact\n      case .location(let location):\n        \u002F\u002F action with location\n    }\n}\nalert.addAction(title: \"Cancel\", style: .cancel)\nalert.show()\n```\n\n## TextViewer\n\n\u003Cdiv align = \"center\">\n\u003Cimg src=\"Assets\u002Fgifs\u002FactionSheet-textViewer.gif\" width=\"350\" \u002F>\n\u003Cimg src=\"Assets\u002Fgifs\u002Falert-textViewer.gif\" width=\"350\" \u002F>\n\u003C\u002Fdiv>\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 `\u002FSource` 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:\u002F\u002Fgithub.com\u002Fdillidon)\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","该项目提供了基于UIAlertController的高级用法，支持多种类型的Picker，如联系人、位置、照片库、国家、电话代码、货币和日期等。核心功能包括自定义Picker视图、Storyboard示例、便捷的内容视图控制器放置、样式化的标题和消息标签以及按钮自定义等。技术特点在于使用纯Swift 4编写，并且易于集成与展示。适用于iOS开发中需要丰富用户输入选择场景的应用程序，例如在表单填写、设置页面或任何需要用户进行多选项选择的地方。",2,"2026-06-11 03:09:01","top_language"]