├── .gitignore ├── LICENSE ├── README.md ├── SweetAlert.podspec ├── SweetAlert.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── gndbl.xcuserdatad │ │ └── WorkspaceSettings.xcsettings └── xcuserdata │ └── gndbl.xcuserdatad │ └── xcschemes │ ├── SweetAlert.xcscheme │ └── xcschememanagement.plist ├── SweetAlert ├── AppDelegate.swift ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── SweetAlert.png ├── SweetAlert.swift ├── ViewController.swift └── logo_big.png ├── SweetAlertiOS.gif └── thumb.jpg /.gitignore: -------------------------------------------------------------------------------- 1 | ### Swift template 2 | # Xcode 3 | # 4 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 5 | 6 | ## Build generated 7 | build/ 8 | DerivedData 9 | 10 | ## Various settings 11 | *.pbxuser 12 | !default.pbxuser 13 | *.mode1v3 14 | !default.mode1v3 15 | *.mode2v3 16 | !default.mode2v3 17 | *.perspectivev3 18 | !default.perspectivev3 19 | xcuserdata 20 | 21 | ## Other 22 | *.xccheckout 23 | *.moved-aside 24 | *.xcuserstate 25 | *.xcscmblueprint 26 | 27 | ## Obj-C/Swift specific 28 | *.hmap 29 | *.ipa 30 | 31 | # CocoaPods 32 | # 33 | # We recommend against adding the Pods directory to your .gitignore. However 34 | # you should judge for yourself, the pros and cons are mentioned at: 35 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 36 | # 37 | # Pods/ 38 | 39 | # Carthage 40 | # 41 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 42 | # Carthage/Checkouts 43 | 44 | Carthage/Build 45 | ### Objective-C template 46 | # Xcode 47 | # 48 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 49 | 50 | ## Build generated 51 | build/ 52 | DerivedData 53 | 54 | ## Various settings 55 | *.pbxuser 56 | !default.pbxuser 57 | *.mode1v3 58 | !default.mode1v3 59 | *.mode2v3 60 | !default.mode2v3 61 | *.perspectivev3 62 | !default.perspectivev3 63 | xcuserdata 64 | 65 | ## Other 66 | *.xccheckout 67 | *.moved-aside 68 | *.xcuserstate 69 | *.xcscmblueprint 70 | 71 | ## Obj-C/Swift specific 72 | *.hmap 73 | *.ipa 74 | 75 | # CocoaPods 76 | # 77 | # We recommend against adding the Pods directory to your .gitignore. However 78 | # you should judge for yourself, the pros and cons are mentioned at: 79 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 80 | # 81 | #Pods/ 82 | 83 | # Carthage 84 | # 85 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 86 | # Carthage/Checkouts 87 | 88 | Carthage/Build 89 | 90 | # Created by .ignore support plugin (hsz.mobi) 91 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 codester 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Sweet Alert iOS 2 | ============== 3 | 4 | Beautiful Animated custom Alert View inspired from javascript library [SweetAlert](http://tristanedwards.me/sweetalert). 5 | Written in Swift this SweetAlertView can be used in Swift and Objective-C projects. SweetAlertView provides live intutive experience to user actions.It can be used in place of `UIAlertView` and `UIAlertController` 6 | 7 | ###ScreenShots 8 | ![SweetAlert](https://github.com/codestergit/SweetAlert-iOS/blob/master/SweetAlertiOS.gif) 9 | 10 | ###Usage 11 | #####Basic message: 12 | ```swift 13 | SweetAlert().showAlert("Here's a message!") 14 | ``` 15 | #####Title with a text under: 16 | ```swift 17 | SweetAlert().showAlert("Here's a message!", subTitle: "It's pretty, isn't it?", style: AlertStyle.None) 18 | ``` 19 | #####Animated Success message: 20 | ```swift 21 | SweetAlert().showAlert("Good job!", subTitle: "You clicked the button!", style: AlertStyle.Success) 22 | ``` 23 | #####Warning message and Chained Animated Success messge on completion: 24 | ```swift 25 | SweetAlert().showAlert("Are you sure?", subTitle: "You file will permanently delete!", style: AlertStyle.Warning, buttonTitle:"Cancel", buttonColor:UIColorFromRGB(0xD0D0D0) , otherButtonTitle: "Yes, delete it!", otherButtonColor: UIColorFromRGB(0xDD6B55)) { (isOtherButton) -> Void in 26 | if isOtherButton == true { 27 | 28 | println("Cancel Button Pressed") 29 | } 30 | else { 31 | SweetAlert().showAlert("Deleted!", subTitle: "Your imaginary file has been deleted!", style: AlertStyle.Success) 32 | } 33 | } 34 | ``` 35 | 36 | #####Chained Alerts on actions with custom button colors: 37 | ```swift 38 | //Chaining alerts with messages on button click 39 | SweetAlert().showAlert("Are you sure?", subTitle: "You file will permanently delete!", style: AlertStyle.Warning, buttonTitle:"No, cancel plx!", buttonColor:UIColorFromRGB(0xD0D0D0) , otherButtonTitle: "Yes, delete it!", otherButtonColor: UIColorFromRGB(0xDD6B55)) { (isOtherButton) -> Void in 40 | if isOtherButton == true { 41 | 42 | SweetAlert().showAlert("Cancelled!", subTitle: "Your imaginary file is safe", style: AlertStyle.Error) 43 | } 44 | else { 45 | SweetAlert().showAlert("Deleted!", subTitle: "Your imaginary file has been deleted!", style: AlertStyle.Success) 46 | } 47 | } 48 | ``` 49 | #####Custom icon alert: 50 | ```swift 51 | SweetAlert().showAlert("Sweet!", subTitle: "Here's a custom image.", style: AlertStyle.CustomImag(imageFile: "thumb.jpg")) 52 | ``` 53 | 54 | ###Diffrent Animated Styles for Diffrent Purposes 55 | ```swift 56 | enum AlertStyle { 57 | case Success,Error,Warning,None 58 | case CustomImag(imageFile:String) 59 | } 60 | ``` 61 | ###Installation 62 | Add the `SwiftAlert.swift` in to your project. 63 | 64 | ###Reuirements 65 | - Xcode 7.0+ 66 | - iOS 7.0+ 67 | 68 | ## License 69 | 70 | The MIT License (MIT) 71 | 72 | Copyright (c) 2014 codestergit 73 | 74 | Permission is hereby granted, free of charge, to any person obtaining a copy 75 | of this software and associated documentation files (the "Software"), to deal 76 | in the Software without restriction, including without limitation the rights 77 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 78 | copies of the Software, and to permit persons to whom the Software is 79 | furnished to do so, subject to the following conditions: 80 | 81 | The above copyright notice and this permission notice shall be included in all 82 | copies or substantial portions of the Software. 83 | 84 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 85 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 86 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 87 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 88 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 89 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 90 | SOFTWARE. 91 | -------------------------------------------------------------------------------- /SweetAlert.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "SweetAlert" 3 | s.version = "0.1.0" 4 | s.summary = "Thin wrapper around NSURLSession in Swift. Simplifies HTTP requests." 5 | s.homepage = "https://github.com/codestergit/SweetAlert-iOS" 6 | s.license = 'MIT' 7 | s.author = {'codestergit' => 'https://github.com/codestergit/SweetAlert-iOS'} 8 | s.source = { :git => 'https://github.com/codestergit/SweetAlert-iOS.git', :tag => "#{s.version}"} 9 | s.ios.deployment_target = '8.0' 10 | s.source_files = 'SweetAlert/*.swift' 11 | s.requires_arc = 'true' 12 | end 13 | -------------------------------------------------------------------------------- /SweetAlert.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 784864ED6A0B7AF68C8DE1D8 /* SweetAlert.podspec in Resources */ = {isa = PBXBuildFile; fileRef = 784869A188ADBAB6A90C84DF /* SweetAlert.podspec */; }; 11 | 9B4286E81A0D2F5C00E9913B /* SweetAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B4286E71A0D2F5C00E9913B /* SweetAlert.swift */; }; 12 | 9B4286EB1A0D2F7700E9913B /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B4286E91A0D2F7700E9913B /* AppDelegate.swift */; }; 13 | 9B4286EC1A0D2F7700E9913B /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B4286EA1A0D2F7700E9913B /* ViewController.swift */; }; 14 | 9B4286EE1A0D2FA000E9913B /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9B4286ED1A0D2FA000E9913B /* Images.xcassets */; }; 15 | 9B4286F31A0D2FAF00E9913B /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9B4286EF1A0D2FAF00E9913B /* LaunchScreen.xib */; }; 16 | 9B4286F41A0D2FAF00E9913B /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9B4286F11A0D2FAF00E9913B /* Main.storyboard */; }; 17 | 9B4286F91A0D2FC500E9913B /* logo_big.png in Resources */ = {isa = PBXBuildFile; fileRef = 9B4286F61A0D2FC500E9913B /* logo_big.png */; }; 18 | 9B4286FA1A0D2FC500E9913B /* SweetAlert.png in Resources */ = {isa = PBXBuildFile; fileRef = 9B4286F71A0D2FC500E9913B /* SweetAlert.png */; }; 19 | 9B4CD1311A06E9C400B65DE0 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9B4CD1301A06E9C400B65DE0 /* QuartzCore.framework */; }; 20 | 9BCAC7A51A0E0B3600282753 /* thumb.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 9BCAC7A41A0E0B3600282753 /* thumb.jpg */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXFileReference section */ 24 | 784869A188ADBAB6A90C84DF /* SweetAlert.podspec */ = {isa = PBXFileReference; lastKnownFileType = file.podspec; path = SweetAlert.podspec; sourceTree = ""; }; 25 | 9B4286E71A0D2F5C00E9913B /* SweetAlert.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SweetAlert.swift; path = SweetAlert/SweetAlert.swift; sourceTree = SOURCE_ROOT; }; 26 | 9B4286E91A0D2F7700E9913B /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = SweetAlert/AppDelegate.swift; sourceTree = SOURCE_ROOT; }; 27 | 9B4286EA1A0D2F7700E9913B /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ViewController.swift; path = SweetAlert/ViewController.swift; sourceTree = SOURCE_ROOT; }; 28 | 9B4286ED1A0D2FA000E9913B /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = SweetAlert/Images.xcassets; sourceTree = SOURCE_ROOT; }; 29 | 9B4286F01A0D2FAF00E9913B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = SweetAlert/Base.lproj/LaunchScreen.xib; sourceTree = SOURCE_ROOT; }; 30 | 9B4286F21A0D2FAF00E9913B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = SweetAlert/Base.lproj/Main.storyboard; sourceTree = SOURCE_ROOT; }; 31 | 9B4286F51A0D2FC500E9913B /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = SweetAlert/Info.plist; sourceTree = SOURCE_ROOT; }; 32 | 9B4286F61A0D2FC500E9913B /* logo_big.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = logo_big.png; path = SweetAlert/logo_big.png; sourceTree = SOURCE_ROOT; }; 33 | 9B4286F71A0D2FC500E9913B /* SweetAlert.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = SweetAlert.png; path = SweetAlert/SweetAlert.png; sourceTree = SOURCE_ROOT; }; 34 | 9B4CD1081A06E55200B65DE0 /* SweetAlert.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SweetAlert.app; sourceTree = BUILT_PRODUCTS_DIR; }; 35 | 9B4CD1301A06E9C400B65DE0 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 36 | 9BCAC7A41A0E0B3600282753 /* thumb.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = thumb.jpg; sourceTree = SOURCE_ROOT; }; 37 | /* End PBXFileReference section */ 38 | 39 | /* Begin PBXFrameworksBuildPhase section */ 40 | 9B4CD1051A06E55200B65DE0 /* Frameworks */ = { 41 | isa = PBXFrameworksBuildPhase; 42 | buildActionMask = 2147483647; 43 | files = ( 44 | 9B4CD1311A06E9C400B65DE0 /* QuartzCore.framework in Frameworks */, 45 | ); 46 | runOnlyForDeploymentPostprocessing = 0; 47 | }; 48 | /* End PBXFrameworksBuildPhase section */ 49 | 50 | /* Begin PBXGroup section */ 51 | 9B4286FB1A0D300300E9913B /* Frameworks */ = { 52 | isa = PBXGroup; 53 | children = ( 54 | 9B4CD1301A06E9C400B65DE0 /* QuartzCore.framework */, 55 | ); 56 | name = Frameworks; 57 | sourceTree = ""; 58 | }; 59 | 9B4CD0FF1A06E55200B65DE0 = { 60 | isa = PBXGroup; 61 | children = ( 62 | 9B4CD10A1A06E55200B65DE0 /* SweetAlert */, 63 | 9B4CD1091A06E55200B65DE0 /* Products */, 64 | 784869A188ADBAB6A90C84DF /* SweetAlert.podspec */, 65 | ); 66 | sourceTree = ""; 67 | }; 68 | 9B4CD1091A06E55200B65DE0 /* Products */ = { 69 | isa = PBXGroup; 70 | children = ( 71 | 9B4CD1081A06E55200B65DE0 /* SweetAlert.app */, 72 | ); 73 | name = Products; 74 | sourceTree = ""; 75 | }; 76 | 9B4CD10A1A06E55200B65DE0 /* SweetAlert */ = { 77 | isa = PBXGroup; 78 | children = ( 79 | 9B4CD12D1A06E7EF00B65DE0 /* SweetAlert */, 80 | 9B4286E91A0D2F7700E9913B /* AppDelegate.swift */, 81 | 9B4286EA1A0D2F7700E9913B /* ViewController.swift */, 82 | 9B4286EF1A0D2FAF00E9913B /* LaunchScreen.xib */, 83 | 9B4286F11A0D2FAF00E9913B /* Main.storyboard */, 84 | 9B4286ED1A0D2FA000E9913B /* Images.xcassets */, 85 | 9B4CD10B1A06E55200B65DE0 /* Supporting Files */, 86 | ); 87 | name = SweetAlert; 88 | path = GNDBLAlert; 89 | sourceTree = ""; 90 | }; 91 | 9B4CD10B1A06E55200B65DE0 /* Supporting Files */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | 9BCAC7A41A0E0B3600282753 /* thumb.jpg */, 95 | 9B4286FB1A0D300300E9913B /* Frameworks */, 96 | 9B4286F51A0D2FC500E9913B /* Info.plist */, 97 | 9B4286F61A0D2FC500E9913B /* logo_big.png */, 98 | 9B4286F71A0D2FC500E9913B /* SweetAlert.png */, 99 | ); 100 | name = "Supporting Files"; 101 | sourceTree = ""; 102 | }; 103 | 9B4CD12D1A06E7EF00B65DE0 /* SweetAlert */ = { 104 | isa = PBXGroup; 105 | children = ( 106 | 9B4286E71A0D2F5C00E9913B /* SweetAlert.swift */, 107 | ); 108 | name = SweetAlert; 109 | sourceTree = ""; 110 | }; 111 | /* End PBXGroup section */ 112 | 113 | /* Begin PBXNativeTarget section */ 114 | 9B4CD1071A06E55200B65DE0 /* SweetAlert */ = { 115 | isa = PBXNativeTarget; 116 | buildConfigurationList = 9B4CD1271A06E55300B65DE0 /* Build configuration list for PBXNativeTarget "SweetAlert" */; 117 | buildPhases = ( 118 | 9B4CD1041A06E55200B65DE0 /* Sources */, 119 | 9B4CD1051A06E55200B65DE0 /* Frameworks */, 120 | 9B4CD1061A06E55200B65DE0 /* Resources */, 121 | ); 122 | buildRules = ( 123 | ); 124 | dependencies = ( 125 | ); 126 | name = SweetAlert; 127 | productName = GNDBLAlert; 128 | productReference = 9B4CD1081A06E55200B65DE0 /* SweetAlert.app */; 129 | productType = "com.apple.product-type.application"; 130 | }; 131 | /* End PBXNativeTarget section */ 132 | 133 | /* Begin PBXProject section */ 134 | 9B4CD1001A06E55200B65DE0 /* Project object */ = { 135 | isa = PBXProject; 136 | attributes = { 137 | LastUpgradeCheck = 0800; 138 | ORGANIZATIONNAME = "Sahil Wasan"; 139 | TargetAttributes = { 140 | 9B4CD1071A06E55200B65DE0 = { 141 | CreatedOnToolsVersion = 6.1; 142 | LastSwiftMigration = 0800; 143 | }; 144 | }; 145 | }; 146 | buildConfigurationList = 9B4CD1031A06E55200B65DE0 /* Build configuration list for PBXProject "SweetAlert" */; 147 | compatibilityVersion = "Xcode 3.2"; 148 | developmentRegion = English; 149 | hasScannedForEncodings = 0; 150 | knownRegions = ( 151 | en, 152 | Base, 153 | ); 154 | mainGroup = 9B4CD0FF1A06E55200B65DE0; 155 | productRefGroup = 9B4CD1091A06E55200B65DE0 /* Products */; 156 | projectDirPath = ""; 157 | projectRoot = ""; 158 | targets = ( 159 | 9B4CD1071A06E55200B65DE0 /* SweetAlert */, 160 | ); 161 | }; 162 | /* End PBXProject section */ 163 | 164 | /* Begin PBXResourcesBuildPhase section */ 165 | 9B4CD1061A06E55200B65DE0 /* Resources */ = { 166 | isa = PBXResourcesBuildPhase; 167 | buildActionMask = 2147483647; 168 | files = ( 169 | 9B4286F31A0D2FAF00E9913B /* LaunchScreen.xib in Resources */, 170 | 9B4286FA1A0D2FC500E9913B /* SweetAlert.png in Resources */, 171 | 9B4286EE1A0D2FA000E9913B /* Images.xcassets in Resources */, 172 | 9B4286F41A0D2FAF00E9913B /* Main.storyboard in Resources */, 173 | 9B4286F91A0D2FC500E9913B /* logo_big.png in Resources */, 174 | 9BCAC7A51A0E0B3600282753 /* thumb.jpg in Resources */, 175 | 784864ED6A0B7AF68C8DE1D8 /* SweetAlert.podspec in Resources */, 176 | ); 177 | runOnlyForDeploymentPostprocessing = 0; 178 | }; 179 | /* End PBXResourcesBuildPhase section */ 180 | 181 | /* Begin PBXSourcesBuildPhase section */ 182 | 9B4CD1041A06E55200B65DE0 /* Sources */ = { 183 | isa = PBXSourcesBuildPhase; 184 | buildActionMask = 2147483647; 185 | files = ( 186 | 9B4286EC1A0D2F7700E9913B /* ViewController.swift in Sources */, 187 | 9B4286EB1A0D2F7700E9913B /* AppDelegate.swift in Sources */, 188 | 9B4286E81A0D2F5C00E9913B /* SweetAlert.swift in Sources */, 189 | ); 190 | runOnlyForDeploymentPostprocessing = 0; 191 | }; 192 | /* End PBXSourcesBuildPhase section */ 193 | 194 | /* Begin PBXVariantGroup section */ 195 | 9B4286EF1A0D2FAF00E9913B /* LaunchScreen.xib */ = { 196 | isa = PBXVariantGroup; 197 | children = ( 198 | 9B4286F01A0D2FAF00E9913B /* Base */, 199 | ); 200 | name = LaunchScreen.xib; 201 | sourceTree = ""; 202 | }; 203 | 9B4286F11A0D2FAF00E9913B /* Main.storyboard */ = { 204 | isa = PBXVariantGroup; 205 | children = ( 206 | 9B4286F21A0D2FAF00E9913B /* Base */, 207 | ); 208 | name = Main.storyboard; 209 | sourceTree = ""; 210 | }; 211 | /* End PBXVariantGroup section */ 212 | 213 | /* Begin XCBuildConfiguration section */ 214 | 9B4CD1251A06E55300B65DE0 /* Debug */ = { 215 | isa = XCBuildConfiguration; 216 | buildSettings = { 217 | ALWAYS_SEARCH_USER_PATHS = NO; 218 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 219 | CLANG_CXX_LIBRARY = "libc++"; 220 | CLANG_ENABLE_MODULES = YES; 221 | CLANG_ENABLE_OBJC_ARC = YES; 222 | CLANG_WARN_BOOL_CONVERSION = YES; 223 | CLANG_WARN_CONSTANT_CONVERSION = YES; 224 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 225 | CLANG_WARN_EMPTY_BODY = YES; 226 | CLANG_WARN_ENUM_CONVERSION = YES; 227 | CLANG_WARN_INFINITE_RECURSION = YES; 228 | CLANG_WARN_INT_CONVERSION = YES; 229 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 230 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 231 | CLANG_WARN_UNREACHABLE_CODE = YES; 232 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 233 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 234 | COPY_PHASE_STRIP = NO; 235 | ENABLE_STRICT_OBJC_MSGSEND = YES; 236 | ENABLE_TESTABILITY = YES; 237 | GCC_C_LANGUAGE_STANDARD = gnu99; 238 | GCC_DYNAMIC_NO_PIC = NO; 239 | GCC_NO_COMMON_BLOCKS = YES; 240 | GCC_OPTIMIZATION_LEVEL = 0; 241 | GCC_PREPROCESSOR_DEFINITIONS = ( 242 | "DEBUG=1", 243 | "$(inherited)", 244 | ); 245 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 246 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 247 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 248 | GCC_WARN_UNDECLARED_SELECTOR = YES; 249 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 250 | GCC_WARN_UNUSED_FUNCTION = YES; 251 | GCC_WARN_UNUSED_VARIABLE = YES; 252 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 253 | MTL_ENABLE_DEBUG_INFO = YES; 254 | ONLY_ACTIVE_ARCH = YES; 255 | SDKROOT = iphoneos; 256 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 257 | }; 258 | name = Debug; 259 | }; 260 | 9B4CD1261A06E55300B65DE0 /* Release */ = { 261 | isa = XCBuildConfiguration; 262 | buildSettings = { 263 | ALWAYS_SEARCH_USER_PATHS = NO; 264 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 265 | CLANG_CXX_LIBRARY = "libc++"; 266 | CLANG_ENABLE_MODULES = YES; 267 | CLANG_ENABLE_OBJC_ARC = YES; 268 | CLANG_WARN_BOOL_CONVERSION = YES; 269 | CLANG_WARN_CONSTANT_CONVERSION = YES; 270 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 271 | CLANG_WARN_EMPTY_BODY = YES; 272 | CLANG_WARN_ENUM_CONVERSION = YES; 273 | CLANG_WARN_INFINITE_RECURSION = YES; 274 | CLANG_WARN_INT_CONVERSION = YES; 275 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 276 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 277 | CLANG_WARN_UNREACHABLE_CODE = YES; 278 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 279 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 280 | COPY_PHASE_STRIP = YES; 281 | ENABLE_NS_ASSERTIONS = NO; 282 | ENABLE_STRICT_OBJC_MSGSEND = YES; 283 | GCC_C_LANGUAGE_STANDARD = gnu99; 284 | GCC_NO_COMMON_BLOCKS = YES; 285 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 286 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 287 | GCC_WARN_UNDECLARED_SELECTOR = YES; 288 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 289 | GCC_WARN_UNUSED_FUNCTION = YES; 290 | GCC_WARN_UNUSED_VARIABLE = YES; 291 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 292 | MTL_ENABLE_DEBUG_INFO = NO; 293 | SDKROOT = iphoneos; 294 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 295 | VALIDATE_PRODUCT = YES; 296 | }; 297 | name = Release; 298 | }; 299 | 9B4CD1281A06E55300B65DE0 /* Debug */ = { 300 | isa = XCBuildConfiguration; 301 | buildSettings = { 302 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 303 | INFOPLIST_FILE = SweetAlert/Info.plist; 304 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 305 | PRODUCT_BUNDLE_IDENTIFIER = "GNDBL.$(PRODUCT_NAME:rfc1034identifier)"; 306 | PRODUCT_NAME = "$(TARGET_NAME)"; 307 | SWIFT_VERSION = 3.0; 308 | }; 309 | name = Debug; 310 | }; 311 | 9B4CD1291A06E55300B65DE0 /* Release */ = { 312 | isa = XCBuildConfiguration; 313 | buildSettings = { 314 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 315 | INFOPLIST_FILE = SweetAlert/Info.plist; 316 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 317 | PRODUCT_BUNDLE_IDENTIFIER = "GNDBL.$(PRODUCT_NAME:rfc1034identifier)"; 318 | PRODUCT_NAME = "$(TARGET_NAME)"; 319 | SWIFT_VERSION = 3.0; 320 | }; 321 | name = Release; 322 | }; 323 | /* End XCBuildConfiguration section */ 324 | 325 | /* Begin XCConfigurationList section */ 326 | 9B4CD1031A06E55200B65DE0 /* Build configuration list for PBXProject "SweetAlert" */ = { 327 | isa = XCConfigurationList; 328 | buildConfigurations = ( 329 | 9B4CD1251A06E55300B65DE0 /* Debug */, 330 | 9B4CD1261A06E55300B65DE0 /* Release */, 331 | ); 332 | defaultConfigurationIsVisible = 0; 333 | defaultConfigurationName = Release; 334 | }; 335 | 9B4CD1271A06E55300B65DE0 /* Build configuration list for PBXNativeTarget "SweetAlert" */ = { 336 | isa = XCConfigurationList; 337 | buildConfigurations = ( 338 | 9B4CD1281A06E55300B65DE0 /* Debug */, 339 | 9B4CD1291A06E55300B65DE0 /* Release */, 340 | ); 341 | defaultConfigurationIsVisible = 0; 342 | defaultConfigurationName = Release; 343 | }; 344 | /* End XCConfigurationList section */ 345 | }; 346 | rootObject = 9B4CD1001A06E55200B65DE0 /* Project object */; 347 | } 348 | -------------------------------------------------------------------------------- /SweetAlert.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SweetAlert.xcodeproj/project.xcworkspace/xcuserdata/gndbl.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 6 | 7 | SnapshotAutomaticallyBeforeSignificantChanges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /SweetAlert.xcodeproj/xcuserdata/gndbl.xcuserdatad/xcschemes/SweetAlert.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 67 | 68 | 78 | 80 | 86 | 87 | 88 | 89 | 93 | 94 | 95 | 96 | 102 | 104 | 110 | 111 | 112 | 113 | 115 | 116 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /SweetAlert.xcodeproj/xcuserdata/gndbl.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SweetAlert.xcscheme 8 | 9 | orderHint 10 | 1 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 9B4CD1071A06E55200B65DE0 16 | 17 | primary 18 | 19 | 20 | 9B4CD11C1A06E55300B65DE0 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /SweetAlert/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SweetAlert 4 | // 5 | // Created by Codester on 11/3/14. 6 | // Copyright (c) 2014 Codester. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /SweetAlert/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /SweetAlert/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 44 | 60 | 76 | 92 | 108 | 115 | 122 | 129 | 136 | 152 | 163 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | -------------------------------------------------------------------------------- /SweetAlert/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /SweetAlert/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /SweetAlert/SweetAlert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codestergit/SweetAlert-iOS/b97db81e4d9cf78e0e41af6e2bbc0ecac59dd120/SweetAlert/SweetAlert.png -------------------------------------------------------------------------------- /SweetAlert/SweetAlert.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SweetAlert.swift 3 | // SweetAlert 4 | // 5 | // Created by Codester on 11/3/14. 6 | // Copyright (c) 2014 Codester. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | import QuartzCore 12 | 13 | public enum AlertStyle { 14 | case success,error,warning,none 15 | case customImage(imageFile:String) 16 | } 17 | 18 | open class SweetAlert: UIViewController { 19 | let kBakcgroundTansperancy: CGFloat = 0.7 20 | let kHeightMargin: CGFloat = 10.0 21 | let KTopMargin: CGFloat = 20.0 22 | let kWidthMargin: CGFloat = 10.0 23 | let kAnimatedViewHeight: CGFloat = 70.0 24 | let kMaxHeight: CGFloat = 300.0 25 | var kContentWidth: CGFloat = 300.0 26 | let kButtonHeight: CGFloat = 35.0 27 | var textViewHeight: CGFloat = 90.0 28 | let kTitleHeight:CGFloat = 30.0 29 | var strongSelf:SweetAlert? 30 | var contentView = UIView() 31 | var titleLabel: UILabel = UILabel() 32 | var buttons: [UIButton] = [] 33 | var animatedView: AnimatableView? 34 | var imageView:UIImageView? 35 | var subTitleTextView = UITextView() 36 | var userAction:((_ isOtherButton: Bool) -> Void)? = nil 37 | let kFont = "Helvetica" 38 | 39 | init() { 40 | super.init(nibName: nil, bundle: nil) 41 | self.view.frame = UIScreen.main.bounds 42 | self.view.autoresizingMask = [UIViewAutoresizing.flexibleHeight, UIViewAutoresizing.flexibleWidth] 43 | self.view.backgroundColor = UIColor(red:0, green:0, blue:0, alpha:kBakcgroundTansperancy) 44 | self.view.addSubview(contentView) 45 | 46 | //Retaining itself strongly so can exist without strong refrence 47 | strongSelf = self 48 | } 49 | 50 | required public init(coder aDecoder: NSCoder) { 51 | fatalError("init(coder:) has not been implemented") 52 | } 53 | 54 | fileprivate func setupContentView() { 55 | contentView.backgroundColor = UIColor(white: 1.0, alpha: 1.0) 56 | contentView.layer.cornerRadius = 5.0 57 | contentView.layer.masksToBounds = true 58 | contentView.layer.borderWidth = 0.5 59 | contentView.addSubview(titleLabel) 60 | contentView.addSubview(subTitleTextView) 61 | contentView.backgroundColor = UIColor.colorFromRGB(0xFFFFFF) 62 | contentView.layer.borderColor = UIColor.colorFromRGB(0xCCCCCC).cgColor 63 | view.addSubview(contentView) 64 | } 65 | 66 | fileprivate func setupTitleLabel() { 67 | titleLabel.text = "" 68 | titleLabel.numberOfLines = 1 69 | titleLabel.textAlignment = .center 70 | titleLabel.font = UIFont(name: kFont, size:25) 71 | titleLabel.textColor = UIColor.colorFromRGB(0x575757) 72 | } 73 | 74 | fileprivate func setupSubtitleTextView() { 75 | subTitleTextView.text = "" 76 | subTitleTextView.textAlignment = .center 77 | subTitleTextView.font = UIFont(name: kFont, size:16) 78 | subTitleTextView.textColor = UIColor.colorFromRGB(0x797979) 79 | subTitleTextView.isEditable = false 80 | } 81 | 82 | fileprivate func resizeAndRelayout() { 83 | let mainScreenBounds = UIScreen.main.bounds 84 | self.view.frame.size = mainScreenBounds.size 85 | let x: CGFloat = kWidthMargin 86 | var y: CGFloat = KTopMargin 87 | let width: CGFloat = kContentWidth - (kWidthMargin*2) 88 | 89 | if animatedView != nil { 90 | animatedView!.frame = CGRect(x: (kContentWidth - kAnimatedViewHeight) / 2.0, y: y, width: kAnimatedViewHeight, height: kAnimatedViewHeight) 91 | contentView.addSubview(animatedView!) 92 | y += kAnimatedViewHeight + kHeightMargin 93 | } 94 | 95 | if imageView != nil { 96 | imageView!.frame = CGRect(x: (kContentWidth - kAnimatedViewHeight) / 2.0, y: y, width: kAnimatedViewHeight, height: kAnimatedViewHeight) 97 | contentView.addSubview(imageView!) 98 | y += imageView!.frame.size.height + kHeightMargin 99 | } 100 | 101 | // Title 102 | if self.titleLabel.text != nil { 103 | titleLabel.frame = CGRect(x: x, y: y, width: width, height: kTitleHeight) 104 | contentView.addSubview(titleLabel) 105 | y += kTitleHeight + kHeightMargin 106 | } 107 | 108 | // Subtitle 109 | if self.subTitleTextView.text.isEmpty == false { 110 | let subtitleString = subTitleTextView.text! as NSString 111 | let rect = subtitleString.boundingRect(with: CGSize(width: width, height: 0.0), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSFontAttributeName:subTitleTextView.font!], context: nil) 112 | textViewHeight = ceil(rect.size.height) + 10.0 113 | subTitleTextView.frame = CGRect(x: x, y: y, width: width, height: textViewHeight) 114 | contentView.addSubview(subTitleTextView) 115 | y += textViewHeight + kHeightMargin 116 | } 117 | 118 | var buttonRect:[CGRect] = [] 119 | for button in buttons { 120 | let string = button.title(for: UIControlState())! as NSString 121 | buttonRect.append(string.boundingRect(with: CGSize(width: width, height:0.0), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes:[NSFontAttributeName:button.titleLabel!.font], context:nil)) 122 | } 123 | 124 | var totalWidth: CGFloat = 0.0 125 | if buttons.count == 2 { 126 | totalWidth = buttonRect[0].size.width + buttonRect[1].size.width + kWidthMargin + 40.0 127 | } 128 | else{ 129 | totalWidth = buttonRect[0].size.width + 20.0 130 | } 131 | y += kHeightMargin 132 | var buttonX = (kContentWidth - totalWidth ) / 2.0 133 | for i in 0 ..< buttons.count { 134 | 135 | buttons[i].frame = CGRect(x: buttonX, y: y, width: buttonRect[i].size.width + 20.0, height: buttonRect[i].size.height + 10.0) 136 | buttonX = buttons[i].frame.origin.x + kWidthMargin + buttonRect[i].size.width + 20.0 137 | buttons[i].layer.cornerRadius = 5.0 138 | self.contentView.addSubview(buttons[i]) 139 | buttons[i].addTarget(self, action: #selector(SweetAlert.pressed(_:)), for: UIControlEvents.touchUpInside) 140 | 141 | } 142 | y += kHeightMargin + buttonRect[0].size.height + 10.0 143 | if y > kMaxHeight { 144 | let diff = y - kMaxHeight 145 | let sFrame = subTitleTextView.frame 146 | subTitleTextView.frame = CGRect(x: sFrame.origin.x, y: sFrame.origin.y, width: sFrame.width, height: sFrame.height - diff) 147 | 148 | for button in buttons { 149 | let bFrame = button.frame 150 | button.frame = CGRect(x: bFrame.origin.x, y: bFrame.origin.y - diff, width: bFrame.width, height: bFrame.height) 151 | } 152 | 153 | y = kMaxHeight 154 | } 155 | 156 | contentView.frame = CGRect(x: (mainScreenBounds.size.width - kContentWidth) / 2.0, y: (mainScreenBounds.size.height - y) / 2.0, width: kContentWidth, height: y) 157 | contentView.clipsToBounds = true 158 | } 159 | 160 | open func pressed(_ sender: UIButton!) { 161 | self.closeAlert(sender.tag) 162 | } 163 | 164 | open override func viewWillLayoutSubviews() { 165 | super.viewWillLayoutSubviews() 166 | var sz = UIScreen.main.bounds.size 167 | let sver = UIDevice.current.systemVersion as NSString 168 | let ver = sver.floatValue 169 | if ver < 8.0 { 170 | // iOS versions before 7.0 did not switch the width and height on device roration 171 | if UIInterfaceOrientationIsLandscape(UIApplication.shared.statusBarOrientation) { 172 | let ssz = sz 173 | sz = CGSize(width:ssz.height, height:ssz.width) 174 | } 175 | } 176 | self.resizeAndRelayout() 177 | } 178 | 179 | func closeAlert(_ buttonIndex:Int){ 180 | if userAction != nil { 181 | let isOtherButton = buttonIndex == 0 ? true: false 182 | SweetAlertContext.shouldNotAnimate = true 183 | userAction!(isOtherButton) 184 | SweetAlertContext.shouldNotAnimate = false 185 | } 186 | 187 | UIView.animate(withDuration: 0.5, delay: 0.0, options: UIViewAnimationOptions.curveEaseOut, animations: { () -> Void in 188 | self.view.alpha = 0.0 189 | }) { (Bool) -> Void in 190 | self.view.removeFromSuperview() 191 | self.cleanUpAlert() 192 | 193 | //Releasing strong refrence of itself. 194 | self.strongSelf = nil 195 | } 196 | } 197 | 198 | func cleanUpAlert() { 199 | 200 | if self.animatedView != nil { 201 | self.animatedView!.removeFromSuperview() 202 | self.animatedView = nil 203 | } 204 | self.contentView.removeFromSuperview() 205 | self.contentView = UIView() 206 | } 207 | 208 | open func showAlert(_ title: String) -> SweetAlert { 209 | _ = showAlert(title, subTitle: nil, style: .none) 210 | return self 211 | } 212 | 213 | open func showAlert(_ title: String, subTitle: String?, style: AlertStyle) -> SweetAlert { 214 | _ = showAlert(title, subTitle: subTitle, style: style, buttonTitle: "OK") 215 | return self 216 | 217 | } 218 | 219 | open func showAlert(_ title: String, subTitle: String?, style: AlertStyle,buttonTitle: String, action: ((_ isOtherButton: Bool) -> Void)? = nil) -> SweetAlert { 220 | _ = showAlert(title, subTitle: subTitle, style: style, buttonTitle: buttonTitle,buttonColor: UIColor.colorFromRGB(0xAEDEF4)) 221 | userAction = action 222 | return self 223 | } 224 | 225 | open func showAlert(_ title: String, subTitle: String?, style: AlertStyle,buttonTitle: String,buttonColor: UIColor,action: ((_ isOtherButton: Bool) -> Void)? = nil) -> SweetAlert { 226 | _ = showAlert(title, subTitle: subTitle, style: style, buttonTitle: buttonTitle,buttonColor: buttonColor,otherButtonTitle: 227 | nil) 228 | userAction = action 229 | return self 230 | } 231 | 232 | open func showAlert(_ title: String, subTitle: String?, style: AlertStyle,buttonTitle: String,buttonColor: UIColor,otherButtonTitle: 233 | String?, action: ((_ isOtherButton: Bool) -> Void)? = nil) -> SweetAlert { 234 | self.showAlert(title, subTitle: subTitle, style: style, buttonTitle: buttonTitle,buttonColor: buttonColor,otherButtonTitle: 235 | otherButtonTitle,otherButtonColor: UIColor.red) 236 | userAction = action 237 | return self 238 | } 239 | 240 | open func showAlert(_ title: String, subTitle: String?, style: AlertStyle,buttonTitle: String,buttonColor: UIColor,otherButtonTitle: 241 | String?, otherButtonColor: UIColor?,action: ((_ isOtherButton: Bool) -> Void)? = nil) { 242 | userAction = action 243 | let window: UIWindow = UIApplication.shared.keyWindow! 244 | window.addSubview(view) 245 | window.bringSubview(toFront: view) 246 | view.frame = window.bounds 247 | self.setupContentView() 248 | self.setupTitleLabel() 249 | self.setupSubtitleTextView() 250 | 251 | switch style { 252 | case .success: 253 | self.animatedView = SuccessAnimatedView() 254 | 255 | case .error: 256 | self.animatedView = CancelAnimatedView() 257 | 258 | case .warning: 259 | self.animatedView = InfoAnimatedView() 260 | 261 | case let .customImage(imageFile): 262 | if let image = UIImage(named: imageFile) { 263 | self.imageView = UIImageView(image: image) 264 | } 265 | case .none: 266 | self.animatedView = nil 267 | } 268 | 269 | self.titleLabel.text = title 270 | if subTitle != nil { 271 | self.subTitleTextView.text = subTitle 272 | } 273 | buttons = [] 274 | if buttonTitle.isEmpty == false { 275 | let button: UIButton = UIButton(type: UIButtonType.custom) 276 | button.setTitle(buttonTitle, for: UIControlState()) 277 | button.backgroundColor = buttonColor 278 | button.isUserInteractionEnabled = true 279 | button.tag = 0 280 | buttons.append(button) 281 | } 282 | 283 | if otherButtonTitle != nil && otherButtonTitle!.isEmpty == false { 284 | let button: UIButton = UIButton(type: UIButtonType.custom) 285 | button.setTitle(otherButtonTitle, for: UIControlState()) 286 | button.backgroundColor = otherButtonColor 287 | button.addTarget(self, action: #selector(SweetAlert.pressed(_:)), for: UIControlEvents.touchUpInside) 288 | button.tag = 1 289 | buttons.append(button) 290 | } 291 | 292 | resizeAndRelayout() 293 | if SweetAlertContext.shouldNotAnimate == true { 294 | //Do not animate Alert 295 | if self.animatedView != nil { 296 | self.animatedView!.animate() 297 | } 298 | } 299 | else { 300 | animateAlert() 301 | } 302 | } 303 | 304 | func animateAlert() { 305 | 306 | view.alpha = 0; 307 | UIView.animate(withDuration: 0.1, animations: { () -> Void in 308 | self.view.alpha = 1.0; 309 | }) 310 | 311 | let previousTransform = self.contentView.transform 312 | self.contentView.layer.transform = CATransform3DMakeScale(0.9, 0.9, 0.0); 313 | UIView.animate(withDuration: 0.2, animations: { () -> Void in 314 | self.contentView.layer.transform = CATransform3DMakeScale(1.1, 1.1, 0.0); 315 | }, completion: { (Bool) -> Void in 316 | UIView.animate(withDuration: 0.1, animations: { () -> Void in 317 | self.contentView.layer.transform = CATransform3DMakeScale(0.9, 0.9, 0.0); 318 | }, completion: { (Bool) -> Void in 319 | UIView.animate(withDuration: 0.1, animations: { () -> Void in 320 | self.contentView.layer.transform = CATransform3DMakeScale(1.0, 1.0, 0.0); 321 | if self.animatedView != nil { 322 | self.animatedView!.animate() 323 | } 324 | 325 | }, completion: { (Bool) -> Void in 326 | 327 | self.contentView.transform = previousTransform 328 | }) 329 | }) 330 | }) 331 | } 332 | 333 | fileprivate struct SweetAlertContext { 334 | static var shouldNotAnimate = false 335 | } 336 | } 337 | 338 | // MARK: - 339 | 340 | // MARK: Animatable Views 341 | 342 | class AnimatableView: UIView { 343 | func animate(){ 344 | print("Should overide by subclasss", terminator: "") 345 | } 346 | } 347 | 348 | class CancelAnimatedView: AnimatableView { 349 | 350 | var circleLayer = CAShapeLayer() 351 | var crossPathLayer = CAShapeLayer() 352 | 353 | override required init(frame: CGRect) { 354 | super.init(frame: frame) 355 | setupLayers() 356 | var t = CATransform3DIdentity; 357 | t.m34 = 1.0 / -500.0; 358 | t = CATransform3DRotate(t, CGFloat(90.0 * M_PI / 180.0), 1, 0, 0); 359 | circleLayer.transform = t 360 | crossPathLayer.opacity = 0.0 361 | } 362 | 363 | override func layoutSubviews() { 364 | setupLayers() 365 | } 366 | 367 | required init(coder aDecoder: NSCoder) { 368 | fatalError("init(coder:) has not been implemented") 369 | } 370 | 371 | fileprivate var outlineCircle: CGPath { 372 | let path = UIBezierPath() 373 | let startAngle: CGFloat = CGFloat((0) / 180.0 * M_PI) //0 374 | let endAngle: CGFloat = CGFloat((360) / 180.0 * M_PI) //360 375 | path.addArc(withCenter: CGPoint(x: self.frame.size.width/2.0, y: self.frame.size.width/2.0), radius: self.frame.size.width/2.0, startAngle: startAngle, endAngle: endAngle, clockwise: false) 376 | 377 | return path.cgPath 378 | } 379 | 380 | fileprivate var crossPath: CGPath { 381 | let path = UIBezierPath() 382 | let factor:CGFloat = self.frame.size.width / 5.0 383 | path.move(to: CGPoint(x: self.frame.size.height/2.0-factor,y: self.frame.size.height/2.0-factor)) 384 | path.addLine(to: CGPoint(x: self.frame.size.height/2.0+factor,y: self.frame.size.height/2.0+factor)) 385 | path.move(to: CGPoint(x: self.frame.size.height/2.0+factor,y: self.frame.size.height/2.0-factor)) 386 | path.addLine(to: CGPoint(x: self.frame.size.height/2.0-factor,y: self.frame.size.height/2.0+factor)) 387 | 388 | return path.cgPath 389 | } 390 | 391 | fileprivate func setupLayers() { 392 | circleLayer.path = outlineCircle 393 | circleLayer.fillColor = UIColor.clear.cgColor; 394 | circleLayer.strokeColor = UIColor.colorFromRGB(0xF27474).cgColor; 395 | circleLayer.lineCap = kCALineCapRound 396 | circleLayer.lineWidth = 4; 397 | circleLayer.frame = CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height) 398 | circleLayer.position = CGPoint(x: self.frame.size.width/2.0, y: self.frame.size.height/2.0) 399 | self.layer.addSublayer(circleLayer) 400 | 401 | crossPathLayer.path = crossPath 402 | crossPathLayer.fillColor = UIColor.clear.cgColor; 403 | crossPathLayer.strokeColor = UIColor.colorFromRGB(0xF27474).cgColor; 404 | crossPathLayer.lineCap = kCALineCapRound 405 | crossPathLayer.lineWidth = 4; 406 | crossPathLayer.frame = CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height) 407 | crossPathLayer.position = CGPoint(x: self.frame.size.width/2.0, y: self.frame.size.height/2.0) 408 | self.layer.addSublayer(crossPathLayer) 409 | 410 | } 411 | 412 | override func animate() { 413 | var t = CATransform3DIdentity; 414 | t.m34 = 1.0 / -500.0; 415 | t = CATransform3DRotate(t, CGFloat(90.0 * M_PI / 180.0), 1, 0, 0); 416 | 417 | var t2 = CATransform3DIdentity; 418 | t2.m34 = 1.0 / -500.0; 419 | t2 = CATransform3DRotate(t2, CGFloat(-M_PI), 1, 0, 0); 420 | 421 | let animation = CABasicAnimation(keyPath: "transform") 422 | let time = 0.3 423 | animation.duration = time; 424 | animation.fromValue = NSValue(caTransform3D: t) 425 | animation.toValue = NSValue(caTransform3D:t2) 426 | animation.isRemovedOnCompletion = false 427 | animation.fillMode = kCAFillModeForwards 428 | self.circleLayer.add(animation, forKey: "transform") 429 | 430 | 431 | var scale = CATransform3DIdentity; 432 | scale = CATransform3DScale(scale, 0.3, 0.3, 0) 433 | 434 | 435 | let crossAnimation = CABasicAnimation(keyPath: "transform") 436 | crossAnimation.duration = 0.3; 437 | crossAnimation.beginTime = CACurrentMediaTime() + time 438 | crossAnimation.fromValue = NSValue(caTransform3D: scale) 439 | crossAnimation.timingFunction = CAMediaTimingFunction(controlPoints: 0.25, 0.8, 0.7, 2.0) 440 | crossAnimation.toValue = NSValue(caTransform3D:CATransform3DIdentity) 441 | self.crossPathLayer.add(crossAnimation, forKey: "scale") 442 | 443 | let fadeInAnimation = CABasicAnimation(keyPath: "opacity") 444 | fadeInAnimation.duration = 0.3; 445 | fadeInAnimation.beginTime = CACurrentMediaTime() + time 446 | fadeInAnimation.fromValue = 0.3 447 | fadeInAnimation.toValue = 1.0 448 | fadeInAnimation.isRemovedOnCompletion = false 449 | fadeInAnimation.fillMode = kCAFillModeForwards 450 | self.crossPathLayer.add(fadeInAnimation, forKey: "opacity") 451 | } 452 | 453 | } 454 | 455 | class InfoAnimatedView: AnimatableView { 456 | 457 | var circleLayer = CAShapeLayer() 458 | var crossPathLayer = CAShapeLayer() 459 | 460 | override init(frame: CGRect) { 461 | super.init(frame: frame) 462 | setupLayers() 463 | } 464 | 465 | override func layoutSubviews() { 466 | setupLayers() 467 | } 468 | 469 | required init(coder aDecoder: NSCoder) { 470 | fatalError("init(coder:) has not been implemented") 471 | } 472 | 473 | var outlineCircle: CGPath { 474 | let path = UIBezierPath() 475 | let startAngle: CGFloat = CGFloat((0) / 180.0 * M_PI) //0 476 | let endAngle: CGFloat = CGFloat((360) / 180.0 * M_PI) //360 477 | path.addArc(withCenter: CGPoint(x: self.frame.size.width/2.0, y: self.frame.size.width/2.0), radius: self.frame.size.width/2.0, startAngle: startAngle, endAngle: endAngle, clockwise: false) 478 | 479 | let factor:CGFloat = self.frame.size.width / 1.5 480 | path.move(to: CGPoint(x: self.frame.size.width/2.0 , y: 15.0)) 481 | path.addLine(to: CGPoint(x: self.frame.size.width/2.0,y: factor)) 482 | path.move(to: CGPoint(x: self.frame.size.width/2.0,y: factor + 10.0)) 483 | path.addArc(withCenter: CGPoint(x: self.frame.size.width/2.0,y: factor + 10.0), radius: 1.0, startAngle: startAngle, endAngle: endAngle, clockwise: true) 484 | 485 | return path.cgPath 486 | } 487 | 488 | func setupLayers() { 489 | circleLayer.path = outlineCircle 490 | circleLayer.fillColor = UIColor.clear.cgColor; 491 | circleLayer.strokeColor = UIColor.colorFromRGB(0xF8D486).cgColor; 492 | circleLayer.lineCap = kCALineCapRound 493 | circleLayer.lineWidth = 4; 494 | circleLayer.frame = CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height) 495 | circleLayer.position = CGPoint(x: self.frame.size.width/2.0, y: self.frame.size.height/2.0) 496 | self.layer.addSublayer(circleLayer) 497 | } 498 | 499 | override func animate() { 500 | 501 | let colorAnimation = CABasicAnimation(keyPath:"strokeColor") 502 | colorAnimation.duration = 1.0; 503 | colorAnimation.repeatCount = HUGE 504 | colorAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) 505 | colorAnimation.autoreverses = true 506 | colorAnimation.fromValue = UIColor.colorFromRGB(0xF7D58B).cgColor 507 | colorAnimation.toValue = UIColor.colorFromRGB(0xF2A665).cgColor 508 | circleLayer.add(colorAnimation, forKey: "strokeColor") 509 | } 510 | } 511 | 512 | 513 | class SuccessAnimatedView: AnimatableView { 514 | 515 | var circleLayer = CAShapeLayer() 516 | var outlineLayer = CAShapeLayer() 517 | 518 | override init(frame: CGRect) { 519 | super.init(frame: frame) 520 | setupLayers() 521 | circleLayer.strokeStart = 0.0 522 | circleLayer.strokeEnd = 0.0 523 | } 524 | 525 | required init(coder aDecoder: NSCoder) { 526 | fatalError("init(coder:) has not been implemented") 527 | } 528 | 529 | override func layoutSubviews() { 530 | setupLayers() 531 | } 532 | 533 | 534 | var outlineCircle: CGPath { 535 | let path = UIBezierPath() 536 | let startAngle: CGFloat = CGFloat((0) / 180.0 * M_PI) //0 537 | let endAngle: CGFloat = CGFloat((360) / 180.0 * M_PI) //360 538 | path.addArc(withCenter: CGPoint(x: self.frame.size.width/2.0, y: self.frame.size.height/2.0), radius: self.frame.size.width/2.0, startAngle: startAngle, endAngle: endAngle, clockwise: false) 539 | return path.cgPath 540 | } 541 | 542 | var path: CGPath { 543 | let path = UIBezierPath() 544 | let startAngle:CGFloat = CGFloat((60) / 180.0 * M_PI) //60 545 | let endAngle:CGFloat = CGFloat((200) / 180.0 * M_PI) //190 546 | path.addArc(withCenter: CGPoint(x: self.frame.size.width/2.0, y: self.frame.size.height/2.0), radius: self.frame.size.width/2.0, startAngle: startAngle, endAngle: endAngle, clockwise: false) 547 | path.addLine(to: CGPoint(x: 36.0 - 10.0 ,y: 60.0 - 10.0)) 548 | path.addLine(to: CGPoint(x: 85.0 - 20.0, y: 30.0 - 20.0)) 549 | return path.cgPath 550 | } 551 | 552 | 553 | func setupLayers() { 554 | 555 | outlineLayer.position = CGPoint(x: 0, 556 | y: 0); 557 | outlineLayer.path = outlineCircle 558 | outlineLayer.fillColor = UIColor.clear.cgColor; 559 | outlineLayer.strokeColor = UIColor(red: 150.0/255.0, green: 216.0/255.0, blue: 115.0/255.0, alpha: 1.0).cgColor; 560 | outlineLayer.lineCap = kCALineCapRound 561 | outlineLayer.lineWidth = 4; 562 | outlineLayer.opacity = 0.1 563 | self.layer.addSublayer(outlineLayer) 564 | 565 | circleLayer.position = CGPoint(x: 0, 566 | y: 0); 567 | circleLayer.path = path 568 | circleLayer.fillColor = UIColor.clear.cgColor; 569 | circleLayer.strokeColor = UIColor(red: 150.0/255.0, green: 216.0/255.0, blue: 115.0/255.0, alpha: 1.0).cgColor; 570 | circleLayer.lineCap = kCALineCapRound 571 | circleLayer.lineWidth = 4; 572 | circleLayer.actions = [ 573 | "strokeStart": NSNull(), 574 | "strokeEnd": NSNull(), 575 | "transform": NSNull() 576 | ] 577 | self.layer.addSublayer(circleLayer) 578 | } 579 | 580 | override func animate() { 581 | let strokeStart = CABasicAnimation(keyPath: "strokeStart") 582 | let strokeEnd = CABasicAnimation(keyPath: "strokeEnd") 583 | let factor = 0.045 584 | strokeEnd.fromValue = 0.00 585 | strokeEnd.toValue = 0.93 586 | strokeEnd.duration = 10.0*factor 587 | let timing = CAMediaTimingFunction(controlPoints: 0.3, 0.6, 0.8, 1.2) 588 | strokeEnd.timingFunction = timing 589 | 590 | strokeStart.fromValue = 0.0 591 | strokeStart.toValue = 0.68 592 | strokeStart.duration = 7.0*factor 593 | strokeStart.beginTime = CACurrentMediaTime() + 3.0*factor 594 | strokeStart.fillMode = kCAFillModeBackwards 595 | strokeStart.timingFunction = timing 596 | circleLayer.strokeStart = 0.68 597 | circleLayer.strokeEnd = 0.93 598 | self.circleLayer.add(strokeEnd, forKey: "strokeEnd") 599 | self.circleLayer.add(strokeStart, forKey: "strokeStart") 600 | } 601 | 602 | } 603 | 604 | extension UIColor { 605 | class func colorFromRGB(_ rgbValue: UInt) -> UIColor { 606 | return UIColor( 607 | red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0, 608 | green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0, 609 | blue: CGFloat(rgbValue & 0x0000FF) / 255.0, 610 | alpha: CGFloat(1.0) 611 | ) 612 | } 613 | } 614 | 615 | -------------------------------------------------------------------------------- /SweetAlert/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // SweetAlert 4 | // 5 | // Created by Codester on 11/3/14. 6 | // Copyright (c) 2014 Codester. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | var alert = SweetAlert() 14 | override func viewDidLoad() { 15 | super.viewDidLoad() 16 | // Do any additional setup after loading the view, typically from a nib. 17 | self.view.backgroundColor = UIColor(red: 242.0/255.0, green: 244.0/255.0, blue: 246.0/255.0, alpha: 1.0) 18 | } 19 | 20 | override func viewDidAppear(_ animated: Bool) { 21 | 22 | 23 | } 24 | 25 | override func didReceiveMemoryWarning() { 26 | super.didReceiveMemoryWarning() 27 | // Dispose of any resources that can be recreated. 28 | } 29 | 30 | 31 | @IBAction func aBasicMessageAlert(_ sender: AnyObject) { 32 | _ = SweetAlert().showAlert("Here's a message!") 33 | } 34 | 35 | 36 | @IBAction func subtitleAlert(_ sender: AnyObject) { 37 | 38 | _ = SweetAlert().showAlert("Here's a message!", subTitle: "It's pretty, isn't it?", style: AlertStyle.none) 39 | } 40 | 41 | @IBAction func sucessAlert(_ sender: AnyObject) { 42 | _ = SweetAlert().showAlert("Good job!", subTitle: "You clicked the button!", style: AlertStyle.success) 43 | } 44 | 45 | @IBAction func warningAlert(_ sender: AnyObject) { 46 | _ = SweetAlert().showAlert("Are you sure?", subTitle: "You file will permanently delete!", style: AlertStyle.warning, buttonTitle:"Cancel", buttonColor:UIColor.colorFromRGB(0xD0D0D0) , otherButtonTitle: "Yes, delete it!", otherButtonColor: UIColor.colorFromRGB(0xDD6B55)) { (isOtherButton) -> Void in 47 | if isOtherButton == true { 48 | 49 | print("Cancel Button Pressed", terminator: "") 50 | } 51 | else { 52 | _ = SweetAlert().showAlert("Deleted!", subTitle: "Your imaginary file has been deleted!", style: AlertStyle.success) 53 | } 54 | } 55 | } 56 | 57 | @IBAction func cancelAndConfirm(_ sender: AnyObject) { 58 | _ = SweetAlert().showAlert("Are you sure?", subTitle: "You file will permanently delete!", style: AlertStyle.warning, buttonTitle:"No, cancel plx!", buttonColor:UIColor.colorFromRGB(0xD0D0D0) , otherButtonTitle: "Yes, delete it!", otherButtonColor: UIColor.colorFromRGB(0xDD6B55)) { (isOtherButton) -> Void in 59 | if isOtherButton == true { 60 | 61 | _ = SweetAlert().showAlert("Cancelled!", subTitle: "Your imaginary file is safe", style: AlertStyle.error) 62 | } 63 | else { 64 | _ = SweetAlert().showAlert("Deleted!", subTitle: "Your imaginary file has been deleted!", style: AlertStyle.success) 65 | } 66 | } 67 | 68 | } 69 | 70 | @IBAction func customIconAlert(_ sender: AnyObject) { 71 | _ = SweetAlert().showAlert("Sweet!", subTitle: "Here's a custom image.", style: AlertStyle.customImag(imageFile: "thumb.jpg")) 72 | } 73 | 74 | } 75 | 76 | -------------------------------------------------------------------------------- /SweetAlert/logo_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codestergit/SweetAlert-iOS/b97db81e4d9cf78e0e41af6e2bbc0ecac59dd120/SweetAlert/logo_big.png -------------------------------------------------------------------------------- /SweetAlertiOS.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codestergit/SweetAlert-iOS/b97db81e4d9cf78e0e41af6e2bbc0ecac59dd120/SweetAlertiOS.gif -------------------------------------------------------------------------------- /thumb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codestergit/SweetAlert-iOS/b97db81e4d9cf78e0e41af6e2bbc0ecac59dd120/thumb.jpg --------------------------------------------------------------------------------