├── .gitignore
├── .swiftpm
└── xcode
│ └── package.xcworkspace
│ └── xcshareddata
│ └── IDEWorkspaceChecks.plist
├── AlertController.podspec.json
├── LICENSE
├── Package.swift
├── README.md
├── Sources
└── AlertController
│ └── AlertController.swift
└── Tests
└── AlertControllerTests
└── AlertControllerTests.swift
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | /.build
3 | /Packages
4 | /*.xcodeproj
5 | xcuserdata/
6 | DerivedData/
7 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
8 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/AlertController.podspec.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "AlertController",
3 | "version": "0.0.3",
4 | "summary": "💬 A tiny extension for UIAlertController that makes working with it very simple",
5 | "homepage": "https://github.com/mezhevikin/AlertController",
6 | "license": {
7 | "type": "MIT",
8 | "file": "LICENSE"
9 | },
10 | "authors": {
11 | "Mezhevikin Alexey": "mezhevikin@gmail.com"
12 | },
13 | "source": {
14 | "git": "https://github.com/mezhevikin/AlertController.git",
15 | "tag": "0.0.3"
16 | },
17 | "platforms": {
18 | "ios": "13.0"
19 | },
20 | "source_files": "Sources/**/*",
21 | "pushed_with_swift_version": "5.5",
22 | "frameworks": [
23 | "UIKit"
24 | ]
25 | }
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright 2022 Mezhevikin Alexey
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.5
2 | import PackageDescription
3 |
4 | let package = Package(
5 | name: "AlertController",
6 | platforms: [
7 | .iOS(.v13)
8 | ],
9 | products: [
10 | .library(
11 | name: "AlertController",
12 | targets: ["AlertController"]),
13 | ],
14 | dependencies: [
15 |
16 | ],
17 | targets: [
18 | .target(
19 | name: "AlertController",
20 | dependencies: []
21 | ),
22 | .testTarget(
23 | name: "AlertControllerTests",
24 | dependencies: ["AlertController"]),
25 | ]
26 | )
27 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AlertController
2 |
3 | 💬 A tiny extension for UIAlertController that makes working with it very simple. Only 150 lines of code.
4 |
5 | ### Alert
6 |
7 | ```swift
8 | let alert = UIAlertController.alert()
9 | alert.setTitle("✅ Success", color: .darkGreen)
10 | alert.setMessage("Your message has been sent")
11 | alert.addAction(
12 | title: "Send more",
13 | systemIcon: "envelope.fill",
14 | color: .darkGreen,
15 | leftAligment: true
16 | ) {}
17 | alert.addAction(
18 | title: "Delete message",
19 | systemIcon: "trash.fill",
20 | color: .red,
21 | leftAligment: true
22 | ) {}
23 | alert.addOkAction()
24 | present(alert, animated: true)
25 | ```
26 |
27 |
28 |
29 |
30 |
31 | ### Sheet
32 |
33 | ```swift
34 | let sheet = UIAlertController.sheet("👨🏻 Mezhevikin Alexey")
35 | sheet.addAction(
36 | title: "Edit profile",
37 | systemIcon: "person.fill",
38 | color: .darkGreen,
39 | leftAligment: true
40 | ) {}
41 | sheet.addAction(
42 | title: "Delete account",
43 | systemIcon: "trash.fill",
44 | color: .red,
45 | leftAligment: true
46 | ) {}
47 | sheet.addAction(
48 | title: "Log out",
49 | systemIcon: "square.and.arrow.down.fill",
50 | leftAligment: true
51 | ) {}
52 | sheet.addCancelAction()
53 | present(sheet, sourceView: cell)
54 | ```
55 |
56 |
57 |
58 |
59 |
60 | ### Choice
61 |
62 | ```swift
63 | let sheet = UIAlertController.sheet("Choose your favorite animal")
64 | let animals = ["🐈 Cat", "🐕 Dog", "🐎 Horse", "🐫 Camel"]
65 | for (i, animal) in animals.enumerated() {
66 | sheet.addAction(
67 | title: animal,
68 | checked: favoriteAnimal == i,
69 | leftAligment: true
70 | ) {
71 | self.favoriteAnimal = i
72 | }
73 | }
74 | sheet.addCancelAction()
75 | present(sheet, sourceView: cell)
76 | ```
77 |
78 |
79 |
80 |
81 |
82 | ### TextField
83 |
84 | ```swift
85 | let alert = UIAlertController.alert("🔓 Login")
86 | alert.addTextField {
87 | $0.placeholder = "✉️ Mail"
88 | }
89 | alert.addTextField {
90 | $0.placeholder = "🔑 Password"
91 | $0.isSecureTextEntry = true
92 | }
93 | alert.addAction(title: "OK") {
94 | if let mail = alert.textFields?[0].text,
95 | let password = alert.textFields?[1].text
96 | {
97 | print("✉️ \(mail), 🔑 \(password)")
98 | }
99 | }
100 | present(alert)
101 | ```
102 |
103 |
104 |
105 |
106 |
107 | ### Present
108 |
109 | ```swift
110 | // Alert
111 | present(alert)
112 | // Sheet from cell with iPad support
113 | present(sheet, sourceView: cell)
114 | // Sheet from BarButton with iPad support
115 | present(sheet, barButtonItem: navigationItem.leftBarButtonItem)
116 | ```
117 |
118 | ### Swift Package Manager
119 |
120 | ```
121 | https://github.com/mezhevikin/AlertController.git
122 | ```
123 |
124 | ### CocoaPods
125 |
126 | ```
127 | pod 'AlertController', :git => 'https://github.com/mezhevikin/AlertController.git'
128 | ```
--------------------------------------------------------------------------------
/Sources/AlertController/AlertController.swift:
--------------------------------------------------------------------------------
1 | // Mezhevikin Alexey: https://github.com/mezhevikin/AlertController
2 | import UIKit
3 |
4 | public extension UIAlertController {
5 | static func alert(
6 | _ title: String? = nil,
7 | message: String? = nil
8 | ) -> UIAlertController {
9 | UIAlertController(
10 | title: title,
11 | message: message,
12 | preferredStyle: .alert
13 | )
14 | }
15 |
16 | static func sheet(
17 | _ title: String? = nil
18 | ) -> UIAlertController {
19 | let sheet = UIAlertController(
20 | title: nil,
21 | message: nil,
22 | preferredStyle: .actionSheet
23 | )
24 | if let title = title {
25 | sheet.addAction(title: title, enabled: false)
26 | }
27 | return sheet
28 | }
29 |
30 | @discardableResult
31 | func addAction(
32 | title: String,
33 | style: UIAlertAction.Style = .default,
34 | icon: String? = nil,
35 | systemIcon: String? = nil,
36 | color: UIColor? = nil,
37 | enabled: Bool = true,
38 | checked: Bool = false,
39 | leftAligment: Bool = false,
40 | handler: (() -> Void)? = nil
41 | ) -> UIAlertAction {
42 | let action = UIAlertAction(title: title, style: style) { _ in
43 | if let handler = handler { handler() }
44 | }
45 | if let icon = icon {
46 | action.setIcon(icon)
47 | }
48 | if let systemIcon = systemIcon {
49 | action.setIcon(systemIcon, isSystem: true)
50 | }
51 | if let color = color {
52 | action.setColor(color)
53 | }
54 | action.isEnabled = enabled
55 | action.setChecked(checked)
56 | action.setLeftAligment(leftAligment)
57 | addAction(action)
58 | return action
59 | }
60 |
61 | func addCancelAction() {
62 | addAction(
63 | title: NSLocalizedString("Cancel", comment: ""),
64 | style: .cancel
65 | )
66 | }
67 |
68 | func addOkAction() {
69 | addAction(
70 | title: NSLocalizedString("OK", comment: ""),
71 | style: .cancel
72 | )
73 | }
74 |
75 | func setTitle(
76 | _ title: String,
77 | color: UIColor = .label,
78 | size: CGFloat = 20
79 | ) {
80 | setValue(NSAttributedString(string: title, attributes: [
81 | .font: UIFont.systemFont(ofSize: size),
82 | .foregroundColor: color
83 | ]), forKey: "attributedTitle")
84 | }
85 |
86 | func setMessage(
87 | _ message: String,
88 | color: UIColor = .secondaryLabel,
89 | size: CGFloat = 18
90 | ) {
91 | setValue(NSAttributedString(string: "\n" + message, attributes: [
92 | .font: UIFont.systemFont(ofSize: size),
93 | .foregroundColor: color
94 | ]), forKey: "attributedMessage")
95 | }
96 | }
97 |
98 | public extension UIAlertAction {
99 | func setImage(_ image: UIImage) {
100 | setValue(image, forKey: "image")
101 | }
102 |
103 | func setIcon(_ name: String, isSystem: Bool = false) {
104 | if let image = isSystem ?
105 | UIImage(systemName: name) :
106 | UIImage(named: name)
107 | {
108 | setImage(image)
109 | }
110 | }
111 |
112 | func setColor(_ color: UIColor) {
113 | setValue(color, forKey: "titleTextColor")
114 | setValue(color, forKey: "imageTintColor")
115 | }
116 |
117 | func setChecked(_ checked: Bool) {
118 | setValue(checked, forKey: "checked")
119 | }
120 |
121 | func setLeftAligment(_ leftAligment: Bool) {
122 | if leftAligment {
123 | setValue(CATextLayerAlignmentMode.left, forKey: "titleTextAlignment")
124 | }
125 | }
126 | }
127 |
128 | public extension UIViewController {
129 | func present(
130 | _ child: UIViewController,
131 | animated: Bool = true,
132 | sourceView: UIView? = nil,
133 | barButtonItem: UIBarButtonItem? = nil,
134 | completion: (() -> Void)? = nil
135 | ) {
136 | if let popover = child.popoverPresentationController {
137 | if let sourceView = sourceView {
138 | popover.sourceView = sourceView
139 | } else if let barButtonItem = barButtonItem {
140 | popover.barButtonItem = barButtonItem
141 | }
142 | }
143 | present(child, animated: animated, completion: completion)
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/Tests/AlertControllerTests/AlertControllerTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import AlertController
3 |
4 | final class AlertControllerTests: XCTestCase {
5 | }
6 |
--------------------------------------------------------------------------------