├── .gitignore ├── .swiftpm └── xcode │ └── package.xcworkspace │ └── contents.xcworkspacedata ├── Example └── SwiftMessageBarExample │ ├── SwiftMessageBarExample.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── SwiftMessageBarExample │ ├── AppDelegate.swift │ ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard │ ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Info.plist │ └── ViewController.swift ├── LICENSE ├── Package.swift ├── README.md ├── SwiftMessageBar.podspec ├── SwiftMessageBar.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcshareddata │ └── xcschemes │ └── SwiftMessageBar.xcscheme ├── SwiftMessageBar.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── SwiftMessageBar ├── Info.plist ├── Message.swift ├── MessageType.swift ├── Queue.swift ├── Resources │ ├── icon-error.png │ ├── icon-error@2x.png │ ├── icon-error@3x.png │ ├── icon-info.png │ ├── icon-info@2x.png │ ├── icon-info@3x.png │ ├── icon-success@1x.png │ ├── icon-success@2x.png │ └── icon-success@3x.png ├── SwiftMessageBar.h └── SwiftMessageBar.swift └── SwiftMessageBarTests ├── Info.plist └── QueueTests.swift /.gitignore: -------------------------------------------------------------------------------- 1 | ### https://raw.github.com/github/gitignore/c70e357bfde8a842faca6574f1dfc6ad416dfc2a/Global/Xcode.gitignore 2 | 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.xcuserstate 17 | 18 | 19 | ### https://raw.github.com/github/gitignore/c70e357bfde8a842faca6574f1dfc6ad416dfc2a/Global/JetBrains.gitignore 20 | 21 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm 22 | 23 | ## Directory-based project format 24 | .idea/ 25 | # if you remove the above rule, at least ignore user-specific stuff: 26 | # .idea/workspace.xml 27 | # .idea/tasks.xml 28 | # and these sensitive or high-churn files: 29 | # .idea/dataSources.ids 30 | # .idea/dataSources.xml 31 | # .idea/sqlDataSources.xml 32 | # .idea/dynamic.xml 33 | 34 | ## File-based project format 35 | *.ipr 36 | *.iml 37 | *.iws 38 | 39 | ## Additional for IntelliJ 40 | out/ 41 | 42 | # generated by mpeltonen/sbt-idea plugin 43 | .idea_modules/ 44 | 45 | # generated by JIRA plugin 46 | atlassian-ide-plugin.xml 47 | 48 | # generated by Crashlytics plugin (for Android Studio and Intellij) 49 | com_crashlytics_export_strings.xml 50 | 51 | 52 | -------------------------------------------------------------------------------- /.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/SwiftMessageBarExample/SwiftMessageBarExample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | F2AB590F1B28B3B3001DCC74 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2AB590E1B28B3B3001DCC74 /* AppDelegate.swift */; }; 11 | F2AB59111B28B3B3001DCC74 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2AB59101B28B3B3001DCC74 /* ViewController.swift */; }; 12 | F2AB59141B28B3B3001DCC74 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F2AB59121B28B3B3001DCC74 /* Main.storyboard */; }; 13 | F2AB59161B28B3B3001DCC74 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F2AB59151B28B3B3001DCC74 /* Images.xcassets */; }; 14 | F2AB59191B28B3B3001DCC74 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = F2AB59171B28B3B3001DCC74 /* LaunchScreen.xib */; }; 15 | /* End PBXBuildFile section */ 16 | 17 | /* Begin PBXContainerItemProxy section */ 18 | F2AB59331B28B3C9001DCC74 /* PBXContainerItemProxy */ = { 19 | isa = PBXContainerItemProxy; 20 | containerPortal = F2AB592E1B28B3C9001DCC74 /* SwiftMessageBar.xcodeproj */; 21 | proxyType = 2; 22 | remoteGlobalIDString = F2AB58E21B28B33C001DCC74; 23 | remoteInfo = SwiftMessageBar; 24 | }; 25 | F2AB59371B28B3D1001DCC74 /* PBXContainerItemProxy */ = { 26 | isa = PBXContainerItemProxy; 27 | containerPortal = F2AB592E1B28B3C9001DCC74 /* SwiftMessageBar.xcodeproj */; 28 | proxyType = 1; 29 | remoteGlobalIDString = F2AB58E11B28B33C001DCC74; 30 | remoteInfo = SwiftMessageBar; 31 | }; 32 | /* End PBXContainerItemProxy section */ 33 | 34 | /* Begin PBXFileReference section */ 35 | F2AB59091B28B3B3001DCC74 /* SwiftMessageBarExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftMessageBarExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 36 | F2AB590D1B28B3B3001DCC74 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 37 | F2AB590E1B28B3B3001DCC74 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 38 | F2AB59101B28B3B3001DCC74 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 39 | F2AB59131B28B3B3001DCC74 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 40 | F2AB59151B28B3B3001DCC74 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 41 | F2AB59181B28B3B3001DCC74 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 42 | F2AB592E1B28B3C9001DCC74 /* SwiftMessageBar.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SwiftMessageBar.xcodeproj; path = ../../SwiftMessageBar.xcodeproj; sourceTree = ""; }; 43 | /* End PBXFileReference section */ 44 | 45 | /* Begin PBXFrameworksBuildPhase section */ 46 | F2AB59061B28B3B3001DCC74 /* Frameworks */ = { 47 | isa = PBXFrameworksBuildPhase; 48 | buildActionMask = 2147483647; 49 | files = ( 50 | ); 51 | runOnlyForDeploymentPostprocessing = 0; 52 | }; 53 | /* End PBXFrameworksBuildPhase section */ 54 | 55 | /* Begin PBXGroup section */ 56 | F2AB59001B28B3B3001DCC74 = { 57 | isa = PBXGroup; 58 | children = ( 59 | F2AB592E1B28B3C9001DCC74 /* SwiftMessageBar.xcodeproj */, 60 | F2AB590B1B28B3B3001DCC74 /* SwiftMessageBarExample */, 61 | F2AB590A1B28B3B3001DCC74 /* Products */, 62 | ); 63 | indentWidth = 2; 64 | sourceTree = ""; 65 | tabWidth = 2; 66 | }; 67 | F2AB590A1B28B3B3001DCC74 /* Products */ = { 68 | isa = PBXGroup; 69 | children = ( 70 | F2AB59091B28B3B3001DCC74 /* SwiftMessageBarExample.app */, 71 | ); 72 | name = Products; 73 | sourceTree = ""; 74 | }; 75 | F2AB590B1B28B3B3001DCC74 /* SwiftMessageBarExample */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | F2AB590E1B28B3B3001DCC74 /* AppDelegate.swift */, 79 | F2AB59101B28B3B3001DCC74 /* ViewController.swift */, 80 | F2AB59121B28B3B3001DCC74 /* Main.storyboard */, 81 | F2AB59151B28B3B3001DCC74 /* Images.xcassets */, 82 | F2AB59171B28B3B3001DCC74 /* LaunchScreen.xib */, 83 | F2AB590C1B28B3B3001DCC74 /* Supporting Files */, 84 | ); 85 | path = SwiftMessageBarExample; 86 | sourceTree = ""; 87 | }; 88 | F2AB590C1B28B3B3001DCC74 /* Supporting Files */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | F2AB590D1B28B3B3001DCC74 /* Info.plist */, 92 | ); 93 | name = "Supporting Files"; 94 | sourceTree = ""; 95 | }; 96 | F2AB592F1B28B3C9001DCC74 /* Products */ = { 97 | isa = PBXGroup; 98 | children = ( 99 | F2AB59341B28B3C9001DCC74 /* SwiftMessageBar.framework */, 100 | ); 101 | name = Products; 102 | sourceTree = ""; 103 | }; 104 | /* End PBXGroup section */ 105 | 106 | /* Begin PBXNativeTarget section */ 107 | F2AB59081B28B3B3001DCC74 /* SwiftMessageBarExample */ = { 108 | isa = PBXNativeTarget; 109 | buildConfigurationList = F2AB59281B28B3B3001DCC74 /* Build configuration list for PBXNativeTarget "SwiftMessageBarExample" */; 110 | buildPhases = ( 111 | F2AB59051B28B3B3001DCC74 /* Sources */, 112 | F2AB59061B28B3B3001DCC74 /* Frameworks */, 113 | F2AB59071B28B3B3001DCC74 /* Resources */, 114 | ); 115 | buildRules = ( 116 | ); 117 | dependencies = ( 118 | F2AB59381B28B3D1001DCC74 /* PBXTargetDependency */, 119 | ); 120 | name = SwiftMessageBarExample; 121 | productName = SwiftMessageBarExample; 122 | productReference = F2AB59091B28B3B3001DCC74 /* SwiftMessageBarExample.app */; 123 | productType = "com.apple.product-type.application"; 124 | }; 125 | /* End PBXNativeTarget section */ 126 | 127 | /* Begin PBXProject section */ 128 | F2AB59011B28B3B3001DCC74 /* Project object */ = { 129 | isa = PBXProject; 130 | attributes = { 131 | LastSwiftUpdateCheck = 0700; 132 | LastUpgradeCheck = 1200; 133 | ORGANIZATIONNAME = Schnaub; 134 | TargetAttributes = { 135 | F2AB59081B28B3B3001DCC74 = { 136 | CreatedOnToolsVersion = 6.3.2; 137 | LastSwiftMigration = 1020; 138 | }; 139 | }; 140 | }; 141 | buildConfigurationList = F2AB59041B28B3B3001DCC74 /* Build configuration list for PBXProject "SwiftMessageBarExample" */; 142 | compatibilityVersion = "Xcode 3.2"; 143 | developmentRegion = en; 144 | hasScannedForEncodings = 0; 145 | knownRegions = ( 146 | en, 147 | Base, 148 | ); 149 | mainGroup = F2AB59001B28B3B3001DCC74; 150 | productRefGroup = F2AB590A1B28B3B3001DCC74 /* Products */; 151 | projectDirPath = ""; 152 | projectReferences = ( 153 | { 154 | ProductGroup = F2AB592F1B28B3C9001DCC74 /* Products */; 155 | ProjectRef = F2AB592E1B28B3C9001DCC74 /* SwiftMessageBar.xcodeproj */; 156 | }, 157 | ); 158 | projectRoot = ""; 159 | targets = ( 160 | F2AB59081B28B3B3001DCC74 /* SwiftMessageBarExample */, 161 | ); 162 | }; 163 | /* End PBXProject section */ 164 | 165 | /* Begin PBXReferenceProxy section */ 166 | F2AB59341B28B3C9001DCC74 /* SwiftMessageBar.framework */ = { 167 | isa = PBXReferenceProxy; 168 | fileType = wrapper.framework; 169 | path = SwiftMessageBar.framework; 170 | remoteRef = F2AB59331B28B3C9001DCC74 /* PBXContainerItemProxy */; 171 | sourceTree = BUILT_PRODUCTS_DIR; 172 | }; 173 | /* End PBXReferenceProxy section */ 174 | 175 | /* Begin PBXResourcesBuildPhase section */ 176 | F2AB59071B28B3B3001DCC74 /* Resources */ = { 177 | isa = PBXResourcesBuildPhase; 178 | buildActionMask = 2147483647; 179 | files = ( 180 | F2AB59141B28B3B3001DCC74 /* Main.storyboard in Resources */, 181 | F2AB59191B28B3B3001DCC74 /* LaunchScreen.xib in Resources */, 182 | F2AB59161B28B3B3001DCC74 /* Images.xcassets in Resources */, 183 | ); 184 | runOnlyForDeploymentPostprocessing = 0; 185 | }; 186 | /* End PBXResourcesBuildPhase section */ 187 | 188 | /* Begin PBXSourcesBuildPhase section */ 189 | F2AB59051B28B3B3001DCC74 /* Sources */ = { 190 | isa = PBXSourcesBuildPhase; 191 | buildActionMask = 2147483647; 192 | files = ( 193 | F2AB59111B28B3B3001DCC74 /* ViewController.swift in Sources */, 194 | F2AB590F1B28B3B3001DCC74 /* AppDelegate.swift in Sources */, 195 | ); 196 | runOnlyForDeploymentPostprocessing = 0; 197 | }; 198 | /* End PBXSourcesBuildPhase section */ 199 | 200 | /* Begin PBXTargetDependency section */ 201 | F2AB59381B28B3D1001DCC74 /* PBXTargetDependency */ = { 202 | isa = PBXTargetDependency; 203 | name = SwiftMessageBar; 204 | targetProxy = F2AB59371B28B3D1001DCC74 /* PBXContainerItemProxy */; 205 | }; 206 | /* End PBXTargetDependency section */ 207 | 208 | /* Begin PBXVariantGroup section */ 209 | F2AB59121B28B3B3001DCC74 /* Main.storyboard */ = { 210 | isa = PBXVariantGroup; 211 | children = ( 212 | F2AB59131B28B3B3001DCC74 /* Base */, 213 | ); 214 | name = Main.storyboard; 215 | sourceTree = ""; 216 | }; 217 | F2AB59171B28B3B3001DCC74 /* LaunchScreen.xib */ = { 218 | isa = PBXVariantGroup; 219 | children = ( 220 | F2AB59181B28B3B3001DCC74 /* Base */, 221 | ); 222 | name = LaunchScreen.xib; 223 | sourceTree = ""; 224 | }; 225 | /* End PBXVariantGroup section */ 226 | 227 | /* Begin XCBuildConfiguration section */ 228 | F2AB59261B28B3B3001DCC74 /* Debug */ = { 229 | isa = XCBuildConfiguration; 230 | buildSettings = { 231 | ALWAYS_SEARCH_USER_PATHS = NO; 232 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 233 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 234 | CLANG_CXX_LIBRARY = "libc++"; 235 | CLANG_ENABLE_MODULES = YES; 236 | CLANG_ENABLE_OBJC_ARC = YES; 237 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 238 | CLANG_WARN_BOOL_CONVERSION = YES; 239 | CLANG_WARN_COMMA = YES; 240 | CLANG_WARN_CONSTANT_CONVERSION = YES; 241 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 242 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 243 | CLANG_WARN_EMPTY_BODY = YES; 244 | CLANG_WARN_ENUM_CONVERSION = YES; 245 | CLANG_WARN_INFINITE_RECURSION = YES; 246 | CLANG_WARN_INT_CONVERSION = YES; 247 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 248 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 249 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 250 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 251 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 252 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 253 | CLANG_WARN_STRICT_PROTOTYPES = YES; 254 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 255 | CLANG_WARN_UNREACHABLE_CODE = YES; 256 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 257 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 258 | COPY_PHASE_STRIP = NO; 259 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 260 | ENABLE_STRICT_OBJC_MSGSEND = YES; 261 | ENABLE_TESTABILITY = YES; 262 | GCC_C_LANGUAGE_STANDARD = gnu99; 263 | GCC_DYNAMIC_NO_PIC = NO; 264 | GCC_NO_COMMON_BLOCKS = YES; 265 | GCC_OPTIMIZATION_LEVEL = 0; 266 | GCC_PREPROCESSOR_DEFINITIONS = ( 267 | "DEBUG=1", 268 | "$(inherited)", 269 | ); 270 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 271 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 272 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 273 | GCC_WARN_UNDECLARED_SELECTOR = YES; 274 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 275 | GCC_WARN_UNUSED_FUNCTION = YES; 276 | GCC_WARN_UNUSED_VARIABLE = YES; 277 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 278 | MTL_ENABLE_DEBUG_INFO = YES; 279 | ONLY_ACTIVE_ARCH = YES; 280 | SDKROOT = iphoneos; 281 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 282 | SWIFT_VERSION = 4.0; 283 | }; 284 | name = Debug; 285 | }; 286 | F2AB59271B28B3B3001DCC74 /* Release */ = { 287 | isa = XCBuildConfiguration; 288 | buildSettings = { 289 | ALWAYS_SEARCH_USER_PATHS = NO; 290 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 291 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 292 | CLANG_CXX_LIBRARY = "libc++"; 293 | CLANG_ENABLE_MODULES = YES; 294 | CLANG_ENABLE_OBJC_ARC = YES; 295 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 296 | CLANG_WARN_BOOL_CONVERSION = YES; 297 | CLANG_WARN_COMMA = YES; 298 | CLANG_WARN_CONSTANT_CONVERSION = YES; 299 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 300 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 301 | CLANG_WARN_EMPTY_BODY = YES; 302 | CLANG_WARN_ENUM_CONVERSION = YES; 303 | CLANG_WARN_INFINITE_RECURSION = YES; 304 | CLANG_WARN_INT_CONVERSION = YES; 305 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 306 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 307 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 308 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 309 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 310 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 311 | CLANG_WARN_STRICT_PROTOTYPES = YES; 312 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 313 | CLANG_WARN_UNREACHABLE_CODE = YES; 314 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 315 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 316 | COPY_PHASE_STRIP = NO; 317 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 318 | ENABLE_NS_ASSERTIONS = NO; 319 | ENABLE_STRICT_OBJC_MSGSEND = YES; 320 | GCC_C_LANGUAGE_STANDARD = gnu99; 321 | GCC_NO_COMMON_BLOCKS = YES; 322 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 323 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 324 | GCC_WARN_UNDECLARED_SELECTOR = YES; 325 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 326 | GCC_WARN_UNUSED_FUNCTION = YES; 327 | GCC_WARN_UNUSED_VARIABLE = YES; 328 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 329 | MTL_ENABLE_DEBUG_INFO = NO; 330 | SDKROOT = iphoneos; 331 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 332 | SWIFT_VERSION = 4.0; 333 | VALIDATE_PRODUCT = YES; 334 | }; 335 | name = Release; 336 | }; 337 | F2AB59291B28B3B3001DCC74 /* Debug */ = { 338 | isa = XCBuildConfiguration; 339 | buildSettings = { 340 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 341 | INFOPLIST_FILE = SwiftMessageBarExample/Info.plist; 342 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 343 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 344 | PRODUCT_BUNDLE_IDENTIFIER = "com.schnaub.$(PRODUCT_NAME:rfc1034identifier)"; 345 | PRODUCT_NAME = "$(TARGET_NAME)"; 346 | SWIFT_VERSION = 5.0; 347 | }; 348 | name = Debug; 349 | }; 350 | F2AB592A1B28B3B3001DCC74 /* Release */ = { 351 | isa = XCBuildConfiguration; 352 | buildSettings = { 353 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 354 | INFOPLIST_FILE = SwiftMessageBarExample/Info.plist; 355 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 356 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 357 | PRODUCT_BUNDLE_IDENTIFIER = "com.schnaub.$(PRODUCT_NAME:rfc1034identifier)"; 358 | PRODUCT_NAME = "$(TARGET_NAME)"; 359 | SWIFT_VERSION = 5.0; 360 | }; 361 | name = Release; 362 | }; 363 | /* End XCBuildConfiguration section */ 364 | 365 | /* Begin XCConfigurationList section */ 366 | F2AB59041B28B3B3001DCC74 /* Build configuration list for PBXProject "SwiftMessageBarExample" */ = { 367 | isa = XCConfigurationList; 368 | buildConfigurations = ( 369 | F2AB59261B28B3B3001DCC74 /* Debug */, 370 | F2AB59271B28B3B3001DCC74 /* Release */, 371 | ); 372 | defaultConfigurationIsVisible = 0; 373 | defaultConfigurationName = Release; 374 | }; 375 | F2AB59281B28B3B3001DCC74 /* Build configuration list for PBXNativeTarget "SwiftMessageBarExample" */ = { 376 | isa = XCConfigurationList; 377 | buildConfigurations = ( 378 | F2AB59291B28B3B3001DCC74 /* Debug */, 379 | F2AB592A1B28B3B3001DCC74 /* Release */, 380 | ); 381 | defaultConfigurationIsVisible = 0; 382 | defaultConfigurationName = Release; 383 | }; 384 | /* End XCConfigurationList section */ 385 | }; 386 | rootObject = F2AB59011B28B3B3001DCC74 /* Project object */; 387 | } 388 | -------------------------------------------------------------------------------- /Example/SwiftMessageBarExample/SwiftMessageBarExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/SwiftMessageBarExample/SwiftMessageBarExample/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015 Schnaub. All rights reserved. 3 | // 4 | 5 | import UIKit 6 | 7 | @main 8 | class AppDelegate: UIResponder, UIApplicationDelegate { 9 | 10 | var window: UIWindow? 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Example/SwiftMessageBarExample/SwiftMessageBarExample/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 | -------------------------------------------------------------------------------- /Example/SwiftMessageBarExample/SwiftMessageBarExample/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 | 33 | 40 | 49 | 58 | 68 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /Example/SwiftMessageBarExample/SwiftMessageBarExample/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 | } -------------------------------------------------------------------------------- /Example/SwiftMessageBarExample/SwiftMessageBarExample/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 | -------------------------------------------------------------------------------- /Example/SwiftMessageBarExample/SwiftMessageBarExample/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015 Schnaub. All rights reserved. 3 | // 4 | 5 | import UIKit 6 | import SwiftMessageBar 7 | 8 | final class ViewController: UIViewController { 9 | 10 | private var uuid: UUID? 11 | 12 | override func viewDidLoad() { 13 | super.viewDidLoad() 14 | let messageBarConfig = SwiftMessageBar.Config(successColor: .orange, isStatusBarHidden: true) 15 | SwiftMessageBar.setSharedConfig(messageBarConfig) 16 | } 17 | 18 | @IBAction private func showSuccess() { 19 | let message = "A really long message can go here, to provide a description for the user" 20 | uuid = SwiftMessageBar.showMessage( 21 | withTitle: nil, 22 | message: message, 23 | type: .success, 24 | duration: 3, 25 | dismiss: false 26 | ) { 27 | print("Dismiss callback") 28 | } 29 | } 30 | 31 | @IBAction private func showError() { 32 | let message = "A really long message can go here, to provide a description for the user" 33 | uuid = SwiftMessageBar.showMessage( 34 | withTitle: "Error", 35 | message: message, 36 | type: .error, 37 | duration: 3 38 | ) { 39 | print("Dismiss callback") 40 | } 41 | } 42 | 43 | @IBAction private func showInfo() { 44 | let message = "A really long message can go here, to provide a description for the user" 45 | uuid = SwiftMessageBar.showMessage(withTitle: "Info", message: message, type: .info, duration: 3) { 46 | print("Dismiss callback") 47 | } 48 | } 49 | 50 | @IBAction private func clearAll() { 51 | SwiftMessageBar.sharedMessageBar.cancelAll(force: true) 52 | uuid = nil 53 | } 54 | 55 | @IBAction private func clearCurrent() { 56 | if let id = uuid { 57 | SwiftMessageBar.sharedMessageBar.cancel(withId: id) 58 | uuid = nil 59 | } 60 | } 61 | 62 | @IBAction private func showSuccessWithAccesoryView() { 63 | let message = "A really long message can go here, to provide a description for the user" 64 | let button = UIButton(type: .roundedRect, primaryAction: UIAction { _ in 65 | print("Button tapped") 66 | }) 67 | button.contentEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5) 68 | button.setContentHuggingPriority(.required, for: .horizontal) 69 | button.setTitle("Open", for: .normal) 70 | button.tintColor = .orange 71 | button.backgroundColor = .white 72 | button.layer.cornerRadius = 6 73 | 74 | uuid = SwiftMessageBar.showMessage( 75 | withTitle: nil, 76 | message: message, 77 | type: .success, 78 | duration: 3, 79 | dismiss: false, 80 | accessoryView: button 81 | ) { 82 | print("Dismiss callback") 83 | } 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Jan Gorman 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. -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.9 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "SwiftMessageBar", 7 | platforms: [ 8 | .iOS(.v12), 9 | ], 10 | products: [ 11 | .library( 12 | name: "SwiftMessageBar", 13 | targets: ["SwiftMessageBar"] 14 | ), 15 | ], 16 | targets: [ 17 | .target( 18 | name: "SwiftMessageBar", 19 | path: "SwiftMessageBar", 20 | resources: [ 21 | .process("Resources") 22 | ] 23 | ), 24 | .testTarget( 25 | name: "SwiftMessageBarTests", 26 | dependencies: ["SwiftMessageBar"], 27 | path: "SwiftMessageBarTests" 28 | ), 29 | ] 30 | ) 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 2 | [![Version](https://img.shields.io/cocoapods/v/SwiftMessageBar.svg?style=flat)](http://cocoapods.org/pods/SwiftMessageBar) 3 | [![License](https://img.shields.io/cocoapods/l/SwiftMessageBar.svg?style=flat)](http://cocoapods.org/pods/SwiftMessageBar) 4 | [![Platform](https://img.shields.io/cocoapods/p/SwiftMessageBar.svg?style=flat)](http://cocoapods.org/pods/SwiftMessageBar) 5 | 6 | # SwiftMessageBar 7 | 8 | An iOS message bar, written in Swift 9 | 10 | ![image](https://www.dropbox.com/s/m0vcdcor6hw4e7a/SwiftMessageBar-2016.06.08.gif?raw=1) 11 | 12 | ## Requirements 13 | 14 | - iOS 9.0+ 15 | - Swift 5 16 | - Xcode 10.2+ 17 | 18 | ## Installation 19 | 20 | You can use [Carthage](https://github.com/Carthage/Carthage): 21 | 22 | ```ogdl 23 | github "JanGorman/SwiftMessageBar" 24 | ``` 25 | 26 | or [CocoaPods](http://cocoapods.org): 27 | 28 | ```ruby 29 | pod 'SwiftMessageBar' 30 | ``` 31 | 32 | ## Usage 33 | 34 | The included sample code shows how to use the message bar. There are three different message types: 35 | 36 | ```swift 37 | enum MessageType { 38 | case error, success, info 39 | } 40 | ``` 41 | 42 | To display a message: 43 | 44 | ```swift 45 | import SwiftMessageBar 46 | 47 | @IBAction func showSuccess(sender: AnyObject) { 48 | SwiftMessageBar.showMessage(withTitle: "Success", message: "The Message Body", type: .success) 49 | } 50 | ``` 51 | 52 | You can customize the duration of each message and also pass in a tap handler closure that is executed when a user taps on the message. 53 | 54 | To customize the look of the messages, create a custom `Config` and set it on the shared messagebar. You can adjust colors, fonts as well as custom images. `Config` comes with a Builder class for easy configuration. For example: 55 | 56 | ```swift 57 | let config = SwiftMessageBar.Config.Builder() 58 | .withErrorColor(.green) 59 | .withSuccessColor(.red) 60 | .withTitleFont(.boldSystemFont(ofSize: 30)) 61 | .withMessageFont(.systemFont(ofSize: 17)) 62 | .build() 63 | SwiftMessageBar.setSharedConfig(config) 64 | ``` 65 | 66 | ### Haptic Feedback 67 | 68 | Per default SwiftMessageBar provides the user with haptic feedback using [UINotificationFeedbackGenerator](https://developer.apple.com/documentation/uikit/uinotificationfeedbackgenerator). You can opt out of this behaviour by disabling it in the configuration: 69 | 70 | ```swift 71 | let config = SwiftMessageBar.Config.Builder() 72 | .withHapticFeedbackEnabled(false) 73 | .build() 74 | SwiftMessageBar.setSharedConfig(config) 75 | ``` 76 | 77 | ## Licence 78 | 79 | SwiftMessageBar is released under the MIT license. See LICENSE for details 80 | -------------------------------------------------------------------------------- /SwiftMessageBar.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = 'SwiftMessageBar' 4 | s.version = '5.6.2' 5 | s.summary = 'A Swift Message Bar' 6 | s.swift_version = '5.0' 7 | 8 | s.description = <<-DESC 9 | A longer description of SwiftMessageBar in Markdown format. 10 | 11 | * Think: Why did you write this? What is the focus? What does it do? 12 | * CocoaPods will be using this to generate tags, and improve search results. 13 | * Try to keep it short, snappy and to the point. 14 | * Finally, don't worry about the indent, CocoaPods strips it! 15 | DESC 16 | 17 | s.homepage = 'https://github.com/JanGorman/SwiftMessageBar' 18 | s.license = 'MIT' 19 | s.authors = { 'Jan Gorman' => 'https://github.com/JanGorman/', 'Ramy Kfoury' => 'https://github.com/ramy-kfoury/' } 20 | s.social_media_url = 'http://twitter.com/JanGorman' 21 | 22 | s.platform = :ios, '12.0' 23 | 24 | s.source = { :git => 'https://github.com/JanGorman/SwiftMessageBar.git', :tag => s.version } 25 | 26 | s.source_files = 'SwiftMessageBar/*.swift' 27 | s.resources = 'SwiftMessageBar/*.png' 28 | 29 | end 30 | -------------------------------------------------------------------------------- /SwiftMessageBar.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 77BBDF7E209705E600BDED60 /* DeviceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77BBDF7D209705E600BDED60 /* DeviceType.swift */; }; 11 | 77E9E14E205167C100E157F5 /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77E9E14D205167C100E157F5 /* Queue.swift */; }; 12 | 77EBFCB420519D5000AFE1F9 /* MessageType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77EBFCB320519D5000AFE1F9 /* MessageType.swift */; }; 13 | B5501F142AF22912009AE3D3 /* icon-info@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = B5501F0B2AF22912009AE3D3 /* icon-info@3x.png */; }; 14 | B5501F152AF22912009AE3D3 /* icon-success@1x.png in Resources */ = {isa = PBXBuildFile; fileRef = B5501F0C2AF22912009AE3D3 /* icon-success@1x.png */; }; 15 | B5501F162AF22912009AE3D3 /* icon-info@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B5501F0D2AF22912009AE3D3 /* icon-info@2x.png */; }; 16 | B5501F172AF22912009AE3D3 /* icon-error.png in Resources */ = {isa = PBXBuildFile; fileRef = B5501F0E2AF22912009AE3D3 /* icon-error.png */; }; 17 | B5501F182AF22912009AE3D3 /* icon-info.png in Resources */ = {isa = PBXBuildFile; fileRef = B5501F0F2AF22912009AE3D3 /* icon-info.png */; }; 18 | B5501F192AF22912009AE3D3 /* icon-success@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B5501F102AF22912009AE3D3 /* icon-success@2x.png */; }; 19 | B5501F1A2AF22912009AE3D3 /* icon-error@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = B5501F112AF22912009AE3D3 /* icon-error@3x.png */; }; 20 | B5501F1B2AF22912009AE3D3 /* icon-error@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B5501F122AF22912009AE3D3 /* icon-error@2x.png */; }; 21 | B5501F1C2AF22912009AE3D3 /* icon-success@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = B5501F132AF22912009AE3D3 /* icon-success@3x.png */; }; 22 | F22ADD2E1B8CB23F00EBA839 /* Message.swift in Sources */ = {isa = PBXBuildFile; fileRef = F22ADD2D1B8CB23F00EBA839 /* Message.swift */; }; 23 | F283F61C25237BAC003DB4CF /* QueueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F283F61B25237BAC003DB4CF /* QueueTests.swift */; }; 24 | F283F61E25237BAC003DB4CF /* SwiftMessageBar.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F2AB58E21B28B33C001DCC74 /* SwiftMessageBar.framework */; }; 25 | F2AB58E81B28B33C001DCC74 /* SwiftMessageBar.h in Headers */ = {isa = PBXBuildFile; fileRef = F2AB58E71B28B33C001DCC74 /* SwiftMessageBar.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26 | F2AB593A1B28B45A001DCC74 /* SwiftMessageBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2AB59391B28B45A001DCC74 /* SwiftMessageBar.swift */; }; 27 | /* End PBXBuildFile section */ 28 | 29 | /* Begin PBXContainerItemProxy section */ 30 | F283F61F25237BAC003DB4CF /* PBXContainerItemProxy */ = { 31 | isa = PBXContainerItemProxy; 32 | containerPortal = F2AB58D91B28B33C001DCC74 /* Project object */; 33 | proxyType = 1; 34 | remoteGlobalIDString = F2AB58E11B28B33C001DCC74; 35 | remoteInfo = SwiftMessageBar; 36 | }; 37 | /* End PBXContainerItemProxy section */ 38 | 39 | /* Begin PBXFileReference section */ 40 | 77BBDF7D209705E600BDED60 /* DeviceType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceType.swift; sourceTree = ""; }; 41 | 77E9E14D205167C100E157F5 /* Queue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Queue.swift; sourceTree = ""; }; 42 | 77EBFCB320519D5000AFE1F9 /* MessageType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageType.swift; sourceTree = ""; }; 43 | B5501F0B2AF22912009AE3D3 /* icon-info@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-info@3x.png"; sourceTree = ""; }; 44 | B5501F0C2AF22912009AE3D3 /* icon-success@1x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-success@1x.png"; sourceTree = ""; }; 45 | B5501F0D2AF22912009AE3D3 /* icon-info@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-info@2x.png"; sourceTree = ""; }; 46 | B5501F0E2AF22912009AE3D3 /* icon-error.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-error.png"; sourceTree = ""; }; 47 | B5501F0F2AF22912009AE3D3 /* icon-info.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-info.png"; sourceTree = ""; }; 48 | B5501F102AF22912009AE3D3 /* icon-success@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-success@2x.png"; sourceTree = ""; }; 49 | B5501F112AF22912009AE3D3 /* icon-error@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-error@3x.png"; sourceTree = ""; }; 50 | B5501F122AF22912009AE3D3 /* icon-error@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-error@2x.png"; sourceTree = ""; }; 51 | B5501F132AF22912009AE3D3 /* icon-success@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-success@3x.png"; sourceTree = ""; }; 52 | F22ADD2D1B8CB23F00EBA839 /* Message.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Message.swift; sourceTree = ""; }; 53 | F283F61925237BAC003DB4CF /* SwiftMessageBarTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwiftMessageBarTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 54 | F283F61B25237BAC003DB4CF /* QueueTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueueTests.swift; sourceTree = ""; }; 55 | F283F61D25237BAC003DB4CF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 56 | F2AB58E21B28B33C001DCC74 /* SwiftMessageBar.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftMessageBar.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | F2AB58E61B28B33C001DCC74 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 58 | F2AB58E71B28B33C001DCC74 /* SwiftMessageBar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SwiftMessageBar.h; sourceTree = ""; }; 59 | F2AB59391B28B45A001DCC74 /* SwiftMessageBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftMessageBar.swift; sourceTree = ""; }; 60 | /* End PBXFileReference section */ 61 | 62 | /* Begin PBXFrameworksBuildPhase section */ 63 | F283F61625237BAC003DB4CF /* Frameworks */ = { 64 | isa = PBXFrameworksBuildPhase; 65 | buildActionMask = 2147483647; 66 | files = ( 67 | F283F61E25237BAC003DB4CF /* SwiftMessageBar.framework in Frameworks */, 68 | ); 69 | runOnlyForDeploymentPostprocessing = 0; 70 | }; 71 | F2AB58DE1B28B33C001DCC74 /* Frameworks */ = { 72 | isa = PBXFrameworksBuildPhase; 73 | buildActionMask = 2147483647; 74 | files = ( 75 | ); 76 | runOnlyForDeploymentPostprocessing = 0; 77 | }; 78 | /* End PBXFrameworksBuildPhase section */ 79 | 80 | /* Begin PBXGroup section */ 81 | B5501F0A2AF22912009AE3D3 /* Resources */ = { 82 | isa = PBXGroup; 83 | children = ( 84 | B5501F0B2AF22912009AE3D3 /* icon-info@3x.png */, 85 | B5501F0C2AF22912009AE3D3 /* icon-success@1x.png */, 86 | B5501F0D2AF22912009AE3D3 /* icon-info@2x.png */, 87 | B5501F0E2AF22912009AE3D3 /* icon-error.png */, 88 | B5501F0F2AF22912009AE3D3 /* icon-info.png */, 89 | B5501F102AF22912009AE3D3 /* icon-success@2x.png */, 90 | B5501F112AF22912009AE3D3 /* icon-error@3x.png */, 91 | B5501F122AF22912009AE3D3 /* icon-error@2x.png */, 92 | B5501F132AF22912009AE3D3 /* icon-success@3x.png */, 93 | ); 94 | path = Resources; 95 | sourceTree = ""; 96 | }; 97 | F283F61A25237BAC003DB4CF /* SwiftMessageBarTests */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | F283F61B25237BAC003DB4CF /* QueueTests.swift */, 101 | F283F61D25237BAC003DB4CF /* Info.plist */, 102 | ); 103 | path = SwiftMessageBarTests; 104 | sourceTree = ""; 105 | }; 106 | F2AB58D81B28B33C001DCC74 = { 107 | isa = PBXGroup; 108 | children = ( 109 | F2AB58E41B28B33C001DCC74 /* SwiftMessageBar */, 110 | F283F61A25237BAC003DB4CF /* SwiftMessageBarTests */, 111 | F2AB58E31B28B33C001DCC74 /* Products */, 112 | ); 113 | indentWidth = 2; 114 | sourceTree = ""; 115 | tabWidth = 2; 116 | }; 117 | F2AB58E31B28B33C001DCC74 /* Products */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | F2AB58E21B28B33C001DCC74 /* SwiftMessageBar.framework */, 121 | F283F61925237BAC003DB4CF /* SwiftMessageBarTests.xctest */, 122 | ); 123 | name = Products; 124 | sourceTree = ""; 125 | }; 126 | F2AB58E41B28B33C001DCC74 /* SwiftMessageBar */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | 77BBDF7D209705E600BDED60 /* DeviceType.swift */, 130 | F22ADD2D1B8CB23F00EBA839 /* Message.swift */, 131 | 77EBFCB320519D5000AFE1F9 /* MessageType.swift */, 132 | 77E9E14D205167C100E157F5 /* Queue.swift */, 133 | F2AB58E61B28B33C001DCC74 /* Info.plist */, 134 | B5501F0A2AF22912009AE3D3 /* Resources */, 135 | F2AB58E71B28B33C001DCC74 /* SwiftMessageBar.h */, 136 | F2AB59391B28B45A001DCC74 /* SwiftMessageBar.swift */, 137 | ); 138 | path = SwiftMessageBar; 139 | sourceTree = ""; 140 | }; 141 | /* End PBXGroup section */ 142 | 143 | /* Begin PBXHeadersBuildPhase section */ 144 | F2AB58DF1B28B33C001DCC74 /* Headers */ = { 145 | isa = PBXHeadersBuildPhase; 146 | buildActionMask = 2147483647; 147 | files = ( 148 | F2AB58E81B28B33C001DCC74 /* SwiftMessageBar.h in Headers */, 149 | ); 150 | runOnlyForDeploymentPostprocessing = 0; 151 | }; 152 | /* End PBXHeadersBuildPhase section */ 153 | 154 | /* Begin PBXNativeTarget section */ 155 | F283F61825237BAC003DB4CF /* SwiftMessageBarTests */ = { 156 | isa = PBXNativeTarget; 157 | buildConfigurationList = F283F62325237BAC003DB4CF /* Build configuration list for PBXNativeTarget "SwiftMessageBarTests" */; 158 | buildPhases = ( 159 | F283F61525237BAC003DB4CF /* Sources */, 160 | F283F61625237BAC003DB4CF /* Frameworks */, 161 | F283F61725237BAC003DB4CF /* Resources */, 162 | ); 163 | buildRules = ( 164 | ); 165 | dependencies = ( 166 | F283F62025237BAC003DB4CF /* PBXTargetDependency */, 167 | ); 168 | name = SwiftMessageBarTests; 169 | productName = SwiftMessageBarTests; 170 | productReference = F283F61925237BAC003DB4CF /* SwiftMessageBarTests.xctest */; 171 | productType = "com.apple.product-type.bundle.unit-test"; 172 | }; 173 | F2AB58E11B28B33C001DCC74 /* SwiftMessageBar */ = { 174 | isa = PBXNativeTarget; 175 | buildConfigurationList = F2AB58F81B28B33D001DCC74 /* Build configuration list for PBXNativeTarget "SwiftMessageBar" */; 176 | buildPhases = ( 177 | F2AB58DD1B28B33C001DCC74 /* Sources */, 178 | F2AB58DE1B28B33C001DCC74 /* Frameworks */, 179 | F2AB58DF1B28B33C001DCC74 /* Headers */, 180 | F2AB58E01B28B33C001DCC74 /* Resources */, 181 | ); 182 | buildRules = ( 183 | ); 184 | dependencies = ( 185 | ); 186 | name = SwiftMessageBar; 187 | productName = SwiftMessageBar; 188 | productReference = F2AB58E21B28B33C001DCC74 /* SwiftMessageBar.framework */; 189 | productType = "com.apple.product-type.framework"; 190 | }; 191 | /* End PBXNativeTarget section */ 192 | 193 | /* Begin PBXProject section */ 194 | F2AB58D91B28B33C001DCC74 /* Project object */ = { 195 | isa = PBXProject; 196 | attributes = { 197 | LastSwiftMigration = 0700; 198 | LastSwiftUpdateCheck = 1200; 199 | LastUpgradeCheck = 1200; 200 | ORGANIZATIONNAME = Schnaub; 201 | TargetAttributes = { 202 | F283F61825237BAC003DB4CF = { 203 | CreatedOnToolsVersion = 12.0; 204 | DevelopmentTeam = CPRVB9W254; 205 | ProvisioningStyle = Automatic; 206 | }; 207 | F2AB58E11B28B33C001DCC74 = { 208 | CreatedOnToolsVersion = 6.3.2; 209 | LastSwiftMigration = 1020; 210 | }; 211 | }; 212 | }; 213 | buildConfigurationList = F2AB58DC1B28B33C001DCC74 /* Build configuration list for PBXProject "SwiftMessageBar" */; 214 | compatibilityVersion = "Xcode 3.2"; 215 | developmentRegion = en; 216 | hasScannedForEncodings = 0; 217 | knownRegions = ( 218 | en, 219 | Base, 220 | ); 221 | mainGroup = F2AB58D81B28B33C001DCC74; 222 | productRefGroup = F2AB58E31B28B33C001DCC74 /* Products */; 223 | projectDirPath = ""; 224 | projectRoot = ""; 225 | targets = ( 226 | F2AB58E11B28B33C001DCC74 /* SwiftMessageBar */, 227 | F283F61825237BAC003DB4CF /* SwiftMessageBarTests */, 228 | ); 229 | }; 230 | /* End PBXProject section */ 231 | 232 | /* Begin PBXResourcesBuildPhase section */ 233 | F283F61725237BAC003DB4CF /* Resources */ = { 234 | isa = PBXResourcesBuildPhase; 235 | buildActionMask = 2147483647; 236 | files = ( 237 | ); 238 | runOnlyForDeploymentPostprocessing = 0; 239 | }; 240 | F2AB58E01B28B33C001DCC74 /* Resources */ = { 241 | isa = PBXResourcesBuildPhase; 242 | buildActionMask = 2147483647; 243 | files = ( 244 | B5501F1A2AF22912009AE3D3 /* icon-error@3x.png in Resources */, 245 | B5501F162AF22912009AE3D3 /* icon-info@2x.png in Resources */, 246 | B5501F1C2AF22912009AE3D3 /* icon-success@3x.png in Resources */, 247 | B5501F182AF22912009AE3D3 /* icon-info.png in Resources */, 248 | B5501F172AF22912009AE3D3 /* icon-error.png in Resources */, 249 | B5501F152AF22912009AE3D3 /* icon-success@1x.png in Resources */, 250 | B5501F142AF22912009AE3D3 /* icon-info@3x.png in Resources */, 251 | B5501F1B2AF22912009AE3D3 /* icon-error@2x.png in Resources */, 252 | B5501F192AF22912009AE3D3 /* icon-success@2x.png in Resources */, 253 | ); 254 | runOnlyForDeploymentPostprocessing = 0; 255 | }; 256 | /* End PBXResourcesBuildPhase section */ 257 | 258 | /* Begin PBXSourcesBuildPhase section */ 259 | F283F61525237BAC003DB4CF /* Sources */ = { 260 | isa = PBXSourcesBuildPhase; 261 | buildActionMask = 2147483647; 262 | files = ( 263 | F283F61C25237BAC003DB4CF /* QueueTests.swift in Sources */, 264 | ); 265 | runOnlyForDeploymentPostprocessing = 0; 266 | }; 267 | F2AB58DD1B28B33C001DCC74 /* Sources */ = { 268 | isa = PBXSourcesBuildPhase; 269 | buildActionMask = 2147483647; 270 | files = ( 271 | F2AB593A1B28B45A001DCC74 /* SwiftMessageBar.swift in Sources */, 272 | 77E9E14E205167C100E157F5 /* Queue.swift in Sources */, 273 | F22ADD2E1B8CB23F00EBA839 /* Message.swift in Sources */, 274 | 77EBFCB420519D5000AFE1F9 /* MessageType.swift in Sources */, 275 | 77BBDF7E209705E600BDED60 /* DeviceType.swift in Sources */, 276 | ); 277 | runOnlyForDeploymentPostprocessing = 0; 278 | }; 279 | /* End PBXSourcesBuildPhase section */ 280 | 281 | /* Begin PBXTargetDependency section */ 282 | F283F62025237BAC003DB4CF /* PBXTargetDependency */ = { 283 | isa = PBXTargetDependency; 284 | target = F2AB58E11B28B33C001DCC74 /* SwiftMessageBar */; 285 | targetProxy = F283F61F25237BAC003DB4CF /* PBXContainerItemProxy */; 286 | }; 287 | /* End PBXTargetDependency section */ 288 | 289 | /* Begin XCBuildConfiguration section */ 290 | F283F62125237BAC003DB4CF /* Debug */ = { 291 | isa = XCBuildConfiguration; 292 | buildSettings = { 293 | CLANG_ANALYZER_NONNULL = YES; 294 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 295 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 296 | CLANG_ENABLE_OBJC_WEAK = YES; 297 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 298 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 299 | CODE_SIGN_STYLE = Automatic; 300 | DEBUG_INFORMATION_FORMAT = dwarf; 301 | DEVELOPMENT_TEAM = CPRVB9W254; 302 | GCC_C_LANGUAGE_STANDARD = gnu11; 303 | INFOPLIST_FILE = SwiftMessageBarTests/Info.plist; 304 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 305 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 306 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 307 | MTL_FAST_MATH = YES; 308 | PRODUCT_BUNDLE_IDENTIFIER = com.schnaub.SwiftMessageBarTests; 309 | PRODUCT_NAME = "$(TARGET_NAME)"; 310 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 311 | SWIFT_VERSION = 5.0; 312 | TARGETED_DEVICE_FAMILY = "1,2"; 313 | }; 314 | name = Debug; 315 | }; 316 | F283F62225237BAC003DB4CF /* Release */ = { 317 | isa = XCBuildConfiguration; 318 | buildSettings = { 319 | CLANG_ANALYZER_NONNULL = YES; 320 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 321 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 322 | CLANG_ENABLE_OBJC_WEAK = YES; 323 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 324 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 325 | CODE_SIGN_STYLE = Automatic; 326 | DEVELOPMENT_TEAM = CPRVB9W254; 327 | GCC_C_LANGUAGE_STANDARD = gnu11; 328 | INFOPLIST_FILE = SwiftMessageBarTests/Info.plist; 329 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 330 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 331 | MTL_FAST_MATH = YES; 332 | PRODUCT_BUNDLE_IDENTIFIER = com.schnaub.SwiftMessageBarTests; 333 | PRODUCT_NAME = "$(TARGET_NAME)"; 334 | SWIFT_VERSION = 5.0; 335 | TARGETED_DEVICE_FAMILY = "1,2"; 336 | }; 337 | name = Release; 338 | }; 339 | F2AB58F61B28B33D001DCC74 /* Debug */ = { 340 | isa = XCBuildConfiguration; 341 | buildSettings = { 342 | ALWAYS_SEARCH_USER_PATHS = NO; 343 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 344 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 345 | CLANG_CXX_LIBRARY = "libc++"; 346 | CLANG_ENABLE_MODULES = YES; 347 | CLANG_ENABLE_OBJC_ARC = YES; 348 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 349 | CLANG_WARN_BOOL_CONVERSION = YES; 350 | CLANG_WARN_COMMA = YES; 351 | CLANG_WARN_CONSTANT_CONVERSION = YES; 352 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 353 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 354 | CLANG_WARN_EMPTY_BODY = YES; 355 | CLANG_WARN_ENUM_CONVERSION = YES; 356 | CLANG_WARN_INFINITE_RECURSION = YES; 357 | CLANG_WARN_INT_CONVERSION = YES; 358 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 359 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 360 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 361 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 362 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 363 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 364 | CLANG_WARN_STRICT_PROTOTYPES = YES; 365 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 366 | CLANG_WARN_UNREACHABLE_CODE = YES; 367 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 368 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 369 | COPY_PHASE_STRIP = NO; 370 | CURRENT_PROJECT_VERSION = 1; 371 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 372 | ENABLE_STRICT_OBJC_MSGSEND = YES; 373 | ENABLE_TESTABILITY = YES; 374 | GCC_C_LANGUAGE_STANDARD = gnu99; 375 | GCC_DYNAMIC_NO_PIC = NO; 376 | GCC_NO_COMMON_BLOCKS = YES; 377 | GCC_OPTIMIZATION_LEVEL = 0; 378 | GCC_PREPROCESSOR_DEFINITIONS = ( 379 | "DEBUG=1", 380 | "$(inherited)", 381 | ); 382 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 383 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 384 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 385 | GCC_WARN_UNDECLARED_SELECTOR = YES; 386 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 387 | GCC_WARN_UNUSED_FUNCTION = YES; 388 | GCC_WARN_UNUSED_VARIABLE = YES; 389 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 390 | MTL_ENABLE_DEBUG_INFO = YES; 391 | ONLY_ACTIVE_ARCH = YES; 392 | SDKROOT = iphoneos; 393 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 394 | SWIFT_VERSION = 4.0; 395 | TARGETED_DEVICE_FAMILY = "1,2"; 396 | VERSIONING_SYSTEM = "apple-generic"; 397 | VERSION_INFO_PREFIX = ""; 398 | }; 399 | name = Debug; 400 | }; 401 | F2AB58F71B28B33D001DCC74 /* Release */ = { 402 | isa = XCBuildConfiguration; 403 | buildSettings = { 404 | ALWAYS_SEARCH_USER_PATHS = NO; 405 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 406 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 407 | CLANG_CXX_LIBRARY = "libc++"; 408 | CLANG_ENABLE_MODULES = YES; 409 | CLANG_ENABLE_OBJC_ARC = YES; 410 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 411 | CLANG_WARN_BOOL_CONVERSION = YES; 412 | CLANG_WARN_COMMA = YES; 413 | CLANG_WARN_CONSTANT_CONVERSION = YES; 414 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 415 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 416 | CLANG_WARN_EMPTY_BODY = YES; 417 | CLANG_WARN_ENUM_CONVERSION = YES; 418 | CLANG_WARN_INFINITE_RECURSION = YES; 419 | CLANG_WARN_INT_CONVERSION = YES; 420 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 421 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 422 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 423 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 424 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 425 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 426 | CLANG_WARN_STRICT_PROTOTYPES = YES; 427 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 428 | CLANG_WARN_UNREACHABLE_CODE = YES; 429 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 430 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 431 | COPY_PHASE_STRIP = NO; 432 | CURRENT_PROJECT_VERSION = 1; 433 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 434 | ENABLE_NS_ASSERTIONS = NO; 435 | ENABLE_STRICT_OBJC_MSGSEND = YES; 436 | GCC_C_LANGUAGE_STANDARD = gnu99; 437 | GCC_NO_COMMON_BLOCKS = YES; 438 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 439 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 440 | GCC_WARN_UNDECLARED_SELECTOR = YES; 441 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 442 | GCC_WARN_UNUSED_FUNCTION = YES; 443 | GCC_WARN_UNUSED_VARIABLE = YES; 444 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 445 | MTL_ENABLE_DEBUG_INFO = NO; 446 | SDKROOT = iphoneos; 447 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 448 | SWIFT_VERSION = 4.0; 449 | TARGETED_DEVICE_FAMILY = "1,2"; 450 | VALIDATE_PRODUCT = YES; 451 | VERSIONING_SYSTEM = "apple-generic"; 452 | VERSION_INFO_PREFIX = ""; 453 | }; 454 | name = Release; 455 | }; 456 | F2AB58F91B28B33D001DCC74 /* Debug */ = { 457 | isa = XCBuildConfiguration; 458 | buildSettings = { 459 | CLANG_ENABLE_MODULES = YES; 460 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 461 | DEFINES_MODULE = YES; 462 | DYLIB_COMPATIBILITY_VERSION = 1; 463 | DYLIB_CURRENT_VERSION = 1; 464 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 465 | INFOPLIST_FILE = SwiftMessageBar/Info.plist; 466 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 467 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 468 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 469 | PRODUCT_BUNDLE_IDENTIFIER = "com.schnaub.$(PRODUCT_NAME:rfc1034identifier)"; 470 | PRODUCT_NAME = "$(TARGET_NAME)"; 471 | SKIP_INSTALL = YES; 472 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 473 | SWIFT_VERSION = 5.0; 474 | }; 475 | name = Debug; 476 | }; 477 | F2AB58FA1B28B33D001DCC74 /* Release */ = { 478 | isa = XCBuildConfiguration; 479 | buildSettings = { 480 | CLANG_ENABLE_MODULES = YES; 481 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 482 | DEFINES_MODULE = YES; 483 | DYLIB_COMPATIBILITY_VERSION = 1; 484 | DYLIB_CURRENT_VERSION = 1; 485 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 486 | INFOPLIST_FILE = SwiftMessageBar/Info.plist; 487 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 488 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 489 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 490 | PRODUCT_BUNDLE_IDENTIFIER = "com.schnaub.$(PRODUCT_NAME:rfc1034identifier)"; 491 | PRODUCT_NAME = "$(TARGET_NAME)"; 492 | SKIP_INSTALL = YES; 493 | SWIFT_VERSION = 5.0; 494 | }; 495 | name = Release; 496 | }; 497 | /* End XCBuildConfiguration section */ 498 | 499 | /* Begin XCConfigurationList section */ 500 | F283F62325237BAC003DB4CF /* Build configuration list for PBXNativeTarget "SwiftMessageBarTests" */ = { 501 | isa = XCConfigurationList; 502 | buildConfigurations = ( 503 | F283F62125237BAC003DB4CF /* Debug */, 504 | F283F62225237BAC003DB4CF /* Release */, 505 | ); 506 | defaultConfigurationIsVisible = 0; 507 | defaultConfigurationName = Release; 508 | }; 509 | F2AB58DC1B28B33C001DCC74 /* Build configuration list for PBXProject "SwiftMessageBar" */ = { 510 | isa = XCConfigurationList; 511 | buildConfigurations = ( 512 | F2AB58F61B28B33D001DCC74 /* Debug */, 513 | F2AB58F71B28B33D001DCC74 /* Release */, 514 | ); 515 | defaultConfigurationIsVisible = 0; 516 | defaultConfigurationName = Release; 517 | }; 518 | F2AB58F81B28B33D001DCC74 /* Build configuration list for PBXNativeTarget "SwiftMessageBar" */ = { 519 | isa = XCConfigurationList; 520 | buildConfigurations = ( 521 | F2AB58F91B28B33D001DCC74 /* Debug */, 522 | F2AB58FA1B28B33D001DCC74 /* Release */, 523 | ); 524 | defaultConfigurationIsVisible = 0; 525 | defaultConfigurationName = Release; 526 | }; 527 | /* End XCConfigurationList section */ 528 | }; 529 | rootObject = F2AB58D91B28B33C001DCC74 /* Project object */; 530 | } 531 | -------------------------------------------------------------------------------- /SwiftMessageBar.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SwiftMessageBar.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SwiftMessageBar.xcodeproj/xcshareddata/xcschemes/SwiftMessageBar.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 45 | 46 | 52 | 53 | 54 | 55 | 57 | 63 | 64 | 65 | 66 | 67 | 77 | 78 | 84 | 85 | 86 | 87 | 93 | 94 | 100 | 101 | 102 | 103 | 105 | 106 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /SwiftMessageBar.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SwiftMessageBar.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SwiftMessageBar/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 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /SwiftMessageBar/Message.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015 Schnaub. All rights reserved. 3 | // 4 | 5 | import UIKit 6 | 7 | final class Message: UIView { 8 | 9 | var isHit = false 10 | 11 | private(set) var type: MessageType! 12 | private let uuid = UUID() 13 | private var title: String? 14 | private var message: String? 15 | private var titleFontColor: UIColor! 16 | private var messageFontColor: UIColor! 17 | private var icon: UIImage? 18 | private(set) var callback: Callback? 19 | private(set) var duration: TimeInterval! 20 | private(set) var dismiss = true 21 | private var languageDirection: NSLocale.LanguageDirection! 22 | private var titleFont: UIFont! 23 | private var messageFont: UIFont! 24 | private var accessoryView: UIView? 25 | 26 | public lazy var contentStackView: UIStackView = { 27 | let contentView = UIStackView(frame: bounds) 28 | contentView.layoutMargins = UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 8) 29 | contentView.isLayoutMarginsRelativeArrangement = true 30 | contentView.axis = .horizontal 31 | contentView.spacing = 10 32 | return contentView 33 | }() 34 | 35 | private var paragraphStyle: NSMutableParagraphStyle { 36 | let paragraphStyle = NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle 37 | paragraphStyle.alignment = .left 38 | return paragraphStyle 39 | } 40 | 41 | init( 42 | type: MessageType, 43 | title: String?, 44 | message: String?, 45 | backgroundColor: UIColor, 46 | titleFontColor: UIColor, 47 | messageFontColor: UIColor, 48 | icon: UIImage?, 49 | duration: TimeInterval, 50 | dismiss: Bool = true, 51 | callback: Callback?, 52 | languageDirection: NSLocale.LanguageDirection, 53 | titleFont: UIFont, 54 | messageFont: UIFont, 55 | accessoryView: UIView? 56 | ) { 57 | self.type = type 58 | self.title = title 59 | self.message = message 60 | self.duration = duration 61 | self.callback = callback 62 | self.titleFontColor = titleFontColor 63 | self.messageFontColor = messageFontColor 64 | self.icon = icon 65 | self.dismiss = dismiss 66 | self.languageDirection = languageDirection 67 | self.titleFont = titleFont 68 | self.messageFont = messageFont 69 | self.accessoryView = accessoryView 70 | 71 | super.init(frame: .zero) 72 | 73 | self.backgroundColor = backgroundColor 74 | usesAutoLayout(true) 75 | } 76 | 77 | func configureSubviews(topAnchor: NSLayoutYAxisAnchor) { 78 | let iconImageView = makeIconView() 79 | let titleLabel = makeTitleLabel() 80 | let messageLabel = makeMessageLabel() 81 | 82 | if languageDirection == .rightToLeft { 83 | titleLabel.textAlignment = .right 84 | messageLabel.textAlignment = .right 85 | titleLabel.flipHorizontal() 86 | messageLabel.flipHorizontal() 87 | iconImageView.flipHorizontal() 88 | accessoryView?.flipHorizontal() 89 | } 90 | 91 | let textStackView = makeTextStackView(with: titleLabel, messageLabel: messageLabel) 92 | contentStackView.addArrangedSubview(iconImageView) 93 | contentStackView.addArrangedSubview(textStackView) 94 | 95 | if let accessoryView = accessoryView { 96 | contentStackView.addArrangedSubview(makeWrapperView(for: accessoryView)) 97 | } 98 | 99 | addSubview(contentStackView) 100 | configureConstraints(withTopAnchor: topAnchor) 101 | } 102 | 103 | private func configureConstraints(withTopAnchor topAnchor: NSLayoutYAxisAnchor) { 104 | contentStackView.usesAutoLayout(true) 105 | NSLayoutConstraint.activate([ 106 | contentStackView.rightAnchor.constraint(equalTo: rightAnchor), 107 | contentStackView.leftAnchor.constraint(equalTo: leftAnchor), 108 | contentStackView.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor), 109 | contentStackView.topAnchor.constraint(equalTo: topAnchor), 110 | ]) 111 | } 112 | 113 | private func makeIconView() -> UIImageView { 114 | let iconImageView = UIImageView(image: icon) 115 | iconImageView.contentMode = .center 116 | iconImageView.setContentCompressionResistancePriority(.required, for: .horizontal) 117 | iconImageView.setContentHuggingPriority(.required, for: .horizontal) 118 | return iconImageView 119 | } 120 | 121 | private func makeTitleLabel() -> UILabel { 122 | let titleLabel = UILabel() 123 | titleLabel.numberOfLines = 0 124 | 125 | if let title = title { 126 | let attributes: [NSAttributedString.Key: Any] = [ 127 | .font : titleFont!, 128 | .foregroundColor: titleFontColor!, 129 | .paragraphStyle: paragraphStyle 130 | ] 131 | titleLabel.attributedText = NSAttributedString(string: title, attributes: attributes) 132 | } 133 | return titleLabel 134 | } 135 | 136 | private func makeMessageLabel() -> UILabel { 137 | let messageLabel = UILabel() 138 | messageLabel.numberOfLines = 0 139 | 140 | if let message = message { 141 | let attributes: [NSAttributedString.Key: Any] = [ 142 | .font : messageFont!, 143 | .foregroundColor: messageFontColor!, 144 | .paragraphStyle: paragraphStyle 145 | ] 146 | messageLabel.attributedText = NSAttributedString(string: message, attributes: attributes) 147 | } 148 | return messageLabel 149 | } 150 | 151 | private func makeTextStackView(with titleLabel: UILabel, messageLabel: UILabel) -> UIStackView { 152 | let isTitleEmpty = title?.isEmpty ?? true 153 | let isMessageEmpty = message?.isEmpty ?? true 154 | 155 | let stackView = UIStackView(frame: bounds) 156 | if !isTitleEmpty { 157 | stackView.addArrangedSubview(titleLabel) 158 | } 159 | if !isMessageEmpty { 160 | stackView.addArrangedSubview(messageLabel) 161 | } 162 | 163 | stackView.usesAutoLayout(true) 164 | stackView.axis = .vertical 165 | stackView.spacing = 1 166 | stackView.distribution = .fill 167 | return stackView 168 | } 169 | 170 | private func makeWrapperView(for view: UIView) -> UIView { 171 | let wrapper = UIView(frame: view.bounds) 172 | 173 | view.setContentCompressionResistancePriority(.required, for: .horizontal) 174 | wrapper.addSubview(view) 175 | wrapper.contentMode = .center 176 | NSLayoutConstraint.activate([ 177 | view.centerYAnchor.constraint(equalTo: wrapper.centerYAnchor), 178 | view.centerXAnchor.constraint(equalTo: wrapper.centerXAnchor), 179 | view.widthAnchor.constraint(equalTo: wrapper.widthAnchor)]) 180 | 181 | view.usesAutoLayout(true) 182 | return wrapper 183 | } 184 | 185 | required init?(coder aDecoder: NSCoder) { 186 | super.init(coder: aDecoder) 187 | } 188 | 189 | override func updateConstraints() { 190 | if let superview = superview { 191 | NSLayoutConstraint.activate([ 192 | rightAnchor.constraint(equalTo: superview.rightAnchor), 193 | leftAnchor.constraint(equalTo: superview.leftAnchor), 194 | topAnchor.constraint(equalTo: superview.topAnchor) 195 | ]) 196 | } 197 | super.updateConstraints() 198 | } 199 | 200 | var estimatedHeight: CGFloat { 201 | self.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).height 202 | } 203 | } 204 | 205 | extension Message: Identifiable { 206 | 207 | var id: UUID { 208 | uuid 209 | } 210 | 211 | } 212 | 213 | extension UIView { 214 | 215 | func flipHorizontal() { 216 | layer.setAffineTransform(CGAffineTransform(scaleX: -1, y: 1)) 217 | } 218 | 219 | fileprivate func usesAutoLayout(_ usesAutoLayout: Bool) { 220 | translatesAutoresizingMaskIntoConstraints = !usesAutoLayout 221 | } 222 | } 223 | 224 | -------------------------------------------------------------------------------- /SwiftMessageBar/MessageType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2018 Schnaub. All rights reserved. 3 | // 4 | 5 | import UIKit 6 | 7 | public enum MessageType { 8 | case error, success, info 9 | 10 | func backgroundColor(fromConfig config: SwiftMessageBar.Config) -> UIColor { 11 | switch self { 12 | case .error: 13 | return config.errorColor 14 | case .info: 15 | return config.infoColor 16 | case .success: 17 | return config.successColor 18 | } 19 | } 20 | 21 | func image(fromConfig config: SwiftMessageBar.Config) -> UIImage? { 22 | switch self { 23 | case .error: 24 | return config.errorIcon 25 | case .info: 26 | return config.infoIcon 27 | case .success: 28 | return config.successIcon 29 | } 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /SwiftMessageBar/Queue.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2018 Schnaub. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | 7 | struct Queue { 8 | 9 | private var left: [T] 10 | private var right: [T] 11 | 12 | var isEmpty: Bool { 13 | left.isEmpty && right.isEmpty 14 | } 15 | 16 | init() { 17 | left = [] 18 | right = [] 19 | } 20 | 21 | mutating func dequeue() -> T? { 22 | guard !(left.isEmpty && right.isEmpty) else { 23 | return nil 24 | } 25 | 26 | if left.isEmpty { 27 | left = right.reversed() 28 | right.removeAll(keepingCapacity: true) 29 | } 30 | return left.removeLast() 31 | } 32 | 33 | mutating func enqueue(_ newElement: T) { 34 | right.append(newElement) 35 | } 36 | 37 | mutating func removeAll() { 38 | left.removeAll() 39 | right.removeAll() 40 | } 41 | 42 | mutating func removeElement(_ element: T) { 43 | if let idx = left.firstIndex(of: element) { 44 | left.remove(at: idx) 45 | } 46 | if let idx = right.firstIndex(of: element) { 47 | right.remove(at: idx) 48 | } 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /SwiftMessageBar/Resources/icon-error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JanGorman/SwiftMessageBar/0664a669264a11d7ba215c5cf6f18a2142d92394/SwiftMessageBar/Resources/icon-error.png -------------------------------------------------------------------------------- /SwiftMessageBar/Resources/icon-error@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JanGorman/SwiftMessageBar/0664a669264a11d7ba215c5cf6f18a2142d92394/SwiftMessageBar/Resources/icon-error@2x.png -------------------------------------------------------------------------------- /SwiftMessageBar/Resources/icon-error@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JanGorman/SwiftMessageBar/0664a669264a11d7ba215c5cf6f18a2142d92394/SwiftMessageBar/Resources/icon-error@3x.png -------------------------------------------------------------------------------- /SwiftMessageBar/Resources/icon-info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JanGorman/SwiftMessageBar/0664a669264a11d7ba215c5cf6f18a2142d92394/SwiftMessageBar/Resources/icon-info.png -------------------------------------------------------------------------------- /SwiftMessageBar/Resources/icon-info@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JanGorman/SwiftMessageBar/0664a669264a11d7ba215c5cf6f18a2142d92394/SwiftMessageBar/Resources/icon-info@2x.png -------------------------------------------------------------------------------- /SwiftMessageBar/Resources/icon-info@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JanGorman/SwiftMessageBar/0664a669264a11d7ba215c5cf6f18a2142d92394/SwiftMessageBar/Resources/icon-info@3x.png -------------------------------------------------------------------------------- /SwiftMessageBar/Resources/icon-success@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JanGorman/SwiftMessageBar/0664a669264a11d7ba215c5cf6f18a2142d92394/SwiftMessageBar/Resources/icon-success@1x.png -------------------------------------------------------------------------------- /SwiftMessageBar/Resources/icon-success@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JanGorman/SwiftMessageBar/0664a669264a11d7ba215c5cf6f18a2142d92394/SwiftMessageBar/Resources/icon-success@2x.png -------------------------------------------------------------------------------- /SwiftMessageBar/Resources/icon-success@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JanGorman/SwiftMessageBar/0664a669264a11d7ba215c5cf6f18a2142d92394/SwiftMessageBar/Resources/icon-success@3x.png -------------------------------------------------------------------------------- /SwiftMessageBar/SwiftMessageBar.h: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftMessageBar.h 3 | // SwiftMessageBar 4 | // 5 | // Created by Jan Gorman on 10/06/15. 6 | // Copyright (c) 2015 Schnaub. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for SwiftMessageBar. 12 | FOUNDATION_EXPORT double SwiftMessageBarVersionNumber; 13 | 14 | //! Project version string for SwiftMessageBar. 15 | FOUNDATION_EXPORT const unsigned char SwiftMessageBarVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /SwiftMessageBar/SwiftMessageBar.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015 Schnaub. All rights reserved. 3 | // 4 | 5 | import UIKit 6 | 7 | public typealias Callback = () -> Void 8 | 9 | public final class SwiftMessageBar { 10 | 11 | public struct Config { 12 | 13 | public struct Defaults { 14 | public static let errorColor: UIColor = .red 15 | public static let successColor: UIColor = .green 16 | public static let infoColor: UIColor = .blue 17 | public static let titleColor: UIColor = .white 18 | public static let messageColor: UIColor = .white 19 | public static let isStatusBarHidden = false 20 | public static let titleFont: UIFont = .boldSystemFont(ofSize: 16) 21 | public static let messageFont: UIFont = .systemFont(ofSize: 14) 22 | public static let isHapticFeedbackEnabled = true 23 | public static let windowLevel:UIWindow.Level = .normal 24 | } 25 | 26 | let errorColor: UIColor 27 | let successColor: UIColor 28 | let infoColor: UIColor 29 | let titleColor: UIColor 30 | let messageColor: UIColor 31 | let isStatusBarHidden: Bool 32 | let successIcon: UIImage? 33 | let infoIcon: UIImage? 34 | let errorIcon: UIImage? 35 | let titleFont: UIFont 36 | let messageFont: UIFont 37 | let isHapticFeedbackEnabled: Bool 38 | let windowLevel: UIWindow.Level 39 | 40 | public init( 41 | errorColor: UIColor = Defaults.errorColor, 42 | successColor: UIColor = Defaults.successColor, 43 | infoColor: UIColor = Defaults.infoColor, 44 | titleColor: UIColor = Defaults.titleColor, 45 | messageColor: UIColor = Defaults.messageColor, 46 | isStatusBarHidden: Bool = Defaults.isStatusBarHidden, 47 | successIcon: UIImage? = nil, 48 | infoIcon: UIImage? = nil, 49 | errorIcon: UIImage? = nil, 50 | titleFont: UIFont = Defaults.titleFont, 51 | messageFont: UIFont = Defaults.messageFont, 52 | isHapticFeedbackEnabled: Bool = Defaults.isHapticFeedbackEnabled, 53 | windowLevel: UIWindow.Level = Defaults.windowLevel 54 | ) { 55 | self.errorColor = errorColor 56 | self.successColor = successColor 57 | self.infoColor = infoColor 58 | self.titleColor = titleColor 59 | self.messageColor = messageColor 60 | self.isStatusBarHidden = isStatusBarHidden 61 | let bundle: Bundle 62 | #if SWIFT_PACKAGE 63 | bundle = Bundle.module 64 | #else 65 | bundle = Bundle(for: SwiftMessageBar.self) 66 | #endif 67 | self.successIcon = successIcon ?? UIImage(named: "icon-success", in: bundle, compatibleWith: nil) 68 | self.infoIcon = infoIcon ?? UIImage(named: "icon-info", in: bundle, compatibleWith: nil) 69 | self.errorIcon = errorIcon ?? UIImage(named: "icon-error", in: bundle, compatibleWith: nil) 70 | self.titleFont = titleFont 71 | self.messageFont = messageFont 72 | self.isHapticFeedbackEnabled = isHapticFeedbackEnabled 73 | self.windowLevel = windowLevel 74 | } 75 | 76 | public class Builder { 77 | 78 | private var errorColor: UIColor? 79 | private var successColor: UIColor? 80 | private var infoColor: UIColor? 81 | private var titleColor: UIColor? 82 | private var messageColor: UIColor? 83 | private var isStatusBarHidden: Bool? 84 | private var successIcon: UIImage? 85 | private var infoIcon: UIImage? 86 | private var errorIcon: UIImage? 87 | private var titleFont: UIFont? 88 | private var messageFont: UIFont? 89 | private var isHapticFeedbackEnabled: Bool? 90 | private var windowLevel: UIWindow.Level? 91 | 92 | public init() {} 93 | 94 | public func withErrorColor(_ color: UIColor) -> Builder { 95 | errorColor = color 96 | return self 97 | } 98 | 99 | public func withSuccessColor(_ color: UIColor) -> Builder { 100 | successColor = color 101 | return self 102 | } 103 | 104 | public func withInfoColor(_ color: UIColor) -> Builder { 105 | infoColor = color 106 | return self 107 | } 108 | 109 | public func withTitleColor(_ color: UIColor) -> Builder { 110 | titleColor = color 111 | return self 112 | } 113 | 114 | public func withMessageColor(_ color: UIColor) -> Builder { 115 | messageColor = color 116 | return self 117 | } 118 | 119 | public func withStatusBarHidden(_ isHidden: Bool) -> Builder { 120 | isStatusBarHidden = isHidden 121 | return self 122 | } 123 | 124 | public func withSuccessIcon(_ icon: UIImage) -> Builder { 125 | successIcon = icon 126 | return self 127 | } 128 | 129 | public func withInfoIcon(_ icon: UIImage) -> Builder { 130 | infoIcon = icon 131 | return self 132 | } 133 | 134 | public func withErrorIcon(_ icon: UIImage) -> Builder { 135 | errorIcon = icon 136 | return self 137 | } 138 | 139 | public func withTitleFont(_ font: UIFont) -> Builder { 140 | titleFont = font 141 | return self 142 | } 143 | 144 | public func withMessageFont(_ font: UIFont) -> Builder { 145 | messageFont = font 146 | return self 147 | } 148 | 149 | public func withHapticFeedbackEnabled(_ isEnabled: Bool) -> Builder { 150 | isHapticFeedbackEnabled = isEnabled 151 | return self 152 | } 153 | 154 | public func withWindowLevel(_ level: UIWindow.Level) -> Builder { 155 | windowLevel = level 156 | return self 157 | } 158 | 159 | public func build() -> Config { 160 | Config( 161 | errorColor: errorColor ?? Defaults.errorColor, 162 | successColor: successColor ?? Defaults.successColor, 163 | infoColor: infoColor ?? Defaults.infoColor, 164 | titleColor: titleColor ?? Defaults.titleColor, 165 | messageColor: messageColor ?? Defaults.messageColor, 166 | isStatusBarHidden: isStatusBarHidden ?? Defaults.isStatusBarHidden, 167 | successIcon: successIcon, infoIcon: infoIcon, errorIcon: errorIcon, 168 | titleFont: titleFont ?? Defaults.titleFont, 169 | messageFont: messageFont ?? Defaults.messageFont, 170 | isHapticFeedbackEnabled: isHapticFeedbackEnabled ?? Defaults.isHapticFeedbackEnabled, 171 | windowLevel: windowLevel ?? Defaults.windowLevel 172 | ) 173 | } 174 | 175 | } 176 | 177 | } 178 | 179 | public static let sharedMessageBar = SwiftMessageBar() 180 | 181 | private static let showHideDuration: TimeInterval = 0.25 182 | 183 | private var config: Config 184 | private var messageWindow: MessageWindow? 185 | private var timer: Timer? 186 | 187 | public var tapHandler : (() -> Void)? 188 | 189 | private func newMessageWindow() -> MessageWindow { 190 | let messageWindow = MessageWindow() 191 | messageWindow.frame = UIScreen.main.bounds 192 | messageWindow.isHidden = false 193 | messageWindow.windowLevel = config.windowLevel 194 | messageWindow.backgroundColor = .clear 195 | messageWindow.messageBarController.statusBarHidden = config.isStatusBarHidden 196 | messageWindow.rootViewController = messageWindow.messageBarController 197 | return messageWindow 198 | } 199 | 200 | private var messageQueue: Queue 201 | private var isMessageVisible = false 202 | 203 | private init() { 204 | messageQueue = Queue() 205 | config = Config() 206 | } 207 | 208 | /// Set a message bar configuration used by all displayed messages. 209 | public static func setSharedConfig(_ config: Config) { 210 | sharedMessageBar.config = config 211 | } 212 | 213 | /// Display a message 214 | /// 215 | /// - Parameters: 216 | /// - title: An optional title 217 | /// - message: An optional message 218 | /// - type: The message type 219 | /// - duration: The time interval in seconds to show the message for 220 | /// - dismiss: Does the message automatically dismiss or not 221 | /// - languageDirection: Set an optional language direction if you require RTL support outside of what the system provides 222 | /// i.e. no need to set this parameter when NSLocale already is set to the proper languageDirection 223 | /// - accessoryView: An optional view to show in the right of the Message Bar 224 | /// - callback: An optional callback to execute when the user taps on a message to dismiss it. 225 | /// - Returns: A UUID for the message. Can be used to cancel the display of a specific message 226 | @discardableResult 227 | public static func showMessage( 228 | withTitle title: String? = nil, 229 | message: String? = nil, 230 | type: MessageType, 231 | duration: TimeInterval = 3, 232 | dismiss: Bool = true, 233 | languageDirection: NSLocale.LanguageDirection = .unknown, 234 | accessoryView: UIView? = nil, 235 | callback: Callback? = nil 236 | ) -> UUID { 237 | sharedMessageBar.showMessage( 238 | withTitle: title, 239 | message: message, 240 | type: type, 241 | duration: duration, 242 | dismiss: dismiss, 243 | languageDirection: languageDirection, 244 | accessoryView: accessoryView, 245 | callback: callback 246 | ) 247 | } 248 | 249 | /// Display a message 250 | /// 251 | /// - Parameters: 252 | /// - title: An optional title 253 | /// - message: An optional message 254 | /// - type: The message type 255 | /// - duration: The time interval in seconds to show the message for 256 | /// - dismiss: Does the message automatically dismiss or not 257 | /// - languageDirection: Set an optional language direction if you require RTL support outside of what the system provides 258 | /// i.e. no need to set this parameter when NSLocale already is set to the proper languageDirection 259 | /// - accessoryView: An optional view to show in the right of the Message Bar 260 | /// - callback: An optional callback to execute when the user taps on a message to dismiss it. 261 | /// - Returns: A UUID for the message. Can be used to cancel the display of a specific message 262 | @discardableResult 263 | public func showMessage( 264 | withTitle title: String? = nil, 265 | message: String? = nil, 266 | type: MessageType, 267 | duration: TimeInterval = 3, 268 | dismiss: Bool = true, 269 | languageDirection: NSLocale.LanguageDirection = .unknown, 270 | accessoryView: UIView? = nil, 271 | callback: Callback? = nil 272 | ) -> UUID { 273 | let message = Message( 274 | type: type, 275 | title: title, 276 | message: message, 277 | backgroundColor: type.backgroundColor(fromConfig: config), 278 | titleFontColor: config.titleColor, 279 | messageFontColor: config.messageColor, 280 | icon: type.image(fromConfig: config), 281 | duration: duration, 282 | dismiss: dismiss, 283 | callback: callback, 284 | languageDirection: languageDirection, 285 | titleFont: config.titleFont, 286 | messageFont: config.messageFont, 287 | accessoryView: accessoryView 288 | ) 289 | if languageDirection == .rightToLeft { 290 | message.flipHorizontal() 291 | } 292 | messageQueue.enqueue(message) 293 | if !isMessageVisible { 294 | dequeueNextMessage() 295 | } 296 | return message.id 297 | } 298 | 299 | /// Cancels the display of all messages. 300 | /// 301 | /// - Parameter force: A boolean to force immediate dismissal (without animation). Defaults to `false` 302 | public func cancelAll(force: Bool = false) { 303 | guard !isMessageVisible && messageQueue.isEmpty || force else { return } 304 | 305 | if let message = visibleMessage { 306 | if force { 307 | message.removeFromSuperview() 308 | messageWindow = nil 309 | } else { 310 | dismissMessage(message) 311 | } 312 | } 313 | resetTimer() 314 | isMessageVisible = false 315 | messageQueue.removeAll() 316 | } 317 | 318 | /// Cancels the display of a specific message 319 | /// 320 | /// - Parameter id: The UUID of the message to cancel. 321 | public func cancel(withId id: UUID) { 322 | if let message = visibleMessage, message.id == id { 323 | dismissMessage(message) 324 | messageQueue.removeElement(message) 325 | } 326 | } 327 | 328 | private var visibleMessage: Message? { 329 | messageWindow?.messageBarView.subviews.compactMap { $0 as? Message }.first 330 | } 331 | 332 | private func dequeueNextMessage() { 333 | guard let message = messageQueue.dequeue() else { return } 334 | 335 | let messageWindow: MessageWindow 336 | if let existensWindow = self.messageWindow { 337 | messageWindow = existensWindow 338 | } else { 339 | messageWindow = newMessageWindow() 340 | self.messageWindow = messageWindow 341 | } 342 | 343 | messageWindow.messageBarView.addSubview(message) 344 | messageWindow.messageBarView.bringSubviewToFront(message) 345 | isMessageVisible = true 346 | 347 | if #available(iOS 11, *) { 348 | message.configureSubviews(topAnchor: messageWindow.messageBarView.safeAreaLayoutGuide.topAnchor) 349 | } else { 350 | message.configureSubviews(topAnchor: messageWindow.messageBarController.topLayoutGuide.bottomAnchor) 351 | } 352 | 353 | message.setNeedsUpdateConstraints() 354 | 355 | let gesture = UITapGestureRecognizer(target: self, action: #selector(tap)) 356 | message.addGestureRecognizer(gesture) 357 | 358 | message.transform = CGAffineTransform(translationX: 0, y: -messageWindow.frame.height) 359 | DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { 360 | message.transform = CGAffineTransform(translationX: 0, y: -message.frame.height) 361 | UIView.animate( 362 | withDuration: SwiftMessageBar.showHideDuration, 363 | animations: { 364 | message.transform = .identity 365 | }, 366 | completion: { _ in 367 | self.provideHapticFeedback(for: message) 368 | } 369 | ) 370 | } 371 | 372 | if message.dismiss { 373 | resetTimer() 374 | timer = Timer.scheduledTimer( 375 | timeInterval: message.duration, 376 | target: self, 377 | selector: #selector(dismiss), 378 | userInfo: nil, 379 | repeats: false 380 | ) 381 | } 382 | } 383 | 384 | private func provideHapticFeedback(for message: Message) { 385 | if #available(iOS 10.0, *), config.isHapticFeedbackEnabled && DeviceType.isPhone { 386 | let generator = UINotificationFeedbackGenerator() 387 | switch message.type! { 388 | case .error: 389 | generator.notificationOccurred(.error) 390 | case .info: 391 | generator.notificationOccurred(.warning) 392 | case .success: 393 | generator.notificationOccurred(.success) 394 | } 395 | } 396 | } 397 | 398 | private func resetTimer() { 399 | timer?.invalidate() 400 | timer = nil 401 | } 402 | 403 | @objc 404 | private func dismiss() { 405 | resetTimer() 406 | if let message = visibleMessage { 407 | dismissMessage(message) 408 | } 409 | } 410 | 411 | private func dismissMessage(_ message: Message) { 412 | dismissMessage(message, fromGesture: false) 413 | } 414 | 415 | @objc 416 | private func tap(_ gesture: UITapGestureRecognizer) { 417 | let message = gesture.view as! Message 418 | dismissMessage(message, fromGesture: true) 419 | tapHandler?() 420 | } 421 | 422 | private func dismissMessage(_ message: Message, fromGesture: Bool) { 423 | if message.isHit { 424 | return 425 | } 426 | 427 | message.isHit = true 428 | 429 | UIView.animate( 430 | withDuration: SwiftMessageBar.showHideDuration, 431 | delay: 0, 432 | options: [], 433 | animations: { 434 | message.transform = CGAffineTransform(translationX: 0, y: -message.frame.height) 435 | }, 436 | completion: { [weak self] _ in 437 | self?.isMessageVisible = false 438 | message.removeFromSuperview() 439 | 440 | if fromGesture { 441 | message.callback?() 442 | } 443 | 444 | if let messageBar = self , 445 | !messageBar.messageQueue.isEmpty { 446 | messageBar.dequeueNextMessage() 447 | } else { 448 | self?.resetTimer() 449 | self?.messageWindow = nil 450 | } 451 | } 452 | ) 453 | } 454 | 455 | } 456 | 457 | private class MessageWindow: UIWindow { 458 | 459 | lazy var messageBarController = MessageBarController() 460 | 461 | var messageBarView: UIView { 462 | messageBarController.view 463 | } 464 | 465 | override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { 466 | var hitView = super.hitTest(point, with: event) 467 | if hitView == rootViewController?.view { 468 | hitView = nil 469 | } 470 | return hitView 471 | } 472 | 473 | } 474 | 475 | private class MessageBarController: UIViewController { 476 | 477 | var statusBarStyle: UIStatusBarStyle = .default { 478 | didSet { 479 | setNeedsStatusBarAppearanceUpdate() 480 | } 481 | } 482 | 483 | var statusBarHidden: Bool = false { 484 | didSet { 485 | setNeedsStatusBarAppearanceUpdate() 486 | } 487 | } 488 | 489 | override var preferredStatusBarStyle: UIStatusBarStyle { 490 | statusBarStyle 491 | } 492 | 493 | override var prefersStatusBarHidden: Bool { 494 | statusBarHidden 495 | } 496 | 497 | } 498 | 499 | private enum DeviceType { 500 | static let isPhone = UIDevice.current.userInterfaceIdiom == .phone 501 | } 502 | -------------------------------------------------------------------------------- /SwiftMessageBarTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /SwiftMessageBarTests/QueueTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2020 Schnaub. All rights reserved. 3 | // 4 | 5 | @testable import SwiftMessageBar 6 | import XCTest 7 | 8 | final class QueueTests: XCTestCase { 9 | 10 | func testEmpty() { 11 | var queue = Queue() 12 | 13 | XCTAssertTrue(queue.isEmpty) 14 | XCTAssertNil(queue.dequeue()) 15 | } 16 | 17 | func testEnqueueDequeue() { 18 | var queue = Queue() 19 | queue.enqueue("foo") 20 | queue.enqueue("bar") 21 | 22 | XCTAssertEqual(queue.dequeue(), "foo") 23 | XCTAssertEqual(queue.dequeue(), "bar") 24 | XCTAssertNil(queue.dequeue()) 25 | } 26 | 27 | func testRemoveAll() { 28 | var queue = Queue() 29 | queue.enqueue("foo") 30 | queue.enqueue("bar") 31 | 32 | queue.removeAll() 33 | 34 | XCTAssertNil(queue.dequeue()) 35 | } 36 | 37 | func testRemoveElement() { 38 | var queue = Queue() 39 | queue.enqueue("foo") 40 | queue.enqueue("bar") 41 | queue.enqueue("baz") 42 | queue.enqueue("bat") 43 | 44 | queue.removeElement("foo") 45 | 46 | XCTAssertEqual(queue.dequeue(), "bar") 47 | 48 | queue.removeElement("baz") 49 | 50 | XCTAssertEqual(queue.dequeue(), "bat") 51 | } 52 | 53 | } 54 | --------------------------------------------------------------------------------