├── .gitignore ├── .swift-version ├── .travis.yml ├── Example ├── Example.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ ├── SwiftOverlays-example-debug.xcscheme │ │ └── SwiftOverlays.xcscheme ├── Example │ ├── AnnoyingNotification.xib │ ├── AppDelegate.swift │ ├── Base.lproj │ │ ├── LaunchScreen.xib │ │ └── Main.storyboard │ ├── Example-Bridging-Header.h │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── close.imageset │ │ │ ├── Contents.json │ │ │ └── closeSlide@2x.png │ │ └── twitter.imageset │ │ │ ├── Contents.json │ │ │ └── twi.png │ ├── Info.plist │ ├── MasterVC.swift │ ├── OverlayExampleVC.swift │ └── Res │ │ └── Loading@2x.gif ├── ExampleTests │ ├── ExampleTests.swift │ └── Info.plist └── PPSwiftGifs │ └── PPSwiftGifs.swift ├── LICENSE ├── README.md ├── SwiftOverlays.podspec └── SwiftOverlays ├── Info.plist ├── SwiftOverlays.h └── SwiftOverlays.swift /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | *.xcworkspace 13 | !default.xcworkspace 14 | xcuserdata 15 | profile 16 | *.moved-aside 17 | DerivedData 18 | .idea/ 19 | # Pods - for those of you who use CocoaPods 20 | Pods 21 | -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 4.2 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode10 3 | env: 4 | global: 5 | - APP_NAME="SwiftOverlays" 6 | script: 7 | - xcodebuild -project Example/Example.xcodeproj -scheme SwiftOverlays-example-debug -destination 'platform=iOS Simulator,name=iPhone X,OS=12.0' test 8 | -------------------------------------------------------------------------------- /Example/Example.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 0D3755511C674336002C2B7F /* SwiftOverlays.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DEE76E519F14A4C00F6F7A7 /* SwiftOverlays.swift */; }; 11 | 0D9008571C673D0D003D334A /* SwiftOverlays.h in Headers */ = {isa = PBXBuildFile; fileRef = 0D9008551C673D0D003D334A /* SwiftOverlays.h */; settings = {ATTRIBUTES = (Public, ); }; }; 12 | 0DC790E71A14F3180097EB37 /* PPSwiftGifs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DC790E61A14F3180097EB37 /* PPSwiftGifs.swift */; }; 13 | 0DC790E91A14F32F0097EB37 /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0DC790E81A14F32F0097EB37 /* ImageIO.framework */; }; 14 | 0DC790EE1A14F6AA0097EB37 /* Loading@2x.gif in Resources */ = {isa = PBXBuildFile; fileRef = 0DC790ED1A14F6AA0097EB37 /* Loading@2x.gif */; }; 15 | 0DC7A86A19F15EC90022AC95 /* AnnoyingNotification.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0DC7A86919F15EC90022AC95 /* AnnoyingNotification.xib */; }; 16 | 0DEE2E601AD3D39D00DDCC32 /* .travis.yml in Resources */ = {isa = PBXBuildFile; fileRef = 0DEE2E5F1AD3D39D00DDCC32 /* .travis.yml */; }; 17 | 0DEE76C319F14A0800F6F7A7 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DEE76C219F14A0800F6F7A7 /* AppDelegate.swift */; }; 18 | 0DEE76C519F14A0800F6F7A7 /* MasterVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DEE76C419F14A0800F6F7A7 /* MasterVC.swift */; }; 19 | 0DEE76CA19F14A0800F6F7A7 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0DEE76C819F14A0800F6F7A7 /* Main.storyboard */; }; 20 | 0DEE76CC19F14A0800F6F7A7 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0DEE76CB19F14A0800F6F7A7 /* Images.xcassets */; }; 21 | 0DEE76CF19F14A0800F6F7A7 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0DEE76CD19F14A0800F6F7A7 /* LaunchScreen.xib */; }; 22 | 0DEE76DB19F14A0800F6F7A7 /* ExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DEE76DA19F14A0800F6F7A7 /* ExampleTests.swift */; }; 23 | 0DEE76E619F14A4C00F6F7A7 /* SwiftOverlays.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DEE76E519F14A4C00F6F7A7 /* SwiftOverlays.swift */; }; 24 | 0DEE76E819F14D5F00F6F7A7 /* OverlayExampleVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DEE76E719F14D5F00F6F7A7 /* OverlayExampleVC.swift */; }; 25 | /* End PBXBuildFile section */ 26 | 27 | /* Begin PBXContainerItemProxy section */ 28 | 0DEE76D519F14A0800F6F7A7 /* PBXContainerItemProxy */ = { 29 | isa = PBXContainerItemProxy; 30 | containerPortal = 0DEE76B519F14A0800F6F7A7 /* Project object */; 31 | proxyType = 1; 32 | remoteGlobalIDString = 0DEE76BC19F14A0800F6F7A7; 33 | remoteInfo = Example; 34 | }; 35 | /* End PBXContainerItemProxy section */ 36 | 37 | /* Begin PBXFileReference section */ 38 | 0D90083D1C673C87003D334A /* SwiftOverlays.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftOverlays.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 39 | 0D9008541C673D0D003D334A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 40 | 0D9008551C673D0D003D334A /* SwiftOverlays.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SwiftOverlays.h; sourceTree = ""; }; 41 | 0DC790E61A14F3180097EB37 /* PPSwiftGifs.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PPSwiftGifs.swift; sourceTree = ""; }; 42 | 0DC790E81A14F32F0097EB37 /* ImageIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = System/Library/Frameworks/ImageIO.framework; sourceTree = SDKROOT; }; 43 | 0DC790EB1A14F6740097EB37 /* Example-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Example-Bridging-Header.h"; sourceTree = ""; }; 44 | 0DC790ED1A14F6AA0097EB37 /* Loading@2x.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = "Loading@2x.gif"; sourceTree = ""; }; 45 | 0DC7A86919F15EC90022AC95 /* AnnoyingNotification.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AnnoyingNotification.xib; sourceTree = ""; }; 46 | 0DEE2E5F1AD3D39D00DDCC32 /* .travis.yml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = .travis.yml; path = ../../.travis.yml; sourceTree = ""; }; 47 | 0DEE76BD19F14A0800F6F7A7 /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 48 | 0DEE76C119F14A0800F6F7A7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 49 | 0DEE76C219F14A0800F6F7A7 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 50 | 0DEE76C419F14A0800F6F7A7 /* MasterVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MasterVC.swift; sourceTree = ""; }; 51 | 0DEE76C919F14A0800F6F7A7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 52 | 0DEE76CB19F14A0800F6F7A7 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 53 | 0DEE76CE19F14A0800F6F7A7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 54 | 0DEE76D419F14A0800F6F7A7 /* ExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 55 | 0DEE76D919F14A0800F6F7A7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 56 | 0DEE76DA19F14A0800F6F7A7 /* ExampleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExampleTests.swift; sourceTree = ""; }; 57 | 0DEE76E519F14A4C00F6F7A7 /* SwiftOverlays.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftOverlays.swift; sourceTree = ""; }; 58 | 0DEE76E719F14D5F00F6F7A7 /* OverlayExampleVC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OverlayExampleVC.swift; sourceTree = ""; }; 59 | /* End PBXFileReference section */ 60 | 61 | /* Begin PBXFrameworksBuildPhase section */ 62 | 0D9008391C673C87003D334A /* Frameworks */ = { 63 | isa = PBXFrameworksBuildPhase; 64 | buildActionMask = 2147483647; 65 | files = ( 66 | ); 67 | runOnlyForDeploymentPostprocessing = 0; 68 | }; 69 | 0DEE76BA19F14A0800F6F7A7 /* Frameworks */ = { 70 | isa = PBXFrameworksBuildPhase; 71 | buildActionMask = 2147483647; 72 | files = ( 73 | 0DC790E91A14F32F0097EB37 /* ImageIO.framework in Frameworks */, 74 | ); 75 | runOnlyForDeploymentPostprocessing = 0; 76 | }; 77 | 0DEE76D119F14A0800F6F7A7 /* Frameworks */ = { 78 | isa = PBXFrameworksBuildPhase; 79 | buildActionMask = 2147483647; 80 | files = ( 81 | ); 82 | runOnlyForDeploymentPostprocessing = 0; 83 | }; 84 | /* End PBXFrameworksBuildPhase section */ 85 | 86 | /* Begin PBXGroup section */ 87 | 0DC790E51A14F3180097EB37 /* PPSwiftGifs */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | 0DC790E61A14F3180097EB37 /* PPSwiftGifs.swift */, 91 | ); 92 | path = PPSwiftGifs; 93 | sourceTree = ""; 94 | }; 95 | 0DC790EC1A14F6A30097EB37 /* Res */ = { 96 | isa = PBXGroup; 97 | children = ( 98 | 0DC790ED1A14F6AA0097EB37 /* Loading@2x.gif */, 99 | ); 100 | path = Res; 101 | sourceTree = ""; 102 | }; 103 | 0DEE76B419F14A0800F6F7A7 = { 104 | isa = PBXGroup; 105 | children = ( 106 | 0DC790E81A14F32F0097EB37 /* ImageIO.framework */, 107 | 0DC790E51A14F3180097EB37 /* PPSwiftGifs */, 108 | 0DEE76E419F14A4C00F6F7A7 /* SwiftOverlays */, 109 | 0DEE76BF19F14A0800F6F7A7 /* Example */, 110 | 0DEE76D719F14A0800F6F7A7 /* ExampleTests */, 111 | 0DEE76BE19F14A0800F6F7A7 /* Products */, 112 | ); 113 | sourceTree = ""; 114 | }; 115 | 0DEE76BE19F14A0800F6F7A7 /* Products */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | 0DEE76BD19F14A0800F6F7A7 /* Example.app */, 119 | 0DEE76D419F14A0800F6F7A7 /* ExampleTests.xctest */, 120 | 0D90083D1C673C87003D334A /* SwiftOverlays.framework */, 121 | ); 122 | name = Products; 123 | sourceTree = ""; 124 | }; 125 | 0DEE76BF19F14A0800F6F7A7 /* Example */ = { 126 | isa = PBXGroup; 127 | children = ( 128 | 0DEE2E5F1AD3D39D00DDCC32 /* .travis.yml */, 129 | 0DC790EC1A14F6A30097EB37 /* Res */, 130 | 0DC790EB1A14F6740097EB37 /* Example-Bridging-Header.h */, 131 | 0DEE76E719F14D5F00F6F7A7 /* OverlayExampleVC.swift */, 132 | 0DEE76C219F14A0800F6F7A7 /* AppDelegate.swift */, 133 | 0DEE76C419F14A0800F6F7A7 /* MasterVC.swift */, 134 | 0DC7A86919F15EC90022AC95 /* AnnoyingNotification.xib */, 135 | 0DEE76C819F14A0800F6F7A7 /* Main.storyboard */, 136 | 0DEE76CB19F14A0800F6F7A7 /* Images.xcassets */, 137 | 0DEE76CD19F14A0800F6F7A7 /* LaunchScreen.xib */, 138 | 0DEE76C019F14A0800F6F7A7 /* Supporting Files */, 139 | ); 140 | path = Example; 141 | sourceTree = ""; 142 | }; 143 | 0DEE76C019F14A0800F6F7A7 /* Supporting Files */ = { 144 | isa = PBXGroup; 145 | children = ( 146 | 0DEE76C119F14A0800F6F7A7 /* Info.plist */, 147 | ); 148 | name = "Supporting Files"; 149 | sourceTree = ""; 150 | }; 151 | 0DEE76D719F14A0800F6F7A7 /* ExampleTests */ = { 152 | isa = PBXGroup; 153 | children = ( 154 | 0DEE76DA19F14A0800F6F7A7 /* ExampleTests.swift */, 155 | 0DEE76D819F14A0800F6F7A7 /* Supporting Files */, 156 | ); 157 | path = ExampleTests; 158 | sourceTree = ""; 159 | }; 160 | 0DEE76D819F14A0800F6F7A7 /* Supporting Files */ = { 161 | isa = PBXGroup; 162 | children = ( 163 | 0DEE76D919F14A0800F6F7A7 /* Info.plist */, 164 | ); 165 | name = "Supporting Files"; 166 | sourceTree = ""; 167 | }; 168 | 0DEE76E419F14A4C00F6F7A7 /* SwiftOverlays */ = { 169 | isa = PBXGroup; 170 | children = ( 171 | 0D9008541C673D0D003D334A /* Info.plist */, 172 | 0D9008551C673D0D003D334A /* SwiftOverlays.h */, 173 | 0DEE76E519F14A4C00F6F7A7 /* SwiftOverlays.swift */, 174 | ); 175 | name = SwiftOverlays; 176 | path = ../SwiftOverlays; 177 | sourceTree = ""; 178 | }; 179 | /* End PBXGroup section */ 180 | 181 | /* Begin PBXHeadersBuildPhase section */ 182 | 0D90083A1C673C87003D334A /* Headers */ = { 183 | isa = PBXHeadersBuildPhase; 184 | buildActionMask = 2147483647; 185 | files = ( 186 | 0D9008571C673D0D003D334A /* SwiftOverlays.h in Headers */, 187 | ); 188 | runOnlyForDeploymentPostprocessing = 0; 189 | }; 190 | /* End PBXHeadersBuildPhase section */ 191 | 192 | /* Begin PBXNativeTarget section */ 193 | 0D90083C1C673C87003D334A /* SwiftOverlays */ = { 194 | isa = PBXNativeTarget; 195 | buildConfigurationList = 0D9008521C673C87003D334A /* Build configuration list for PBXNativeTarget "SwiftOverlays" */; 196 | buildPhases = ( 197 | 0D9008381C673C87003D334A /* Sources */, 198 | 0D9008391C673C87003D334A /* Frameworks */, 199 | 0D90083A1C673C87003D334A /* Headers */, 200 | 0D90083B1C673C87003D334A /* Resources */, 201 | ); 202 | buildRules = ( 203 | ); 204 | dependencies = ( 205 | ); 206 | name = SwiftOverlays; 207 | productName = SwiftOverlays; 208 | productReference = 0D90083D1C673C87003D334A /* SwiftOverlays.framework */; 209 | productType = "com.apple.product-type.framework"; 210 | }; 211 | 0DEE76BC19F14A0800F6F7A7 /* Example */ = { 212 | isa = PBXNativeTarget; 213 | buildConfigurationList = 0DEE76DE19F14A0800F6F7A7 /* Build configuration list for PBXNativeTarget "Example" */; 214 | buildPhases = ( 215 | 0DEE76B919F14A0800F6F7A7 /* Sources */, 216 | 0DEE76BA19F14A0800F6F7A7 /* Frameworks */, 217 | 0DEE76BB19F14A0800F6F7A7 /* Resources */, 218 | ); 219 | buildRules = ( 220 | ); 221 | dependencies = ( 222 | ); 223 | name = Example; 224 | productName = Example; 225 | productReference = 0DEE76BD19F14A0800F6F7A7 /* Example.app */; 226 | productType = "com.apple.product-type.application"; 227 | }; 228 | 0DEE76D319F14A0800F6F7A7 /* ExampleTests */ = { 229 | isa = PBXNativeTarget; 230 | buildConfigurationList = 0DEE76E119F14A0800F6F7A7 /* Build configuration list for PBXNativeTarget "ExampleTests" */; 231 | buildPhases = ( 232 | 0DEE76D019F14A0800F6F7A7 /* Sources */, 233 | 0DEE76D119F14A0800F6F7A7 /* Frameworks */, 234 | 0DEE76D219F14A0800F6F7A7 /* Resources */, 235 | ); 236 | buildRules = ( 237 | ); 238 | dependencies = ( 239 | 0DEE76D619F14A0800F6F7A7 /* PBXTargetDependency */, 240 | ); 241 | name = ExampleTests; 242 | productName = ExampleTests; 243 | productReference = 0DEE76D419F14A0800F6F7A7 /* ExampleTests.xctest */; 244 | productType = "com.apple.product-type.bundle.unit-test"; 245 | }; 246 | /* End PBXNativeTarget section */ 247 | 248 | /* Begin PBXProject section */ 249 | 0DEE76B519F14A0800F6F7A7 /* Project object */ = { 250 | isa = PBXProject; 251 | attributes = { 252 | LastSwiftMigration = 0700; 253 | LastSwiftUpdateCheck = 0710; 254 | LastUpgradeCheck = 0940; 255 | TargetAttributes = { 256 | 0D90083C1C673C87003D334A = { 257 | CreatedOnToolsVersion = 7.1; 258 | LastSwiftMigration = 0800; 259 | }; 260 | 0DEE76BC19F14A0800F6F7A7 = { 261 | CreatedOnToolsVersion = 6.0.1; 262 | DevelopmentTeam = 97H7M775CZ; 263 | LastSwiftMigration = 1000; 264 | }; 265 | 0DEE76D319F14A0800F6F7A7 = { 266 | CreatedOnToolsVersion = 6.0.1; 267 | LastSwiftMigration = 1000; 268 | TestTargetID = 0DEE76BC19F14A0800F6F7A7; 269 | }; 270 | }; 271 | }; 272 | buildConfigurationList = 0DEE76B819F14A0800F6F7A7 /* Build configuration list for PBXProject "Example" */; 273 | compatibilityVersion = "Xcode 3.2"; 274 | developmentRegion = English; 275 | hasScannedForEncodings = 0; 276 | knownRegions = ( 277 | en, 278 | Base, 279 | ); 280 | mainGroup = 0DEE76B419F14A0800F6F7A7; 281 | productRefGroup = 0DEE76BE19F14A0800F6F7A7 /* Products */; 282 | projectDirPath = ""; 283 | projectRoot = ""; 284 | targets = ( 285 | 0DEE76BC19F14A0800F6F7A7 /* Example */, 286 | 0DEE76D319F14A0800F6F7A7 /* ExampleTests */, 287 | 0D90083C1C673C87003D334A /* SwiftOverlays */, 288 | ); 289 | }; 290 | /* End PBXProject section */ 291 | 292 | /* Begin PBXResourcesBuildPhase section */ 293 | 0D90083B1C673C87003D334A /* Resources */ = { 294 | isa = PBXResourcesBuildPhase; 295 | buildActionMask = 2147483647; 296 | files = ( 297 | ); 298 | runOnlyForDeploymentPostprocessing = 0; 299 | }; 300 | 0DEE76BB19F14A0800F6F7A7 /* Resources */ = { 301 | isa = PBXResourcesBuildPhase; 302 | buildActionMask = 2147483647; 303 | files = ( 304 | 0DEE2E601AD3D39D00DDCC32 /* .travis.yml in Resources */, 305 | 0DEE76CA19F14A0800F6F7A7 /* Main.storyboard in Resources */, 306 | 0DEE76CF19F14A0800F6F7A7 /* LaunchScreen.xib in Resources */, 307 | 0DC790EE1A14F6AA0097EB37 /* Loading@2x.gif in Resources */, 308 | 0DEE76CC19F14A0800F6F7A7 /* Images.xcassets in Resources */, 309 | 0DC7A86A19F15EC90022AC95 /* AnnoyingNotification.xib in Resources */, 310 | ); 311 | runOnlyForDeploymentPostprocessing = 0; 312 | }; 313 | 0DEE76D219F14A0800F6F7A7 /* Resources */ = { 314 | isa = PBXResourcesBuildPhase; 315 | buildActionMask = 2147483647; 316 | files = ( 317 | ); 318 | runOnlyForDeploymentPostprocessing = 0; 319 | }; 320 | /* End PBXResourcesBuildPhase section */ 321 | 322 | /* Begin PBXSourcesBuildPhase section */ 323 | 0D9008381C673C87003D334A /* Sources */ = { 324 | isa = PBXSourcesBuildPhase; 325 | buildActionMask = 2147483647; 326 | files = ( 327 | 0D3755511C674336002C2B7F /* SwiftOverlays.swift in Sources */, 328 | ); 329 | runOnlyForDeploymentPostprocessing = 0; 330 | }; 331 | 0DEE76B919F14A0800F6F7A7 /* Sources */ = { 332 | isa = PBXSourcesBuildPhase; 333 | buildActionMask = 2147483647; 334 | files = ( 335 | 0DEE76E619F14A4C00F6F7A7 /* SwiftOverlays.swift in Sources */, 336 | 0DEE76E819F14D5F00F6F7A7 /* OverlayExampleVC.swift in Sources */, 337 | 0DEE76C519F14A0800F6F7A7 /* MasterVC.swift in Sources */, 338 | 0DC790E71A14F3180097EB37 /* PPSwiftGifs.swift in Sources */, 339 | 0DEE76C319F14A0800F6F7A7 /* AppDelegate.swift in Sources */, 340 | ); 341 | runOnlyForDeploymentPostprocessing = 0; 342 | }; 343 | 0DEE76D019F14A0800F6F7A7 /* Sources */ = { 344 | isa = PBXSourcesBuildPhase; 345 | buildActionMask = 2147483647; 346 | files = ( 347 | 0DEE76DB19F14A0800F6F7A7 /* ExampleTests.swift in Sources */, 348 | ); 349 | runOnlyForDeploymentPostprocessing = 0; 350 | }; 351 | /* End PBXSourcesBuildPhase section */ 352 | 353 | /* Begin PBXTargetDependency section */ 354 | 0DEE76D619F14A0800F6F7A7 /* PBXTargetDependency */ = { 355 | isa = PBXTargetDependency; 356 | target = 0DEE76BC19F14A0800F6F7A7 /* Example */; 357 | targetProxy = 0DEE76D519F14A0800F6F7A7 /* PBXContainerItemProxy */; 358 | }; 359 | /* End PBXTargetDependency section */ 360 | 361 | /* Begin PBXVariantGroup section */ 362 | 0DEE76C819F14A0800F6F7A7 /* Main.storyboard */ = { 363 | isa = PBXVariantGroup; 364 | children = ( 365 | 0DEE76C919F14A0800F6F7A7 /* Base */, 366 | ); 367 | name = Main.storyboard; 368 | sourceTree = ""; 369 | }; 370 | 0DEE76CD19F14A0800F6F7A7 /* LaunchScreen.xib */ = { 371 | isa = PBXVariantGroup; 372 | children = ( 373 | 0DEE76CE19F14A0800F6F7A7 /* Base */, 374 | ); 375 | name = LaunchScreen.xib; 376 | sourceTree = ""; 377 | }; 378 | /* End PBXVariantGroup section */ 379 | 380 | /* Begin XCBuildConfiguration section */ 381 | 0D90084E1C673C87003D334A /* Debug */ = { 382 | isa = XCBuildConfiguration; 383 | buildSettings = { 384 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 385 | CURRENT_PROJECT_VERSION = 1; 386 | DEBUG_INFORMATION_FORMAT = dwarf; 387 | DEFINES_MODULE = YES; 388 | DYLIB_COMPATIBILITY_VERSION = 1; 389 | DYLIB_CURRENT_VERSION = 1; 390 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 391 | ENABLE_TESTABILITY = YES; 392 | GCC_NO_COMMON_BLOCKS = YES; 393 | HEADER_SEARCH_PATHS = ""; 394 | INFOPLIST_FILE = "$(SRCROOT)/../SwiftOverlays/Info.plist"; 395 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 396 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 397 | PRODUCT_BUNDLE_IDENTIFIER = Prokop.SwiftOverlays; 398 | PRODUCT_NAME = "$(TARGET_NAME)"; 399 | SKIP_INSTALL = YES; 400 | TARGETED_DEVICE_FAMILY = "1,2"; 401 | VERSIONING_SYSTEM = "apple-generic"; 402 | VERSION_INFO_PREFIX = ""; 403 | }; 404 | name = Debug; 405 | }; 406 | 0D90084F1C673C87003D334A /* Release */ = { 407 | isa = XCBuildConfiguration; 408 | buildSettings = { 409 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 410 | COPY_PHASE_STRIP = NO; 411 | CURRENT_PROJECT_VERSION = 1; 412 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 413 | DEFINES_MODULE = YES; 414 | DYLIB_COMPATIBILITY_VERSION = 1; 415 | DYLIB_CURRENT_VERSION = 1; 416 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 417 | GCC_NO_COMMON_BLOCKS = YES; 418 | HEADER_SEARCH_PATHS = ""; 419 | INFOPLIST_FILE = "$(SRCROOT)/../SwiftOverlays/Info.plist"; 420 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 421 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 422 | PRODUCT_BUNDLE_IDENTIFIER = Prokop.SwiftOverlays; 423 | PRODUCT_NAME = "$(TARGET_NAME)"; 424 | SKIP_INSTALL = YES; 425 | TARGETED_DEVICE_FAMILY = "1,2"; 426 | VERSIONING_SYSTEM = "apple-generic"; 427 | VERSION_INFO_PREFIX = ""; 428 | }; 429 | name = Release; 430 | }; 431 | 0DEE76DC19F14A0800F6F7A7 /* Debug */ = { 432 | isa = XCBuildConfiguration; 433 | buildSettings = { 434 | ALWAYS_SEARCH_USER_PATHS = NO; 435 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 436 | CLANG_CXX_LIBRARY = "libc++"; 437 | CLANG_ENABLE_MODULES = YES; 438 | CLANG_ENABLE_OBJC_ARC = YES; 439 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 440 | CLANG_WARN_BOOL_CONVERSION = YES; 441 | CLANG_WARN_COMMA = YES; 442 | CLANG_WARN_CONSTANT_CONVERSION = YES; 443 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 444 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 445 | CLANG_WARN_EMPTY_BODY = YES; 446 | CLANG_WARN_ENUM_CONVERSION = YES; 447 | CLANG_WARN_INFINITE_RECURSION = YES; 448 | CLANG_WARN_INT_CONVERSION = YES; 449 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 450 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 451 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 452 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 453 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 454 | CLANG_WARN_STRICT_PROTOTYPES = YES; 455 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 456 | CLANG_WARN_UNREACHABLE_CODE = YES; 457 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 458 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 459 | COPY_PHASE_STRIP = NO; 460 | ENABLE_STRICT_OBJC_MSGSEND = YES; 461 | ENABLE_TESTABILITY = YES; 462 | GCC_C_LANGUAGE_STANDARD = gnu99; 463 | GCC_DYNAMIC_NO_PIC = NO; 464 | GCC_NO_COMMON_BLOCKS = YES; 465 | GCC_OPTIMIZATION_LEVEL = 0; 466 | GCC_PREPROCESSOR_DEFINITIONS = ( 467 | "DEBUG=1", 468 | "$(inherited)", 469 | ); 470 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 471 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 472 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 473 | GCC_WARN_UNDECLARED_SELECTOR = YES; 474 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 475 | GCC_WARN_UNUSED_FUNCTION = YES; 476 | GCC_WARN_UNUSED_VARIABLE = YES; 477 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 478 | MTL_ENABLE_DEBUG_INFO = YES; 479 | ONLY_ACTIVE_ARCH = YES; 480 | SDKROOT = iphoneos; 481 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 482 | SWIFT_VERSION = 4.2; 483 | }; 484 | name = Debug; 485 | }; 486 | 0DEE76DD19F14A0800F6F7A7 /* Release */ = { 487 | isa = XCBuildConfiguration; 488 | buildSettings = { 489 | ALWAYS_SEARCH_USER_PATHS = NO; 490 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 491 | CLANG_CXX_LIBRARY = "libc++"; 492 | CLANG_ENABLE_MODULES = YES; 493 | CLANG_ENABLE_OBJC_ARC = YES; 494 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 495 | CLANG_WARN_BOOL_CONVERSION = YES; 496 | CLANG_WARN_COMMA = YES; 497 | CLANG_WARN_CONSTANT_CONVERSION = YES; 498 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 499 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 500 | CLANG_WARN_EMPTY_BODY = YES; 501 | CLANG_WARN_ENUM_CONVERSION = YES; 502 | CLANG_WARN_INFINITE_RECURSION = YES; 503 | CLANG_WARN_INT_CONVERSION = YES; 504 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 505 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 506 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 507 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 508 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 509 | CLANG_WARN_STRICT_PROTOTYPES = YES; 510 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 511 | CLANG_WARN_UNREACHABLE_CODE = YES; 512 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 513 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 514 | COPY_PHASE_STRIP = YES; 515 | ENABLE_NS_ASSERTIONS = NO; 516 | ENABLE_STRICT_OBJC_MSGSEND = YES; 517 | GCC_C_LANGUAGE_STANDARD = gnu99; 518 | GCC_NO_COMMON_BLOCKS = YES; 519 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 520 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 521 | GCC_WARN_UNDECLARED_SELECTOR = YES; 522 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 523 | GCC_WARN_UNUSED_FUNCTION = YES; 524 | GCC_WARN_UNUSED_VARIABLE = YES; 525 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 526 | MTL_ENABLE_DEBUG_INFO = NO; 527 | SDKROOT = iphoneos; 528 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 529 | SWIFT_VERSION = 4.2; 530 | VALIDATE_PRODUCT = YES; 531 | }; 532 | name = Release; 533 | }; 534 | 0DEE76DF19F14A0800F6F7A7 /* Debug */ = { 535 | isa = XCBuildConfiguration; 536 | buildSettings = { 537 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 538 | CODE_SIGN_IDENTITY = "iPhone Developer"; 539 | INFOPLIST_FILE = Example/Info.plist; 540 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 541 | PRODUCT_BUNDLE_IDENTIFIER = "SwiftOverlays.$(PRODUCT_NAME:rfc1034identifier)"; 542 | PRODUCT_NAME = "$(TARGET_NAME)"; 543 | SWIFT_OBJC_BRIDGING_HEADER = "Example/Example-Bridging-Header.h"; 544 | }; 545 | name = Debug; 546 | }; 547 | 0DEE76E019F14A0800F6F7A7 /* Release */ = { 548 | isa = XCBuildConfiguration; 549 | buildSettings = { 550 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 551 | CODE_SIGN_IDENTITY = "iPhone Developer"; 552 | INFOPLIST_FILE = Example/Info.plist; 553 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 554 | PRODUCT_BUNDLE_IDENTIFIER = "SwiftOverlays.$(PRODUCT_NAME:rfc1034identifier)"; 555 | PRODUCT_NAME = "$(TARGET_NAME)"; 556 | SWIFT_OBJC_BRIDGING_HEADER = "Example/Example-Bridging-Header.h"; 557 | }; 558 | name = Release; 559 | }; 560 | 0DEE76E219F14A0800F6F7A7 /* Debug */ = { 561 | isa = XCBuildConfiguration; 562 | buildSettings = { 563 | BUNDLE_LOADER = "$(TEST_HOST)"; 564 | GCC_PREPROCESSOR_DEFINITIONS = ( 565 | "DEBUG=1", 566 | "$(inherited)", 567 | ); 568 | INFOPLIST_FILE = ExampleTests/Info.plist; 569 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 570 | PRODUCT_BUNDLE_IDENTIFIER = "SwiftOverlays.$(PRODUCT_NAME:rfc1034identifier)"; 571 | PRODUCT_NAME = "$(TARGET_NAME)"; 572 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example.app/Example"; 573 | }; 574 | name = Debug; 575 | }; 576 | 0DEE76E319F14A0800F6F7A7 /* Release */ = { 577 | isa = XCBuildConfiguration; 578 | buildSettings = { 579 | BUNDLE_LOADER = "$(TEST_HOST)"; 580 | INFOPLIST_FILE = ExampleTests/Info.plist; 581 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 582 | PRODUCT_BUNDLE_IDENTIFIER = "SwiftOverlays.$(PRODUCT_NAME:rfc1034identifier)"; 583 | PRODUCT_NAME = "$(TARGET_NAME)"; 584 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example.app/Example"; 585 | }; 586 | name = Release; 587 | }; 588 | /* End XCBuildConfiguration section */ 589 | 590 | /* Begin XCConfigurationList section */ 591 | 0D9008521C673C87003D334A /* Build configuration list for PBXNativeTarget "SwiftOverlays" */ = { 592 | isa = XCConfigurationList; 593 | buildConfigurations = ( 594 | 0D90084E1C673C87003D334A /* Debug */, 595 | 0D90084F1C673C87003D334A /* Release */, 596 | ); 597 | defaultConfigurationIsVisible = 0; 598 | defaultConfigurationName = Release; 599 | }; 600 | 0DEE76B819F14A0800F6F7A7 /* Build configuration list for PBXProject "Example" */ = { 601 | isa = XCConfigurationList; 602 | buildConfigurations = ( 603 | 0DEE76DC19F14A0800F6F7A7 /* Debug */, 604 | 0DEE76DD19F14A0800F6F7A7 /* Release */, 605 | ); 606 | defaultConfigurationIsVisible = 0; 607 | defaultConfigurationName = Release; 608 | }; 609 | 0DEE76DE19F14A0800F6F7A7 /* Build configuration list for PBXNativeTarget "Example" */ = { 610 | isa = XCConfigurationList; 611 | buildConfigurations = ( 612 | 0DEE76DF19F14A0800F6F7A7 /* Debug */, 613 | 0DEE76E019F14A0800F6F7A7 /* Release */, 614 | ); 615 | defaultConfigurationIsVisible = 0; 616 | defaultConfigurationName = Release; 617 | }; 618 | 0DEE76E119F14A0800F6F7A7 /* Build configuration list for PBXNativeTarget "ExampleTests" */ = { 619 | isa = XCConfigurationList; 620 | buildConfigurations = ( 621 | 0DEE76E219F14A0800F6F7A7 /* Debug */, 622 | 0DEE76E319F14A0800F6F7A7 /* Release */, 623 | ); 624 | defaultConfigurationIsVisible = 0; 625 | defaultConfigurationName = Release; 626 | }; 627 | /* End XCConfigurationList section */ 628 | }; 629 | rootObject = 0DEE76B519F14A0800F6F7A7 /* Project object */; 630 | } 631 | -------------------------------------------------------------------------------- /Example/Example.xcodeproj/xcshareddata/xcschemes/SwiftOverlays-example-debug.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 | 90 | 91 | 97 | 99 | 105 | 106 | 107 | 108 | 110 | 111 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /Example/Example.xcodeproj/xcshareddata/xcschemes/SwiftOverlays.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 65 | 71 | 72 | 73 | 74 | 75 | 76 | 82 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /Example/Example/AnnoyingNotification.xib: -------------------------------------------------------------------------------- 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 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 44 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /Example/Example/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Example 4 | // 5 | // Created by Peter Prokop on 17/10/14. 6 | // 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | func applicationWillResignActive(_ application: UIApplication) { 22 | // 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. 23 | // 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. 24 | } 25 | 26 | func applicationDidEnterBackground(_ application: UIApplication) { 27 | // 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. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | func applicationWillEnterForeground(_ application: UIApplication) { 32 | // 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. 33 | } 34 | 35 | func applicationDidBecomeActive(_ application: UIApplication) { 36 | // 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. 37 | } 38 | 39 | func applicationWillTerminate(_ application: UIApplication) { 40 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 41 | } 42 | 43 | 44 | } 45 | 46 | -------------------------------------------------------------------------------- /Example/Example/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/Example/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 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /Example/Example/Example-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #import -------------------------------------------------------------------------------- /Example/Example/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/Example/Images.xcassets/close.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "closeSlide@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/Example/Images.xcassets/close.imageset/closeSlide@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peterprokop/SwiftOverlays/c307de5ad1873eededba8e58ec495be1abfe2431/Example/Example/Images.xcassets/close.imageset/closeSlide@2x.png -------------------------------------------------------------------------------- /Example/Example/Images.xcassets/twitter.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "twi.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/Example/Images.xcassets/twitter.imageset/twi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peterprokop/SwiftOverlays/c307de5ad1873eededba8e58ec495be1abfe2431/Example/Example/Images.xcassets/twitter.imageset/twi.png -------------------------------------------------------------------------------- /Example/Example/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 | UIStatusBarTintParameters 34 | 35 | UINavigationBar 36 | 37 | Style 38 | UIBarStyleDefault 39 | Translucent 40 | 41 | 42 | 43 | UISupportedInterfaceOrientations 44 | 45 | UIInterfaceOrientationPortrait 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /Example/Example/MasterVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MasterViewController.swift 3 | // Example 4 | // 5 | // Created by Peter Prokop on 17/10/14. 6 | // 7 | // 8 | 9 | import UIKit 10 | 11 | class MasterVC: UITableViewController { 12 | 13 | var exampleDescriptions = ["Wait overlay", 14 | "Wait overlay with text", 15 | "Overlay with text only", 16 | "Image and text overlay", 17 | "Progress", 18 | "Annoying notification on top", 19 | "Blocking wait overlay", 20 | "Blocking wait overlay with text", 21 | ] 22 | 23 | var types: Array = [ 24 | .Wait, 25 | .WaitWithText, 26 | .TextOnly, 27 | .ImageAndText, 28 | .Progress, 29 | .AnnoyingNotification, 30 | .BlockingWait, 31 | .BlockingWaitWithText 32 | ] 33 | 34 | override func awakeFromNib() { 35 | super.awakeFromNib() 36 | } 37 | 38 | override func viewDidLoad() { 39 | super.viewDidLoad() 40 | } 41 | 42 | override func didReceiveMemoryWarning() { 43 | super.didReceiveMemoryWarning() 44 | // Dispose of any resources that can be recreated. 45 | } 46 | 47 | // MARK: - Segues 48 | 49 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 50 | if segue.identifier == "showOverlayExample" { 51 | if let indexPath = self.tableView.indexPathForSelectedRow { 52 | let type = types[indexPath.row] 53 | (segue.destination as! OverlayExampleVC).type = type 54 | (segue.destination ).title = exampleDescriptions[indexPath.row] 55 | } 56 | } 57 | } 58 | 59 | // MARK: - Table View 60 | 61 | override func numberOfSections(in tableView: UITableView) -> Int { 62 | return 1 63 | } 64 | 65 | override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 66 | return exampleDescriptions.count 67 | } 68 | 69 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 70 | let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath as IndexPath) 71 | 72 | let exampleDescription = exampleDescriptions[indexPath.row] 73 | 74 | cell.textLabel?.text = exampleDescription 75 | 76 | return cell 77 | } 78 | 79 | override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 80 | self.performSegue(withIdentifier: "showOverlayExample", sender: nil) 81 | } 82 | 83 | } 84 | 85 | -------------------------------------------------------------------------------- /Example/Example/OverlayExampleVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WaitVC.swift 3 | // Example 4 | // 5 | // Created by Peter Prokop on 17/10/14. 6 | // 7 | // 8 | 9 | import UIKit 10 | 11 | class OverlayExampleVC: UIViewController { 12 | enum ExampleType { 13 | case Wait 14 | case WaitWithText 15 | case TextOnly 16 | case ImageAndText 17 | case Progress 18 | case AnnoyingNotification 19 | case BlockingWait 20 | case BlockingWaitWithText 21 | } 22 | 23 | @IBOutlet var annoyingNotificationView: UIView? 24 | 25 | var type: ExampleType = .Wait 26 | 27 | var beginTimer: Timer? 28 | var endTimer: Timer? 29 | 30 | var progress = 0.0 31 | 32 | override func viewDidLoad() { 33 | super.viewDidLoad() 34 | 35 | self.begin() 36 | } 37 | 38 | override func viewWillDisappear(_ animated: Bool) { 39 | super.viewWillDisappear(animated) 40 | 41 | if let beginTimer = beginTimer { 42 | beginTimer.invalidate() 43 | } 44 | 45 | if let endTimer = endTimer { 46 | endTimer.invalidate() 47 | } 48 | 49 | SwiftOverlays.removeAllBlockingOverlays() 50 | } 51 | 52 | // MARK: begin/end 53 | @objc func begin() { 54 | switch (type) { 55 | case .Wait: 56 | self.showWaitOverlay() 57 | // Or SwiftOverlays.showCenteredWaitOverlay(self.view) 58 | 59 | case .WaitWithText: 60 | let text = "Please wait..." 61 | self.showWaitOverlayWithText(text) 62 | // Or SwiftOverlays.showCenteredWaitOverlayWithText(self.view, text: text) 63 | 64 | case .TextOnly: 65 | let text = "This is a text-only overlay...\n...spanning several lines" 66 | self.showTextOverlay(text) 67 | // Or SwiftOverlays.showTextOverlay(self.view, text: text) 68 | 69 | return 70 | 71 | case .ImageAndText: 72 | let image = PPSwiftGifs.animatedImageWithGIFNamed(name: "Loading") 73 | let text = "Overlay\nWith cool GIF!" 74 | self.showImageAndTextOverlay(image!, text: text) 75 | // Or SwiftOverlays.showImageAndTextOverlay(self.view, image: image!, text: text) 76 | 77 | return 78 | 79 | case .Progress: 80 | self.showProgressOverlay("This is a progress overlay!") 81 | endTimer = Timer.scheduledTimer(timeInterval: 0.02, target: self, selector: #selector(end), userInfo: nil, repeats: true) 82 | 83 | return 84 | 85 | case .AnnoyingNotification: 86 | Bundle.main.loadNibNamed("AnnoyingNotification", owner: self, options: nil) 87 | 88 | UIViewController.showOnTopOfStatusBar(annoyingNotificationView!, duration: 5) 89 | // Or SwiftOverlays.showAnnoyingNotificationOnTopOfStatusBar(annoyingNotificationView!, duration: 5) 90 | 91 | return 92 | 93 | case .BlockingWait: 94 | SwiftOverlays.showBlockingWaitOverlay() 95 | 96 | case .BlockingWaitWithText: 97 | SwiftOverlays.showBlockingWaitOverlayWithText("This is blocking overlay!") 98 | } 99 | 100 | if let endTimer = endTimer { 101 | endTimer.invalidate() 102 | } 103 | 104 | endTimer = Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(end), userInfo: nil, repeats: false) 105 | } 106 | 107 | @objc func end() { 108 | switch (type) { 109 | case .Wait, .WaitWithText, .TextOnly, .ImageAndText: 110 | SwiftOverlays.removeAllOverlaysFromView(self.view) 111 | 112 | case .Progress: 113 | progress += 0.01 114 | let newProgressValue = Int(100*progress) % 101 115 | self.updateOverlayProgress(Float(newProgressValue)/100) 116 | return 117 | 118 | case .BlockingWait, .BlockingWaitWithText: 119 | SwiftOverlays.removeAllBlockingOverlays() 120 | 121 | case .AnnoyingNotification: 122 | return 123 | } 124 | 125 | 126 | if let beginTimer = beginTimer { 127 | beginTimer.invalidate() 128 | } 129 | 130 | beginTimer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(begin), userInfo: nil, repeats: false) 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /Example/Example/Res/Loading@2x.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peterprokop/SwiftOverlays/c307de5ad1873eededba8e58ec495be1abfe2431/Example/Example/Res/Loading@2x.gif -------------------------------------------------------------------------------- /Example/ExampleTests/ExampleTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExampleTests.swift 3 | // ExampleTests 4 | // 5 | // Created by Peter Prokop on 17/10/14. 6 | // 7 | // 8 | 9 | import UIKit 10 | import XCTest 11 | 12 | class ExampleTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | XCTAssert(true, "Pass") 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measure() { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Example/ExampleTests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Example/PPSwiftGifs/PPSwiftGifs.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PPSwiftGifs.swift 3 | // PPSwiftGifsExample 4 | // 5 | // Created by Peter Prokop on 08/11/14. 6 | // Copyright (c) 2014 Peter Prokop. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | import CoreFoundation 12 | 13 | class PPSwiftGifs 14 | { 15 | // MARK: Public 16 | class func animatedImageWithGIFNamed(name: String!) -> UIImage? { 17 | let screenScale = Int(UIScreen.main.scale) 18 | let possibleScales = [1, 2, 3] 19 | let orderedScales = [screenScale] + possibleScales.filter{$0 != screenScale} 20 | 21 | let mapping = { (x: Int) in ["@" + String(x) + "x", "@" + String(x) + "X"]} 22 | let tmp = orderedScales.map(mapping) 23 | let orderedSuffixes = tmp.reduce([], +) + [""] 24 | 25 | for suffix in orderedSuffixes { 26 | if let url = Bundle.main.url(forResource: name + suffix, withExtension: "gif") { 27 | if let source = CGImageSourceCreateWithURL(url as CFURL, nil) { 28 | return animatedImageWithImageSource(source: source) 29 | } 30 | } 31 | } 32 | 33 | return nil 34 | } 35 | 36 | class func animatedImageWithGIFData(data: NSData!) -> UIImage? { 37 | if let source = CGImageSourceCreateWithData(data, nil) { 38 | return animatedImageWithImageSource(source: source) 39 | } 40 | 41 | return nil 42 | } 43 | 44 | // MARK: Private 45 | private class func animatedImageWithImageSource (source: CGImageSource) -> UIImage? { 46 | let (images, delays) = createImagesAndDelays(source: source); 47 | let totalDuration = delays.reduce(0, +) 48 | let frames = frameArray(images, delays, totalDuration) 49 | 50 | // All durations in GIF are in 1/100th of second 51 | let duration = TimeInterval(Double(totalDuration)/100.0) 52 | let animation = UIImage.animatedImage(with: frames, duration: duration) 53 | 54 | return animation 55 | } 56 | 57 | private class func createImagesAndDelays(source: CGImageSource) -> (Array, Array) { 58 | let count = Int(CGImageSourceGetCount(source)) 59 | 60 | var images = Array() 61 | var delays = Array() 62 | 63 | for i in 0 ..< count { 64 | if let image = CGImageSourceCreateImageAtIndex(source, i, [:] as CFDictionary) { 65 | images.append(image) 66 | delays.append(delayForImageAtIndex(source, UInt(i))) 67 | } 68 | } 69 | 70 | return (images, delays) 71 | } 72 | 73 | private class func delayForImageAtIndex(_ source: CGImageSource, _ i: UInt) -> Int { 74 | var delay = 1 75 | 76 | let properties = CGImageSourceCopyPropertiesAtIndex(source, Int(i), [:] as CFDictionary) 77 | 78 | if (properties != nil) { 79 | let gifDictionaryProperty = unsafeBitCast(kCGImagePropertyGIFDictionary, to: UnsafeRawPointer.self) 80 | let gifProperties = CFDictionaryGetValue(properties, gifDictionaryProperty) 81 | 82 | if (gifProperties != nil) { 83 | let gifPropertiesCFD = unsafeBitCast(gifProperties, to: CFDictionary.self) 84 | 85 | let unclampedDelayTimeProperty = unsafeBitCast(kCGImagePropertyGIFUnclampedDelayTime, to: UnsafeRawPointer.self) 86 | var number = unsafeBitCast(CFDictionaryGetValue(gifPropertiesCFD, unclampedDelayTimeProperty), to: NSNumber.self); 87 | 88 | if (number.doubleValue == 0) { 89 | let delayTimeProperty = unsafeBitCast(kCGImagePropertyGIFDelayTime, to: UnsafeRawPointer.self) 90 | number = unsafeBitCast(CFDictionaryGetValue(gifPropertiesCFD, delayTimeProperty), to: NSNumber.self); 91 | } 92 | 93 | if (number.doubleValue > 0) { 94 | delay = lrint(number.doubleValue * 100); 95 | } 96 | } 97 | } 98 | 99 | return delay; 100 | } 101 | 102 | private class func frameArray(_ images: Array, _ delays: Array, _ totalDuration: Int) -> [UIImage] { 103 | let delayGCD = gcd(values: delays) 104 | 105 | var frames = Array() 106 | frames.reserveCapacity(images.count) 107 | 108 | for i in 0 ..< images.count { 109 | let frame = UIImage(cgImage: images[i], scale: UIScreen.main.scale, orientation: .up) 110 | for _ in 0 ..< delays[i]/delayGCD { 111 | frames.append(frame) 112 | } 113 | } 114 | 115 | return frames; 116 | } 117 | 118 | private class func gcd(values: Array) -> Int { 119 | if values.count == 0 { 120 | return 1; 121 | } 122 | 123 | var currentGCD = values[0] 124 | 125 | for i in 0 ..< values.count { 126 | currentGCD = gcd(currentGCD, values[i]) 127 | } 128 | 129 | return currentGCD; 130 | } 131 | 132 | private class func gcd(_ aNumber: Int, _ anotherNumber: Int) -> Int { 133 | var a = aNumber 134 | var b = anotherNumber 135 | while true { 136 | let r = a % b 137 | if r == 0 { 138 | return b 139 | } 140 | a = b 141 | b = r 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Peter Prokop 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. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Imgur](http://i.imgur.com/AFMWOiJ.gif) 2 | 3 | SwiftOverlays is a Swift GUI library for displaying various popups and notifications. 4 | 5 | SwiftOverlays animated logo is kindly made by [Crafted Pixels](http://bit.ly/craftedpx) 6 | 7 | [![Build Status](https://travis-ci.org/peterprokop/SwiftOverlays.svg?branch=master)](https://travis-ci.org/peterprokop/SwiftOverlays) 8 | [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 9 | 10 | ## Features 11 | 12 | SwiftOverlays provides several ways to notify user: 13 | 14 | - [x] Wait overlay: a simple overlay with activity indicator 15 | 16 | ![Wait](https://i.imgflip.com/df53v.gif) 17 | 18 | - [x] Wait overlay with text 19 | 20 | ![WaitWithText](https://i.imgflip.com/df525.gif) 21 | 22 | - [x] Overlay with text only 23 | - [x] Overlay with image and text (can be used with [PPSwiftGifs](https://github.com/peterprokop/PPSwiftGifs) to show custom animated GIF instead of UIActivityIndicatorView) 24 | - [x] All of the above with blocking any user interaction 25 | - [x] Notification on top of the status bar, similar to native iOS local/push notifications 26 | 27 | ![Notification](https://i.imgflip.com/df5k5.gif) 28 | 29 | ## Installation 30 | 31 | ### Manual 32 | Just clone and add ```SwiftOverlays.swift``` to your project. 33 | 34 | ### Carthage 35 | * `> Cartfile` 36 | * `nano Cartfile` 37 | * put `github "peterprokop/SwiftOverlays" ~> 5.0.1` into Cartfile 38 | * Save it: `ctrl-x`, `y`, `enter` 39 | * Run `carthage update` 40 | * Copy `SwiftOverlays.framework` from `Carthage/Build/iOS` to your project 41 | * Make sure that `SwiftOverlays` is added in `Embedded Binaries` section of your target (or else you will get `dyld library not loaded referenced from ... reason image not found` error) 42 | * Add `import SwiftOverlays` on top of your view controller's code 43 | 44 | ### Cocoapods 45 | - Make sure that you use latest stable Cocoapods version: `pod --version` 46 | - If not, update it: `sudo gem install cocoapods` 47 | - `pod init` in you project root dir 48 | - `nano Podfile`, add: 49 | 50 | ``` 51 | pod 'SwiftOverlays', '~> 5.0.1' 52 | use_frameworks! 53 | ``` 54 | - Save it: `ctrl-x`, `y`, `enter` 55 | - `pod update` 56 | - Open generated `.xcworkspace` 57 | - Don't forget to import SwiftOverlays: `import SwiftOverlays`! 58 | 59 | ## Requirements 60 | 61 | - iOS 10.0+ 62 | - Xcode 10.0+ 63 | - Swift 4.2 (if you need older swift version, see 64 | [swift-3.0](https://github.com/peterprokop/SwiftOverlays/tree/swift-3.0) and others) 65 | 66 | ## Usage 67 | 68 | If you're using CocoaPods, import the library with `import SwiftOverlays` 69 | 70 | You can use UIViewController convenience methods provided by library: 71 | 72 | ```swift 73 | // In your view controller: 74 | 75 | // Wait overlay 76 | self.showWaitOverlay() 77 | 78 | // Wait overlay with text 79 | let text = "Please wait..." 80 | self.showWaitOverlayWithText(text) 81 | 82 | // Overlay with text only 83 | let text = "This is a text-only overlay...\n...spanning several lines" 84 | self.showTextOverlay(text) 85 | 86 | // Remove everything 87 | self.removeAllOverlays() 88 | 89 | // Notification on top of the status bar 90 | UIViewController.showOnTopOfStatusBar(annoyingNotificationView!, duration: 5) 91 | 92 | // Block user interaction 93 | SwiftOverlays.showBlockingWaitOverlayWithText("This is blocking overlay!") 94 | 95 | // Don't forget to unblock! 96 | SwiftOverlays.removeAllBlockingOverlays() 97 | 98 | ``` 99 | 100 | ### Using with UITableViewController/UICollectionViewController 101 | 102 | You can't use SwiftOverlays convenience methods directly with UITableViewController - because its view is, well, an UITableView, and overlay will be scrolled along with it. 103 | 104 | Instead I suggest using UIViewController instead of UITableViewController and adding UITableView as a subview. 105 | (the same applies to UICollectionViewController) 106 | 107 | If for some reason you can't use UIViewController, you can do something like: 108 | ```swift 109 | if let superview = self.view.superview { 110 | SwiftOverlays.showCenteredWaitOverlayWithText(superview, text: "Please wait...") 111 | SwiftOverlays.removeAllOverlaysFromView(superview) 112 | } 113 | ``` 114 | 115 | (but in that case overlay will be added to the superview, and you should obviously do that only if superview is available - for example in viewDidAppear method of your controller.). 116 | 117 | ## Contribution 118 | 119 | You are welcome to fork and submit pull requests 120 | 121 | ## Other Projects 122 | 123 | - [StarryStars](https://github.com/peterprokop/StarryStars) - iOS GUI library for displaying and editing ratings. 124 | - [AlertyAlert](https://github.com/peterprokop/AlertyAlert) - AlertyAlert is a nice and fluffy iOS alert library for all your alerty needs. 125 | -------------------------------------------------------------------------------- /SwiftOverlays.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'SwiftOverlays' 3 | s.version = '5.0.1' 4 | s.license = 'MIT' 5 | s.summary = 'GUI library for displaying various popups and notifications' 6 | s.homepage = 'https://github.com/peterprokop/SwiftOverlays' 7 | s.authors = { 'Peter Prokop' => 'prokop.petr@gmail.com' } 8 | s.source = { :git => 'https://github.com/peterprokop/SwiftOverlays.git', :tag => s.version.to_s } 9 | s.ios.deployment_target = '8.0' 10 | s.source_files = 'SwiftOverlays/*.swift' 11 | end 12 | -------------------------------------------------------------------------------- /SwiftOverlays/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 | -------------------------------------------------------------------------------- /SwiftOverlays/SwiftOverlays.h: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftOverlays.h 3 | // SwiftOverlays 4 | // 5 | // Created by Peter Prokop on 07/02/16. 6 | // 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for SwiftOverlays. 12 | FOUNDATION_EXPORT double SwiftOverlaysVersionNumber; 13 | 14 | //! Project version string for SwiftOverlays. 15 | FOUNDATION_EXPORT const unsigned char SwiftOverlaysVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /SwiftOverlays/SwiftOverlays.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftOverlays.swift 3 | // SwiftTest 4 | // 5 | // Created by Peter Prokop on 15/10/14. 6 | // Copyright (c) 2014 Peter Prokop. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | 13 | // For convenience methods 14 | @objc public extension UIViewController { 15 | 16 | /** 17 | Shows wait overlay with activity indicator, centered in the view controller's main view 18 | 19 | Do not use this method for **UITableViewController** or **UICollectionViewController** 20 | 21 | - returns: Created overlay 22 | */ 23 | @discardableResult 24 | func showWaitOverlay() -> UIView { 25 | return SwiftOverlays.showCenteredWaitOverlay(self.view) 26 | } 27 | 28 | /** 29 | Shows wait overlay with activity indicator *and text*, centered in the view controller's main view 30 | 31 | Do not use this method for **UITableViewController** or **UICollectionViewController** 32 | 33 | - parameter text: Text to be shown on overlay 34 | 35 | - returns: Created overlay 36 | */ 37 | @discardableResult 38 | func showWaitOverlayWithText(_ text: String) -> UIView { 39 | return SwiftOverlays.showCenteredWaitOverlayWithText(self.view, text: text) 40 | } 41 | 42 | /** 43 | Shows *text-only* overlay, centered in the view controller's main view 44 | 45 | Do not use this method for **UITableViewController** or **UICollectionViewController** 46 | 47 | - parameter text: Text to be shown on overlay 48 | 49 | - returns: Created overlay 50 | */ 51 | @discardableResult 52 | func showTextOverlay(_ text: String) -> UIView { 53 | return SwiftOverlays.showTextOverlay(self.view, text: text) 54 | } 55 | 56 | /** 57 | Shows overlay with text and progress bar, centered in the view controller's main view 58 | 59 | Do not use this method for **UITableViewController** or **UICollectionViewController** 60 | 61 | - parameter text: Text to be shown on overlay 62 | 63 | - returns: Created overlay 64 | */ 65 | @discardableResult 66 | func showProgressOverlay(_ text: String) -> UIView { 67 | return SwiftOverlays.showProgressOverlay(self.view, text: text) 68 | } 69 | 70 | /** 71 | Shows overlay *with image and text*, centered in the view controller's main view 72 | 73 | Do not use this method for **UITableViewController** or **UICollectionViewController** 74 | 75 | - parameter image: Image to be added to overlay 76 | - parameter text: Text to be shown on overlay 77 | 78 | - returns: Created overlay 79 | */ 80 | @discardableResult 81 | func showImageAndTextOverlay(_ image: UIImage, text: String) -> UIView { 82 | return SwiftOverlays.showImageAndTextOverlay(self.view, image: image, text: text) 83 | } 84 | 85 | /** 86 | Shows notification on top of the status bar, similar to native local or remote notifications 87 | 88 | - parameter notificationView: View that will be shown as notification 89 | - parameter duration: Amount of time until notification disappears 90 | - parameter animated: Should appearing be animated 91 | */ 92 | class func showOnTopOfStatusBar(_ notificationView: UIView, duration: TimeInterval, animated: Bool = true) { 93 | SwiftOverlays.showOnTopOfStatusBar(notificationView, duration: duration, animated: animated) 94 | } 95 | 96 | /** 97 | Removes all overlays from view controller's main view 98 | */ 99 | func removeAllOverlays() { 100 | SwiftOverlays.removeAllOverlaysFromView(self.view) 101 | } 102 | 103 | /** 104 | Updates text on the current overlay. 105 | Does nothing if no overlay is present. 106 | 107 | - parameter text: Text to set 108 | */ 109 | func updateOverlayText(_ text: String) { 110 | SwiftOverlays.updateOverlayText(self.view, text: text) 111 | } 112 | 113 | /** 114 | Updates progress on the current overlay. 115 | Does nothing if no overlay is present. 116 | 117 | - parameter progress: Progress to set 0.0 .. 1.0 118 | */ 119 | func updateOverlayProgress(_ progress: Float) { 120 | SwiftOverlays.updateOverlayProgress(self.view, progress: progress) 121 | } 122 | } 123 | 124 | open class SwiftOverlays: NSObject { 125 | // You can customize these values 126 | 127 | // Some random number 128 | static let containerViewTag = 456987123 129 | 130 | static let cornerRadius = CGFloat(10) 131 | static let padding = CGFloat(10) 132 | 133 | static let backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.7) 134 | static let textColor = UIColor(red: 1, green: 1, blue: 1, alpha: 1) 135 | static let font = UIFont.systemFont(ofSize: 14) 136 | 137 | // Annoying notifications on top of status bar 138 | static let bannerDissapearAnimationDuration = 0.5 139 | 140 | static var bannerWindow : UIWindow? 141 | 142 | open class Utils { 143 | 144 | /** 145 | Adds autolayout constraints to innerView to center it in its superview and fix its size. 146 | `innerView` should have a superview. 147 | 148 | - parameter innerView: View to set constraints on 149 | */ 150 | public static func centerViewInSuperview(_ view: UIView) { 151 | assert(view.superview != nil, "`view` should have a superview") 152 | 153 | view.translatesAutoresizingMaskIntoConstraints = false 154 | 155 | let constraintH = NSLayoutConstraint( 156 | item: view, 157 | attribute: NSLayoutConstraint.Attribute.centerX, 158 | relatedBy: NSLayoutConstraint.Relation.equal, 159 | toItem: view.superview, 160 | attribute: NSLayoutConstraint.Attribute.centerX, 161 | multiplier: 1, 162 | constant: 0 163 | ) 164 | let constraintV = NSLayoutConstraint( 165 | item: view, 166 | attribute: NSLayoutConstraint.Attribute.centerY, 167 | relatedBy: NSLayoutConstraint.Relation.equal, 168 | toItem: view.superview, 169 | attribute: NSLayoutConstraint.Attribute.centerY, 170 | multiplier: 1, 171 | constant: 0 172 | ) 173 | let constraintWidth = NSLayoutConstraint( 174 | item: view, 175 | attribute: NSLayoutConstraint.Attribute.width, 176 | relatedBy: NSLayoutConstraint.Relation.equal, 177 | toItem: nil, 178 | attribute: NSLayoutConstraint.Attribute.notAnAttribute, 179 | multiplier: 1, 180 | constant: view.frame.size.width 181 | ) 182 | let constraintHeight = NSLayoutConstraint( 183 | item: view, 184 | attribute: NSLayoutConstraint.Attribute.height, 185 | relatedBy: NSLayoutConstraint.Relation.equal, 186 | toItem: nil, 187 | attribute: NSLayoutConstraint.Attribute.notAnAttribute, 188 | multiplier: 1, 189 | constant: view.frame.size.height 190 | ) 191 | view.superview!.addConstraints([constraintV, constraintH, constraintWidth, constraintHeight]) 192 | } 193 | } 194 | 195 | // MARK: - Public class methods - 196 | 197 | // MARK: Blocking 198 | 199 | /** 200 | Shows *blocking* wait overlay with activity indicator, centered in the app's main window 201 | 202 | - returns: Created overlay 203 | */ 204 | @discardableResult 205 | open class func showBlockingWaitOverlay() -> UIView { 206 | let blocker = addMainWindowBlocker() 207 | showCenteredWaitOverlay(blocker) 208 | 209 | return blocker 210 | } 211 | 212 | /** 213 | Shows wait overlay with activity indicator *and text*, centered in the app's main window 214 | 215 | - parameter text: Text to be shown on overlay 216 | 217 | - returns: Created overlay 218 | */ 219 | @discardableResult 220 | open class func showBlockingWaitOverlayWithText(_ text: String) -> UIView { 221 | let blocker = addMainWindowBlocker() 222 | showCenteredWaitOverlayWithText(blocker, text: text) 223 | 224 | return blocker 225 | } 226 | 227 | /** 228 | Shows *blocking* overlay *with image and text*,, centered in the app's main window 229 | 230 | - parameter image: Image to be added to overlay 231 | - parameter text: Text to be shown on overlay 232 | 233 | - returns: Created overlay 234 | */ 235 | open class func showBlockingImageAndTextOverlay(_ image: UIImage, text: String) -> UIView { 236 | let blocker = addMainWindowBlocker() 237 | showImageAndTextOverlay(blocker, image: image, text: text) 238 | 239 | return blocker 240 | } 241 | 242 | /** 243 | Shows *text-only* overlay, centered in the app's main window 244 | 245 | - parameter text: Text to be shown on overlay 246 | 247 | - returns: Created overlay 248 | */ 249 | open class func showBlockingTextOverlay(_ text: String) -> UIView { 250 | let blocker = addMainWindowBlocker() 251 | showTextOverlay(blocker, text: text) 252 | 253 | return blocker 254 | } 255 | 256 | /** 257 | Removes all *blocking* overlays from application's main window 258 | */ 259 | open class func removeAllBlockingOverlays() { 260 | let window = UIApplication.shared.delegate!.window!! 261 | removeAllOverlaysFromView(window) 262 | } 263 | 264 | // MARK: Non-blocking 265 | @discardableResult 266 | open class func showCenteredWaitOverlay(_ parentView: UIView) -> UIView { 267 | let ai = UIActivityIndicatorView(style: .whiteLarge) 268 | ai.startAnimating() 269 | 270 | let containerViewRect = CGRect( 271 | x: 0, 272 | y: 0, 273 | width: ai.frame.size.width * 2, 274 | height: ai.frame.size.height * 2 275 | ) 276 | 277 | let containerView = UIView(frame: containerViewRect) 278 | 279 | containerView.tag = containerViewTag 280 | containerView.layer.cornerRadius = cornerRadius 281 | containerView.backgroundColor = backgroundColor 282 | containerView.center = CGPoint( 283 | x: parentView.bounds.size.width/2, 284 | y: parentView.bounds.size.height/2 285 | ) 286 | 287 | ai.center = CGPoint( 288 | x: containerView.bounds.size.width/2, 289 | y: containerView.bounds.size.height/2 290 | ) 291 | 292 | containerView.addSubview(ai) 293 | 294 | parentView.addSubview(containerView) 295 | 296 | Utils.centerViewInSuperview(containerView) 297 | 298 | return containerView 299 | } 300 | 301 | @discardableResult 302 | open class func showCenteredWaitOverlayWithText(_ parentView: UIView, text: String) -> UIView { 303 | let ai = UIActivityIndicatorView(style: .white) 304 | ai.startAnimating() 305 | 306 | return showGenericOverlay(parentView, text: text, accessoryView: ai) 307 | } 308 | 309 | @discardableResult 310 | open class func showImageAndTextOverlay(_ parentView: UIView, image: UIImage, text: String) -> UIView { 311 | let imageView = UIImageView(image: image) 312 | 313 | return showGenericOverlay(parentView, text: text, accessoryView: imageView) 314 | } 315 | 316 | open class func showGenericOverlay(_ parentView: UIView, text: String, accessoryView: UIView, horizontalLayout: Bool = true) -> UIView { 317 | let label = labelForText(text) 318 | var actualSize = CGSize.zero 319 | 320 | if horizontalLayout { 321 | actualSize = CGSize(width: accessoryView.frame.size.width + label.frame.size.width + padding * 3, 322 | height: max(label.frame.size.height, accessoryView.frame.size.height) + padding * 2) 323 | 324 | label.frame = label.frame.offsetBy(dx: accessoryView.frame.size.width + padding * 2, dy: padding) 325 | 326 | accessoryView.frame = accessoryView.frame.offsetBy(dx: padding, dy: (actualSize.height - accessoryView.frame.size.height)/2) 327 | } else { 328 | actualSize = CGSize(width: max(accessoryView.frame.size.width, label.frame.size.width) + padding * 2, 329 | height: label.frame.size.height + accessoryView.frame.size.height + padding * 3) 330 | 331 | label.frame = label.frame.offsetBy(dx: padding, dy: accessoryView.frame.size.height + padding * 2) 332 | 333 | accessoryView.frame = accessoryView.frame.offsetBy(dx: (actualSize.width - accessoryView.frame.size.width)/2, dy: padding) 334 | } 335 | 336 | // Container view 337 | let containerViewRect = CGRect(origin: .zero, size: actualSize) 338 | let containerView = UIView(frame: containerViewRect) 339 | 340 | containerView.tag = containerViewTag 341 | containerView.layer.cornerRadius = cornerRadius 342 | containerView.backgroundColor = backgroundColor 343 | containerView.center = CGPoint( 344 | x: parentView.bounds.size.width/2, 345 | y: parentView.bounds.size.height/2 346 | ) 347 | 348 | containerView.addSubview(accessoryView) 349 | containerView.addSubview(label) 350 | 351 | parentView.addSubview(containerView) 352 | 353 | Utils.centerViewInSuperview(containerView) 354 | 355 | return containerView 356 | } 357 | 358 | @discardableResult 359 | open class func showTextOverlay(_ parentView: UIView, text: String) -> UIView { 360 | let label = labelForText(text) 361 | label.frame = label.frame.offsetBy(dx: padding, dy: padding) 362 | 363 | let actualSize = CGSize(width: label.frame.size.width + padding * 2, 364 | height: label.frame.size.height + padding * 2) 365 | 366 | // Container view 367 | let containerViewRect = CGRect(origin: .zero, size: actualSize) 368 | let containerView = UIView(frame: containerViewRect) 369 | 370 | containerView.tag = containerViewTag 371 | containerView.layer.cornerRadius = cornerRadius 372 | containerView.backgroundColor = backgroundColor 373 | containerView.center = CGPoint( 374 | x: parentView.bounds.size.width/2, 375 | y: parentView.bounds.size.height/2 376 | ) 377 | 378 | containerView.addSubview(label) 379 | 380 | parentView.addSubview(containerView) 381 | 382 | Utils.centerViewInSuperview(containerView) 383 | 384 | return containerView 385 | } 386 | 387 | open class func showProgressOverlay(_ parentView: UIView, text: String) -> UIView { 388 | let pv = UIProgressView(progressViewStyle: .default) 389 | 390 | return showGenericOverlay(parentView, text: text, accessoryView: pv, horizontalLayout: false) 391 | } 392 | 393 | open class func removeAllOverlaysFromView(_ parentView: UIView) { 394 | parentView.subviews 395 | .filter { $0.tag == containerViewTag } 396 | .forEach { $0.removeFromSuperview() } 397 | } 398 | 399 | open class func updateOverlayText(_ parentView: UIView, text: String) { 400 | if let overlay = parentView.viewWithTag(containerViewTag) { 401 | overlay.subviews.compactMap { $0 as? UILabel }.first?.text = text 402 | } 403 | } 404 | 405 | open class func updateOverlayProgress(_ parentView: UIView, progress: Float) { 406 | if let overlay = parentView.viewWithTag(containerViewTag) { 407 | overlay.subviews.compactMap { $0 as? UIProgressView }.first?.progress = progress 408 | } 409 | } 410 | 411 | // MARK: Status bar notification 412 | 413 | open class func showOnTopOfStatusBar(_ notificationView: UIView, duration: TimeInterval, animated: Bool = true) { 414 | if bannerWindow == nil { 415 | bannerWindow = UIWindow() 416 | bannerWindow!.windowLevel = UIWindow.Level.statusBar + 1 417 | bannerWindow!.backgroundColor = UIColor.clear 418 | } 419 | 420 | // TODO: use autolayout instead 421 | // Ugly, but works 422 | let topHeight = UIApplication.shared.statusBarFrame.size.height 423 | + UINavigationController().navigationBar.frame.height 424 | 425 | let height = max(topHeight, 64) 426 | let width = UIScreen.main.bounds.width 427 | 428 | let frame = CGRect(x: 0, y: 0, width: width, height: height) 429 | 430 | bannerWindow!.frame = frame 431 | bannerWindow!.isHidden = false 432 | 433 | let selector = #selector(closeNotificationOnTopOfStatusBar) 434 | let gestureRecognizer = UITapGestureRecognizer(target: self, action: selector) 435 | notificationView.addGestureRecognizer(gestureRecognizer) 436 | 437 | bannerWindow!.addSubview(notificationView) 438 | 439 | if animated { 440 | notificationView.frame = frame.offsetBy(dx: 0, dy: -frame.height) 441 | bannerWindow!.layoutIfNeeded() 442 | 443 | // Show appearing animation, schedule calling closing selector after completed 444 | UIView.animate(withDuration: bannerDissapearAnimationDuration, animations: { 445 | let frame = notificationView.frame 446 | notificationView.frame = frame.offsetBy(dx: 0, dy: frame.height) 447 | }, completion: { (finished) in 448 | self.perform(selector, with: notificationView, afterDelay: duration) 449 | }) 450 | } else { 451 | notificationView.frame = frame 452 | // Schedule calling closing selector right away 453 | self.perform(selector, with: notificationView, afterDelay: duration) 454 | } 455 | } 456 | 457 | @objc open class func closeNotificationOnTopOfStatusBar(_ sender: AnyObject) { 458 | NSObject.cancelPreviousPerformRequests(withTarget: self) 459 | 460 | let notificationView: UIView 461 | 462 | if let recognizer = sender as? UITapGestureRecognizer { 463 | notificationView = recognizer.view! 464 | } else if let view = sender as? UIView { 465 | notificationView = view 466 | } else { 467 | return 468 | } 469 | 470 | UIView.animate(withDuration: bannerDissapearAnimationDuration, 471 | animations: { () -> Void in 472 | let frame = notificationView.frame 473 | notificationView.frame = frame.offsetBy(dx: 0, dy: -frame.height) 474 | }, 475 | completion: { (finished) -> Void in 476 | notificationView.removeFromSuperview() 477 | bannerWindow?.isHidden = true 478 | } 479 | ) 480 | } 481 | 482 | // MARK: - Private class methods - 483 | 484 | fileprivate class func labelForText(_ text: String) -> UILabel { 485 | let textSize = text.size(withAttributes: [NSAttributedString.Key.font: font]) 486 | 487 | let labelRect = CGRect(origin: .zero, size: textSize) 488 | 489 | let label = UILabel(frame: labelRect) 490 | label.font = font 491 | label.textColor = textColor 492 | label.text = text 493 | label.numberOfLines = 0 494 | 495 | return label 496 | } 497 | 498 | fileprivate class func addMainWindowBlocker() -> UIView { 499 | let window = UIApplication.shared.delegate!.window!! 500 | 501 | let blocker = UIView(frame: window.bounds) 502 | blocker.backgroundColor = backgroundColor 503 | blocker.tag = containerViewTag 504 | 505 | blocker.translatesAutoresizingMaskIntoConstraints = false 506 | 507 | window.addSubview(blocker) 508 | 509 | let viewsDictionary = ["blocker": blocker] 510 | 511 | // Add constraints to handle orientation change 512 | let constraintsV = NSLayoutConstraint.constraints( 513 | withVisualFormat: "V:|-0-[blocker]-0-|", 514 | options: [], 515 | metrics: nil, 516 | views: viewsDictionary 517 | ) 518 | 519 | let constraintsH = NSLayoutConstraint.constraints( 520 | withVisualFormat: "|-0-[blocker]-0-|", 521 | options: [], 522 | metrics: nil, 523 | views: viewsDictionary 524 | ) 525 | 526 | window.addConstraints(constraintsV + constraintsH) 527 | 528 | return blocker 529 | } 530 | } 531 | --------------------------------------------------------------------------------