├── .gitignore ├── Blurberry.podspec ├── Blurberry.xcodeproj ├── project.pbxproj └── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── Blurberry.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── Demo ├── Blurberry-Demo-iOS │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Contents.json │ │ └── wwdc.imageset │ │ │ ├── Contents.json │ │ │ └── wwdc.png │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Button.swift │ ├── Info.plist │ └── ViewController.swift └── Blurberry-Demo.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── LICENSE ├── README.md ├── Resources └── demo.gif └── Sources ├── Blurberry.h ├── Extensions ├── NSObject+Extension.h └── NSObject+Extension.m ├── General └── Blurberry.swift ├── Info.plist └── Views ├── VisualEffectView+Internal.swift └── VisualEffectView+Public.swift /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | DerivedData 5 | xcuserdata 6 | !default.mode1v3 7 | !default.mode2v3 8 | !default.pbxuser 9 | !default.perspectivev3 10 | *.hmap 11 | *.ipa 12 | *.mode1v3 13 | *.mode2v3 14 | *.moved-aside 15 | *.pbxuser 16 | *.perspective 17 | *.perspectivev3 18 | *.swp 19 | *.xccheckout 20 | *.xcuserstate 21 | *~.nib 22 | 23 | # OS X temporary files 24 | # 25 | .DS_Store 26 | .Trashes 27 | .swp 28 | 29 | # AppCode 30 | # 31 | .idea/ 32 | 33 | # CocoaPods 34 | # 35 | *.dblite 36 | Pods/ -------------------------------------------------------------------------------- /Blurberry.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |spec| 2 | spec.name = "Blurberry" 3 | spec.version = "0.1.0" 4 | spec.summary = "Extends the functionality of the UIVisualEffectView" 5 | spec.homepage = "https://github.com/unboxme/Blurberry" 6 | spec.license = { :type => "MIT", :file => "LICENSE" } 7 | spec.author = { "Pavel Puzyrev" => "cannedapp@yahoo.com" } 8 | spec.source = { :git => 'https://github.com/unboxme/Blurberry.git', :tag => spec.version } 9 | spec.source_files = "Sources/**/*.{swift,h,m}" 10 | 11 | spec.swift_version = "5.0" 12 | spec.ios.deployment_target = "10.0" 13 | end 14 | -------------------------------------------------------------------------------- /Blurberry.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | E9F4A6842508C9E7002EDC02 /* Blurberry.h in Headers */ = {isa = PBXBuildFile; fileRef = E9F4A6822508C9E7002EDC02 /* Blurberry.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | E9F4A6A42508D016002EDC02 /* Blurberry.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9F4A69D2508D016002EDC02 /* Blurberry.swift */; }; 12 | E9F4A6A52508D016002EDC02 /* VisualEffectView+Internal.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9F4A69F2508D016002EDC02 /* VisualEffectView+Internal.swift */; }; 13 | E9F4A6A62508D016002EDC02 /* VisualEffectView+Public.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9F4A6A02508D016002EDC02 /* VisualEffectView+Public.swift */; }; 14 | E9F4A6A72508D016002EDC02 /* NSObject+Extension.h in Headers */ = {isa = PBXBuildFile; fileRef = E9F4A6A22508D016002EDC02 /* NSObject+Extension.h */; settings = {ATTRIBUTES = (Public, ); }; }; 15 | E9F4A6A82508D016002EDC02 /* NSObject+Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = E9F4A6A32508D016002EDC02 /* NSObject+Extension.m */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXFileReference section */ 19 | E9F4A67F2508C9E7002EDC02 /* Blurberry.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Blurberry.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 20 | E9F4A6822508C9E7002EDC02 /* Blurberry.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Blurberry.h; sourceTree = ""; }; 21 | E9F4A6832508C9E7002EDC02 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 22 | E9F4A69D2508D016002EDC02 /* Blurberry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Blurberry.swift; sourceTree = ""; }; 23 | E9F4A69F2508D016002EDC02 /* VisualEffectView+Internal.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "VisualEffectView+Internal.swift"; sourceTree = ""; }; 24 | E9F4A6A02508D016002EDC02 /* VisualEffectView+Public.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "VisualEffectView+Public.swift"; sourceTree = ""; }; 25 | E9F4A6A22508D016002EDC02 /* NSObject+Extension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+Extension.h"; sourceTree = ""; }; 26 | E9F4A6A32508D016002EDC02 /* NSObject+Extension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+Extension.m"; sourceTree = ""; }; 27 | /* End PBXFileReference section */ 28 | 29 | /* Begin PBXFrameworksBuildPhase section */ 30 | E9F4A67C2508C9E7002EDC02 /* Frameworks */ = { 31 | isa = PBXFrameworksBuildPhase; 32 | buildActionMask = 2147483647; 33 | files = ( 34 | ); 35 | runOnlyForDeploymentPostprocessing = 0; 36 | }; 37 | /* End PBXFrameworksBuildPhase section */ 38 | 39 | /* Begin PBXGroup section */ 40 | E9F4A6752508C9E7002EDC02 = { 41 | isa = PBXGroup; 42 | children = ( 43 | E9F4A6812508C9E7002EDC02 /* Sources */, 44 | E9F4A6802508C9E7002EDC02 /* Products */, 45 | ); 46 | sourceTree = ""; 47 | }; 48 | E9F4A6802508C9E7002EDC02 /* Products */ = { 49 | isa = PBXGroup; 50 | children = ( 51 | E9F4A67F2508C9E7002EDC02 /* Blurberry.framework */, 52 | ); 53 | name = Products; 54 | sourceTree = ""; 55 | }; 56 | E9F4A6812508C9E7002EDC02 /* Sources */ = { 57 | isa = PBXGroup; 58 | children = ( 59 | E9F4A6822508C9E7002EDC02 /* Blurberry.h */, 60 | E9F4A69C2508D016002EDC02 /* General */, 61 | E9F4A69E2508D016002EDC02 /* Views */, 62 | E9F4A6A12508D016002EDC02 /* Extensions */, 63 | E9F4A6832508C9E7002EDC02 /* Info.plist */, 64 | ); 65 | path = Sources; 66 | sourceTree = ""; 67 | }; 68 | E9F4A69C2508D016002EDC02 /* General */ = { 69 | isa = PBXGroup; 70 | children = ( 71 | E9F4A69D2508D016002EDC02 /* Blurberry.swift */, 72 | ); 73 | path = General; 74 | sourceTree = ""; 75 | }; 76 | E9F4A69E2508D016002EDC02 /* Views */ = { 77 | isa = PBXGroup; 78 | children = ( 79 | E9F4A6A02508D016002EDC02 /* VisualEffectView+Public.swift */, 80 | E9F4A69F2508D016002EDC02 /* VisualEffectView+Internal.swift */, 81 | ); 82 | path = Views; 83 | sourceTree = ""; 84 | }; 85 | E9F4A6A12508D016002EDC02 /* Extensions */ = { 86 | isa = PBXGroup; 87 | children = ( 88 | E9F4A6A22508D016002EDC02 /* NSObject+Extension.h */, 89 | E9F4A6A32508D016002EDC02 /* NSObject+Extension.m */, 90 | ); 91 | path = Extensions; 92 | sourceTree = ""; 93 | }; 94 | /* End PBXGroup section */ 95 | 96 | /* Begin PBXHeadersBuildPhase section */ 97 | E9F4A67A2508C9E7002EDC02 /* Headers */ = { 98 | isa = PBXHeadersBuildPhase; 99 | buildActionMask = 2147483647; 100 | files = ( 101 | E9F4A6A72508D016002EDC02 /* NSObject+Extension.h in Headers */, 102 | E9F4A6842508C9E7002EDC02 /* Blurberry.h in Headers */, 103 | ); 104 | runOnlyForDeploymentPostprocessing = 0; 105 | }; 106 | /* End PBXHeadersBuildPhase section */ 107 | 108 | /* Begin PBXNativeTarget section */ 109 | E9F4A67E2508C9E7002EDC02 /* Blurberry */ = { 110 | isa = PBXNativeTarget; 111 | buildConfigurationList = E9F4A6872508C9E7002EDC02 /* Build configuration list for PBXNativeTarget "Blurberry" */; 112 | buildPhases = ( 113 | E9F4A67A2508C9E7002EDC02 /* Headers */, 114 | E9F4A67B2508C9E7002EDC02 /* Sources */, 115 | E9F4A67C2508C9E7002EDC02 /* Frameworks */, 116 | E9F4A67D2508C9E7002EDC02 /* Resources */, 117 | ); 118 | buildRules = ( 119 | ); 120 | dependencies = ( 121 | ); 122 | name = Blurberry; 123 | productName = Blurberry; 124 | productReference = E9F4A67F2508C9E7002EDC02 /* Blurberry.framework */; 125 | productType = "com.apple.product-type.framework"; 126 | }; 127 | /* End PBXNativeTarget section */ 128 | 129 | /* Begin PBXProject section */ 130 | E9F4A6762508C9E7002EDC02 /* Project object */ = { 131 | isa = PBXProject; 132 | attributes = { 133 | LastUpgradeCheck = 1170; 134 | ORGANIZATIONNAME = "Pavel Puzyrev"; 135 | TargetAttributes = { 136 | E9F4A67E2508C9E7002EDC02 = { 137 | CreatedOnToolsVersion = 11.7; 138 | }; 139 | }; 140 | }; 141 | buildConfigurationList = E9F4A6792508C9E7002EDC02 /* Build configuration list for PBXProject "Blurberry" */; 142 | compatibilityVersion = "Xcode 9.3"; 143 | developmentRegion = en; 144 | hasScannedForEncodings = 0; 145 | knownRegions = ( 146 | en, 147 | Base, 148 | ); 149 | mainGroup = E9F4A6752508C9E7002EDC02; 150 | productRefGroup = E9F4A6802508C9E7002EDC02 /* Products */; 151 | projectDirPath = ""; 152 | projectRoot = ""; 153 | targets = ( 154 | E9F4A67E2508C9E7002EDC02 /* Blurberry */, 155 | ); 156 | }; 157 | /* End PBXProject section */ 158 | 159 | /* Begin PBXResourcesBuildPhase section */ 160 | E9F4A67D2508C9E7002EDC02 /* Resources */ = { 161 | isa = PBXResourcesBuildPhase; 162 | buildActionMask = 2147483647; 163 | files = ( 164 | ); 165 | runOnlyForDeploymentPostprocessing = 0; 166 | }; 167 | /* End PBXResourcesBuildPhase section */ 168 | 169 | /* Begin PBXSourcesBuildPhase section */ 170 | E9F4A67B2508C9E7002EDC02 /* Sources */ = { 171 | isa = PBXSourcesBuildPhase; 172 | buildActionMask = 2147483647; 173 | files = ( 174 | E9F4A6A62508D016002EDC02 /* VisualEffectView+Public.swift in Sources */, 175 | E9F4A6A52508D016002EDC02 /* VisualEffectView+Internal.swift in Sources */, 176 | E9F4A6A42508D016002EDC02 /* Blurberry.swift in Sources */, 177 | E9F4A6A82508D016002EDC02 /* NSObject+Extension.m in Sources */, 178 | ); 179 | runOnlyForDeploymentPostprocessing = 0; 180 | }; 181 | /* End PBXSourcesBuildPhase section */ 182 | 183 | /* Begin XCBuildConfiguration section */ 184 | E9F4A6852508C9E7002EDC02 /* Debug */ = { 185 | isa = XCBuildConfiguration; 186 | buildSettings = { 187 | ALWAYS_SEARCH_USER_PATHS = NO; 188 | CLANG_ANALYZER_NONNULL = YES; 189 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 190 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 191 | CLANG_CXX_LIBRARY = "libc++"; 192 | CLANG_ENABLE_MODULES = YES; 193 | CLANG_ENABLE_OBJC_ARC = YES; 194 | CLANG_ENABLE_OBJC_WEAK = YES; 195 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 196 | CLANG_WARN_BOOL_CONVERSION = YES; 197 | CLANG_WARN_COMMA = YES; 198 | CLANG_WARN_CONSTANT_CONVERSION = YES; 199 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 200 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 201 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 202 | CLANG_WARN_EMPTY_BODY = YES; 203 | CLANG_WARN_ENUM_CONVERSION = YES; 204 | CLANG_WARN_INFINITE_RECURSION = YES; 205 | CLANG_WARN_INT_CONVERSION = YES; 206 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 207 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 208 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 209 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 210 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 211 | CLANG_WARN_STRICT_PROTOTYPES = YES; 212 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 213 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 214 | CLANG_WARN_UNREACHABLE_CODE = YES; 215 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 216 | COPY_PHASE_STRIP = NO; 217 | CURRENT_PROJECT_VERSION = 1; 218 | DEBUG_INFORMATION_FORMAT = dwarf; 219 | ENABLE_STRICT_OBJC_MSGSEND = YES; 220 | ENABLE_TESTABILITY = YES; 221 | GCC_C_LANGUAGE_STANDARD = gnu11; 222 | GCC_DYNAMIC_NO_PIC = NO; 223 | GCC_NO_COMMON_BLOCKS = YES; 224 | GCC_OPTIMIZATION_LEVEL = 0; 225 | GCC_PREPROCESSOR_DEFINITIONS = ( 226 | "DEBUG=1", 227 | "$(inherited)", 228 | ); 229 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 230 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 231 | GCC_WARN_UNDECLARED_SELECTOR = YES; 232 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 233 | GCC_WARN_UNUSED_FUNCTION = YES; 234 | GCC_WARN_UNUSED_VARIABLE = YES; 235 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 236 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 237 | MTL_FAST_MATH = YES; 238 | ONLY_ACTIVE_ARCH = YES; 239 | SDKROOT = iphoneos; 240 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 241 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 242 | VERSIONING_SYSTEM = "apple-generic"; 243 | VERSION_INFO_PREFIX = ""; 244 | }; 245 | name = Debug; 246 | }; 247 | E9F4A6862508C9E7002EDC02 /* Release */ = { 248 | isa = XCBuildConfiguration; 249 | buildSettings = { 250 | ALWAYS_SEARCH_USER_PATHS = NO; 251 | CLANG_ANALYZER_NONNULL = YES; 252 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 253 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 254 | CLANG_CXX_LIBRARY = "libc++"; 255 | CLANG_ENABLE_MODULES = YES; 256 | CLANG_ENABLE_OBJC_ARC = YES; 257 | CLANG_ENABLE_OBJC_WEAK = YES; 258 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 259 | CLANG_WARN_BOOL_CONVERSION = YES; 260 | CLANG_WARN_COMMA = YES; 261 | CLANG_WARN_CONSTANT_CONVERSION = YES; 262 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 263 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 264 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 265 | CLANG_WARN_EMPTY_BODY = YES; 266 | CLANG_WARN_ENUM_CONVERSION = YES; 267 | CLANG_WARN_INFINITE_RECURSION = YES; 268 | CLANG_WARN_INT_CONVERSION = YES; 269 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 270 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 271 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 272 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 273 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 274 | CLANG_WARN_STRICT_PROTOTYPES = YES; 275 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 276 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 277 | CLANG_WARN_UNREACHABLE_CODE = YES; 278 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 279 | COPY_PHASE_STRIP = NO; 280 | CURRENT_PROJECT_VERSION = 1; 281 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 282 | ENABLE_NS_ASSERTIONS = NO; 283 | ENABLE_STRICT_OBJC_MSGSEND = YES; 284 | GCC_C_LANGUAGE_STANDARD = gnu11; 285 | GCC_NO_COMMON_BLOCKS = YES; 286 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 287 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 288 | GCC_WARN_UNDECLARED_SELECTOR = YES; 289 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 290 | GCC_WARN_UNUSED_FUNCTION = YES; 291 | GCC_WARN_UNUSED_VARIABLE = YES; 292 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 293 | MTL_ENABLE_DEBUG_INFO = NO; 294 | MTL_FAST_MATH = YES; 295 | SDKROOT = iphoneos; 296 | SWIFT_COMPILATION_MODE = wholemodule; 297 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 298 | VALIDATE_PRODUCT = YES; 299 | VERSIONING_SYSTEM = "apple-generic"; 300 | VERSION_INFO_PREFIX = ""; 301 | }; 302 | name = Release; 303 | }; 304 | E9F4A6882508C9E7002EDC02 /* Debug */ = { 305 | isa = XCBuildConfiguration; 306 | buildSettings = { 307 | CODE_SIGN_STYLE = Automatic; 308 | DEFINES_MODULE = YES; 309 | DEVELOPMENT_TEAM = 22BDH96YAS; 310 | DYLIB_COMPATIBILITY_VERSION = 1; 311 | DYLIB_CURRENT_VERSION = 1; 312 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 313 | INFOPLIST_FILE = Sources/Info.plist; 314 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 315 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 316 | LD_RUNPATH_SEARCH_PATHS = ( 317 | "$(inherited)", 318 | "@executable_path/Frameworks", 319 | "@loader_path/Frameworks", 320 | ); 321 | MARKETING_VERSION = 0.0.1; 322 | PRODUCT_BUNDLE_IDENTIFIER = com.cannedapp.blurberry; 323 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 324 | SKIP_INSTALL = YES; 325 | SUPPORTS_MACCATALYST = NO; 326 | SWIFT_OBJC_BRIDGING_HEADER = ""; 327 | SWIFT_VERSION = 5.0; 328 | TARGETED_DEVICE_FAMILY = "1,2"; 329 | }; 330 | name = Debug; 331 | }; 332 | E9F4A6892508C9E7002EDC02 /* Release */ = { 333 | isa = XCBuildConfiguration; 334 | buildSettings = { 335 | CODE_SIGN_STYLE = Automatic; 336 | DEFINES_MODULE = YES; 337 | DEVELOPMENT_TEAM = 22BDH96YAS; 338 | DYLIB_COMPATIBILITY_VERSION = 1; 339 | DYLIB_CURRENT_VERSION = 1; 340 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 341 | INFOPLIST_FILE = Sources/Info.plist; 342 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 343 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 344 | LD_RUNPATH_SEARCH_PATHS = ( 345 | "$(inherited)", 346 | "@executable_path/Frameworks", 347 | "@loader_path/Frameworks", 348 | ); 349 | MARKETING_VERSION = 0.0.1; 350 | PRODUCT_BUNDLE_IDENTIFIER = com.cannedapp.blurberry; 351 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 352 | SKIP_INSTALL = YES; 353 | SUPPORTS_MACCATALYST = NO; 354 | SWIFT_OBJC_BRIDGING_HEADER = ""; 355 | SWIFT_VERSION = 5.0; 356 | TARGETED_DEVICE_FAMILY = "1,2"; 357 | }; 358 | name = Release; 359 | }; 360 | /* End XCBuildConfiguration section */ 361 | 362 | /* Begin XCConfigurationList section */ 363 | E9F4A6792508C9E7002EDC02 /* Build configuration list for PBXProject "Blurberry" */ = { 364 | isa = XCConfigurationList; 365 | buildConfigurations = ( 366 | E9F4A6852508C9E7002EDC02 /* Debug */, 367 | E9F4A6862508C9E7002EDC02 /* Release */, 368 | ); 369 | defaultConfigurationIsVisible = 0; 370 | defaultConfigurationName = Release; 371 | }; 372 | E9F4A6872508C9E7002EDC02 /* Build configuration list for PBXNativeTarget "Blurberry" */ = { 373 | isa = XCConfigurationList; 374 | buildConfigurations = ( 375 | E9F4A6882508C9E7002EDC02 /* Debug */, 376 | E9F4A6892508C9E7002EDC02 /* Release */, 377 | ); 378 | defaultConfigurationIsVisible = 0; 379 | defaultConfigurationName = Release; 380 | }; 381 | /* End XCConfigurationList section */ 382 | }; 383 | rootObject = E9F4A6762508C9E7002EDC02 /* Project object */; 384 | } 385 | -------------------------------------------------------------------------------- /Blurberry.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Blurberry.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Blurberry.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Blurberry.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Demo/Blurberry-Demo-iOS/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Blurberry-Demo-iOS 4 | // 5 | // Created by Pavel Puzyrev on 09.09.2020. 6 | // 7 | // Copyright (c) 2020 Pavel Puzyrev 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | 27 | import UIKit 28 | 29 | @UIApplicationMain 30 | class AppDelegate: UIResponder, UIApplicationDelegate { 31 | 32 | var window: UIWindow? 33 | 34 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 35 | return true 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /Demo/Blurberry-Demo-iOS/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "scale" : "1x", 46 | "size" : "20x20" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "scale" : "2x", 51 | "size" : "20x20" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "1x", 56 | "size" : "29x29" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "29x29" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "1x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "40x40" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "1x", 76 | "size" : "76x76" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "76x76" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "scale" : "2x", 86 | "size" : "83.5x83.5" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "scale" : "1x", 91 | "size" : "1024x1024" 92 | } 93 | ], 94 | "info" : { 95 | "author" : "xcode", 96 | "version" : 1 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Demo/Blurberry-Demo-iOS/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Demo/Blurberry-Demo-iOS/Assets.xcassets/wwdc.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "wwdc.png", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Demo/Blurberry-Demo-iOS/Assets.xcassets/wwdc.imageset/wwdc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unboxme/Blurberry/df33a04e403e092ed29fc1ee878a56a659ebb966/Demo/Blurberry-Demo-iOS/Assets.xcassets/wwdc.imageset/wwdc.png -------------------------------------------------------------------------------- /Demo/Blurberry-Demo-iOS/Base.lproj/LaunchScreen.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 | -------------------------------------------------------------------------------- /Demo/Blurberry-Demo-iOS/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 | 40 | 41 | 42 | 43 | 44 | 45 | 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 | 88 | 104 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /Demo/Blurberry-Demo-iOS/Button.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Button.swift 3 | // Blurberry-Demo-iOS 4 | // 5 | // Created by Pavel Puzyrev on 09.09.2020. 6 | // 7 | // Copyright (c) 2020 Pavel Puzyrev 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | 27 | import UIKit 28 | 29 | @IBDesignable 30 | final class Button: UIButton { 31 | 32 | @IBInspectable var color: UIColor? 33 | @IBInspectable var providedColor: UIColor? 34 | 35 | override init(frame: CGRect) { 36 | super.init(frame: frame) 37 | setup() 38 | } 39 | 40 | required init?(coder: NSCoder) { 41 | super.init(coder: coder) 42 | setup() 43 | } 44 | 45 | override func awakeFromNib() { 46 | super.awakeFromNib() 47 | setup() 48 | } 49 | 50 | override func prepareForInterfaceBuilder() { 51 | super.prepareForInterfaceBuilder() 52 | setup() 53 | } 54 | 55 | override var isHighlighted: Bool { 56 | didSet { 57 | UIView.animate(withDuration: 0.25) { [unowned self] in 58 | self.alpha = self.isHighlighted ? 0.5 : 1.0 59 | } 60 | } 61 | } 62 | 63 | private func setup() { 64 | guard let color = color else { 65 | return 66 | } 67 | 68 | setTitleColor(color, for: .normal) 69 | layer.borderColor = color.cgColor 70 | layer.borderWidth = 2.0 71 | layer.cornerRadius = 8.0 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Demo/Blurberry-Demo-iOS/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 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UIStatusBarHidden 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationLandscapeLeft 36 | UIInterfaceOrientationLandscapeRight 37 | UIInterfaceOrientationPortrait 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /Demo/Blurberry-Demo-iOS/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // Blurberry-Demo-iOS 4 | // 5 | // Created by Pavel Puzyrev on 09.09.2020. 6 | // 7 | // Copyright (c) 2020 Pavel Puzyrev 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | 27 | import UIKit 28 | import Blurberry 29 | 30 | final class ViewController: UIViewController { 31 | 32 | @IBOutlet private weak var blurSlider: UISlider? 33 | @IBOutlet private weak var visualEffectView: UIVisualEffectView? 34 | @IBOutlet private weak var separatorView: UIView? 35 | 36 | override func viewDidLoad() { 37 | super.viewDidLoad() 38 | 39 | if let blurSlider = blurSlider { 40 | visualEffectView?.blur.radius = blurSlider.value.blurReady 41 | visualEffectView?.blur.tintColor = .clear 42 | } 43 | } 44 | } 45 | 46 | private extension ViewController { 47 | 48 | @IBAction func sliderValueChanged(_ blurSlider: UISlider) { 49 | visualEffectView?.blur.radius = blurSlider.value.blurReady 50 | } 51 | 52 | @IBAction func colorButtonClicked(_ button: Button) { 53 | UIView.animate(withDuration: 0.25) { [unowned self] in 54 | self.blurSlider?.tintColor = button.color 55 | self.separatorView?.backgroundColor = button.color 56 | self.visualEffectView?.blur.tintColor = button.providedColor 57 | } 58 | } 59 | } 60 | 61 | private extension Float { 62 | 63 | var blurReady: CGFloat { 64 | CGFloat(self * 100.0 / 5.0) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Demo/Blurberry-Demo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | E9F4A6D02508D79A002EDC02 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9F4A6CF2508D79A002EDC02 /* AppDelegate.swift */; }; 11 | E9F4A6D42508D79A002EDC02 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9F4A6D32508D79A002EDC02 /* ViewController.swift */; }; 12 | E9F4A6D72508D79A002EDC02 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E9F4A6D52508D79A002EDC02 /* Main.storyboard */; }; 13 | E9F4A6D92508D79B002EDC02 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E9F4A6D82508D79B002EDC02 /* Assets.xcassets */; }; 14 | E9F4A6DC2508D79B002EDC02 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E9F4A6DA2508D79B002EDC02 /* LaunchScreen.storyboard */; }; 15 | E9F4A6FE2508F8D8002EDC02 /* Blurberry.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E9F4A6FD2508F8D8002EDC02 /* Blurberry.framework */; }; 16 | E9F4A6FF2508F8D8002EDC02 /* Blurberry.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = E9F4A6FD2508F8D8002EDC02 /* Blurberry.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 17 | E9F4A7022508FA52002EDC02 /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9F4A7012508FA52002EDC02 /* Button.swift */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXCopyFilesBuildPhase section */ 21 | E9F4A7002508F8D8002EDC02 /* Embed Frameworks */ = { 22 | isa = PBXCopyFilesBuildPhase; 23 | buildActionMask = 2147483647; 24 | dstPath = ""; 25 | dstSubfolderSpec = 10; 26 | files = ( 27 | E9F4A6FF2508F8D8002EDC02 /* Blurberry.framework in Embed Frameworks */, 28 | ); 29 | name = "Embed Frameworks"; 30 | runOnlyForDeploymentPostprocessing = 0; 31 | }; 32 | /* End PBXCopyFilesBuildPhase section */ 33 | 34 | /* Begin PBXFileReference section */ 35 | E9F4A6CD2508D79A002EDC02 /* Blurberry-Demo-iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Blurberry-Demo-iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 36 | E9F4A6CF2508D79A002EDC02 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 37 | E9F4A6D32508D79A002EDC02 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 38 | E9F4A6D62508D79A002EDC02 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 39 | E9F4A6D82508D79B002EDC02 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 40 | E9F4A6DB2508D79B002EDC02 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 41 | E9F4A6DD2508D79B002EDC02 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 42 | E9F4A6FD2508F8D8002EDC02 /* Blurberry.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Blurberry.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 43 | E9F4A7012508FA52002EDC02 /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = ""; }; 44 | /* End PBXFileReference section */ 45 | 46 | /* Begin PBXFrameworksBuildPhase section */ 47 | E9F4A6CA2508D79A002EDC02 /* Frameworks */ = { 48 | isa = PBXFrameworksBuildPhase; 49 | buildActionMask = 2147483647; 50 | files = ( 51 | E9F4A6FE2508F8D8002EDC02 /* Blurberry.framework in Frameworks */, 52 | ); 53 | runOnlyForDeploymentPostprocessing = 0; 54 | }; 55 | /* End PBXFrameworksBuildPhase section */ 56 | 57 | /* Begin PBXGroup section */ 58 | E9F4A6A92508D4D9002EDC02 = { 59 | isa = PBXGroup; 60 | children = ( 61 | E9F4A6CE2508D79A002EDC02 /* Blurberry-Demo-iOS */, 62 | E9F4A6B32508D4D9002EDC02 /* Products */, 63 | E9F4A6FC2508F8D8002EDC02 /* Frameworks */, 64 | ); 65 | sourceTree = ""; 66 | }; 67 | E9F4A6B32508D4D9002EDC02 /* Products */ = { 68 | isa = PBXGroup; 69 | children = ( 70 | E9F4A6CD2508D79A002EDC02 /* Blurberry-Demo-iOS.app */, 71 | ); 72 | name = Products; 73 | sourceTree = ""; 74 | }; 75 | E9F4A6CE2508D79A002EDC02 /* Blurberry-Demo-iOS */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | E9F4A6DD2508D79B002EDC02 /* Info.plist */, 79 | E9F4A6CF2508D79A002EDC02 /* AppDelegate.swift */, 80 | E9F4A6D32508D79A002EDC02 /* ViewController.swift */, 81 | E9F4A7012508FA52002EDC02 /* Button.swift */, 82 | E9F4A6D52508D79A002EDC02 /* Main.storyboard */, 83 | E9F4A6DA2508D79B002EDC02 /* LaunchScreen.storyboard */, 84 | E9F4A6D82508D79B002EDC02 /* Assets.xcassets */, 85 | ); 86 | path = "Blurberry-Demo-iOS"; 87 | sourceTree = ""; 88 | }; 89 | E9F4A6FC2508F8D8002EDC02 /* Frameworks */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | E9F4A6FD2508F8D8002EDC02 /* Blurberry.framework */, 93 | ); 94 | name = Frameworks; 95 | sourceTree = ""; 96 | }; 97 | /* End PBXGroup section */ 98 | 99 | /* Begin PBXNativeTarget section */ 100 | E9F4A6CC2508D79A002EDC02 /* Blurberry-Demo-iOS */ = { 101 | isa = PBXNativeTarget; 102 | buildConfigurationList = E9F4A6E02508D79B002EDC02 /* Build configuration list for PBXNativeTarget "Blurberry-Demo-iOS" */; 103 | buildPhases = ( 104 | E9F4A6C92508D79A002EDC02 /* Sources */, 105 | E9F4A6CA2508D79A002EDC02 /* Frameworks */, 106 | E9F4A6CB2508D79A002EDC02 /* Resources */, 107 | E9F4A7002508F8D8002EDC02 /* Embed Frameworks */, 108 | ); 109 | buildRules = ( 110 | ); 111 | dependencies = ( 112 | ); 113 | name = "Blurberry-Demo-iOS"; 114 | productName = "Blurberry-Demo-iOS"; 115 | productReference = E9F4A6CD2508D79A002EDC02 /* Blurberry-Demo-iOS.app */; 116 | productType = "com.apple.product-type.application"; 117 | }; 118 | /* End PBXNativeTarget section */ 119 | 120 | /* Begin PBXProject section */ 121 | E9F4A6AA2508D4D9002EDC02 /* Project object */ = { 122 | isa = PBXProject; 123 | attributes = { 124 | LastSwiftUpdateCheck = 1170; 125 | LastUpgradeCheck = 1170; 126 | ORGANIZATIONNAME = "Pavel Puzyrev"; 127 | TargetAttributes = { 128 | E9F4A6CC2508D79A002EDC02 = { 129 | CreatedOnToolsVersion = 11.7; 130 | }; 131 | }; 132 | }; 133 | buildConfigurationList = E9F4A6AD2508D4D9002EDC02 /* Build configuration list for PBXProject "Blurberry-Demo" */; 134 | compatibilityVersion = "Xcode 9.3"; 135 | developmentRegion = en; 136 | hasScannedForEncodings = 0; 137 | knownRegions = ( 138 | en, 139 | Base, 140 | ); 141 | mainGroup = E9F4A6A92508D4D9002EDC02; 142 | productRefGroup = E9F4A6B32508D4D9002EDC02 /* Products */; 143 | projectDirPath = ""; 144 | projectRoot = ""; 145 | targets = ( 146 | E9F4A6CC2508D79A002EDC02 /* Blurberry-Demo-iOS */, 147 | ); 148 | }; 149 | /* End PBXProject section */ 150 | 151 | /* Begin PBXResourcesBuildPhase section */ 152 | E9F4A6CB2508D79A002EDC02 /* Resources */ = { 153 | isa = PBXResourcesBuildPhase; 154 | buildActionMask = 2147483647; 155 | files = ( 156 | E9F4A6DC2508D79B002EDC02 /* LaunchScreen.storyboard in Resources */, 157 | E9F4A6D92508D79B002EDC02 /* Assets.xcassets in Resources */, 158 | E9F4A6D72508D79A002EDC02 /* Main.storyboard in Resources */, 159 | ); 160 | runOnlyForDeploymentPostprocessing = 0; 161 | }; 162 | /* End PBXResourcesBuildPhase section */ 163 | 164 | /* Begin PBXSourcesBuildPhase section */ 165 | E9F4A6C92508D79A002EDC02 /* Sources */ = { 166 | isa = PBXSourcesBuildPhase; 167 | buildActionMask = 2147483647; 168 | files = ( 169 | E9F4A6D42508D79A002EDC02 /* ViewController.swift in Sources */, 170 | E9F4A7022508FA52002EDC02 /* Button.swift in Sources */, 171 | E9F4A6D02508D79A002EDC02 /* AppDelegate.swift in Sources */, 172 | ); 173 | runOnlyForDeploymentPostprocessing = 0; 174 | }; 175 | /* End PBXSourcesBuildPhase section */ 176 | 177 | /* Begin PBXVariantGroup section */ 178 | E9F4A6D52508D79A002EDC02 /* Main.storyboard */ = { 179 | isa = PBXVariantGroup; 180 | children = ( 181 | E9F4A6D62508D79A002EDC02 /* Base */, 182 | ); 183 | name = Main.storyboard; 184 | sourceTree = ""; 185 | }; 186 | E9F4A6DA2508D79B002EDC02 /* LaunchScreen.storyboard */ = { 187 | isa = PBXVariantGroup; 188 | children = ( 189 | E9F4A6DB2508D79B002EDC02 /* Base */, 190 | ); 191 | name = LaunchScreen.storyboard; 192 | sourceTree = ""; 193 | }; 194 | /* End PBXVariantGroup section */ 195 | 196 | /* Begin XCBuildConfiguration section */ 197 | E9F4A6C42508D4DA002EDC02 /* Debug */ = { 198 | isa = XCBuildConfiguration; 199 | buildSettings = { 200 | ALWAYS_SEARCH_USER_PATHS = NO; 201 | CLANG_ANALYZER_NONNULL = YES; 202 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 203 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 204 | CLANG_CXX_LIBRARY = "libc++"; 205 | CLANG_ENABLE_MODULES = YES; 206 | CLANG_ENABLE_OBJC_ARC = YES; 207 | CLANG_ENABLE_OBJC_WEAK = YES; 208 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 209 | CLANG_WARN_BOOL_CONVERSION = YES; 210 | CLANG_WARN_COMMA = YES; 211 | CLANG_WARN_CONSTANT_CONVERSION = YES; 212 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 213 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 214 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 215 | CLANG_WARN_EMPTY_BODY = YES; 216 | CLANG_WARN_ENUM_CONVERSION = YES; 217 | CLANG_WARN_INFINITE_RECURSION = YES; 218 | CLANG_WARN_INT_CONVERSION = YES; 219 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 220 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 221 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 222 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 223 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 224 | CLANG_WARN_STRICT_PROTOTYPES = YES; 225 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 226 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 227 | CLANG_WARN_UNREACHABLE_CODE = YES; 228 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 229 | COPY_PHASE_STRIP = NO; 230 | DEBUG_INFORMATION_FORMAT = dwarf; 231 | ENABLE_STRICT_OBJC_MSGSEND = YES; 232 | ENABLE_TESTABILITY = YES; 233 | GCC_C_LANGUAGE_STANDARD = gnu11; 234 | GCC_DYNAMIC_NO_PIC = NO; 235 | GCC_NO_COMMON_BLOCKS = YES; 236 | GCC_OPTIMIZATION_LEVEL = 0; 237 | GCC_PREPROCESSOR_DEFINITIONS = ( 238 | "DEBUG=1", 239 | "$(inherited)", 240 | ); 241 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 242 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 243 | GCC_WARN_UNDECLARED_SELECTOR = YES; 244 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 245 | GCC_WARN_UNUSED_FUNCTION = YES; 246 | GCC_WARN_UNUSED_VARIABLE = YES; 247 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 248 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 249 | MTL_FAST_MATH = YES; 250 | ONLY_ACTIVE_ARCH = YES; 251 | SDKROOT = iphoneos; 252 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 253 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 254 | }; 255 | name = Debug; 256 | }; 257 | E9F4A6C52508D4DA002EDC02 /* Release */ = { 258 | isa = XCBuildConfiguration; 259 | buildSettings = { 260 | ALWAYS_SEARCH_USER_PATHS = NO; 261 | CLANG_ANALYZER_NONNULL = YES; 262 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 263 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 264 | CLANG_CXX_LIBRARY = "libc++"; 265 | CLANG_ENABLE_MODULES = YES; 266 | CLANG_ENABLE_OBJC_ARC = YES; 267 | CLANG_ENABLE_OBJC_WEAK = YES; 268 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 269 | CLANG_WARN_BOOL_CONVERSION = YES; 270 | CLANG_WARN_COMMA = YES; 271 | CLANG_WARN_CONSTANT_CONVERSION = YES; 272 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 273 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 274 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 275 | CLANG_WARN_EMPTY_BODY = YES; 276 | CLANG_WARN_ENUM_CONVERSION = YES; 277 | CLANG_WARN_INFINITE_RECURSION = YES; 278 | CLANG_WARN_INT_CONVERSION = YES; 279 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 280 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 281 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 282 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 283 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 284 | CLANG_WARN_STRICT_PROTOTYPES = YES; 285 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 286 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 287 | CLANG_WARN_UNREACHABLE_CODE = YES; 288 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 289 | COPY_PHASE_STRIP = NO; 290 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 291 | ENABLE_NS_ASSERTIONS = NO; 292 | ENABLE_STRICT_OBJC_MSGSEND = YES; 293 | GCC_C_LANGUAGE_STANDARD = gnu11; 294 | GCC_NO_COMMON_BLOCKS = YES; 295 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 296 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 297 | GCC_WARN_UNDECLARED_SELECTOR = YES; 298 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 299 | GCC_WARN_UNUSED_FUNCTION = YES; 300 | GCC_WARN_UNUSED_VARIABLE = YES; 301 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 302 | MTL_ENABLE_DEBUG_INFO = NO; 303 | MTL_FAST_MATH = YES; 304 | SDKROOT = iphoneos; 305 | SWIFT_COMPILATION_MODE = wholemodule; 306 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 307 | VALIDATE_PRODUCT = YES; 308 | }; 309 | name = Release; 310 | }; 311 | E9F4A6DE2508D79B002EDC02 /* Debug */ = { 312 | isa = XCBuildConfiguration; 313 | buildSettings = { 314 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 315 | CODE_SIGN_STYLE = Automatic; 316 | DEVELOPMENT_TEAM = 22BDH96YAS; 317 | INFOPLIST_FILE = "Blurberry-Demo-iOS/Info.plist"; 318 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 319 | LD_RUNPATH_SEARCH_PATHS = ( 320 | "$(inherited)", 321 | "@executable_path/Frameworks", 322 | ); 323 | PRODUCT_BUNDLE_IDENTIFIER = "com.cannedapp.blurberry-demo-ios"; 324 | PRODUCT_NAME = "$(TARGET_NAME)"; 325 | SWIFT_VERSION = 5.0; 326 | TARGETED_DEVICE_FAMILY = "1,2"; 327 | }; 328 | name = Debug; 329 | }; 330 | E9F4A6DF2508D79B002EDC02 /* Release */ = { 331 | isa = XCBuildConfiguration; 332 | buildSettings = { 333 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 334 | CODE_SIGN_STYLE = Automatic; 335 | DEVELOPMENT_TEAM = 22BDH96YAS; 336 | INFOPLIST_FILE = "Blurberry-Demo-iOS/Info.plist"; 337 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 338 | LD_RUNPATH_SEARCH_PATHS = ( 339 | "$(inherited)", 340 | "@executable_path/Frameworks", 341 | ); 342 | PRODUCT_BUNDLE_IDENTIFIER = "com.cannedapp.blurberry-demo-ios"; 343 | PRODUCT_NAME = "$(TARGET_NAME)"; 344 | SWIFT_VERSION = 5.0; 345 | TARGETED_DEVICE_FAMILY = "1,2"; 346 | }; 347 | name = Release; 348 | }; 349 | /* End XCBuildConfiguration section */ 350 | 351 | /* Begin XCConfigurationList section */ 352 | E9F4A6AD2508D4D9002EDC02 /* Build configuration list for PBXProject "Blurberry-Demo" */ = { 353 | isa = XCConfigurationList; 354 | buildConfigurations = ( 355 | E9F4A6C42508D4DA002EDC02 /* Debug */, 356 | E9F4A6C52508D4DA002EDC02 /* Release */, 357 | ); 358 | defaultConfigurationIsVisible = 0; 359 | defaultConfigurationName = Release; 360 | }; 361 | E9F4A6E02508D79B002EDC02 /* Build configuration list for PBXNativeTarget "Blurberry-Demo-iOS" */ = { 362 | isa = XCConfigurationList; 363 | buildConfigurations = ( 364 | E9F4A6DE2508D79B002EDC02 /* Debug */, 365 | E9F4A6DF2508D79B002EDC02 /* Release */, 366 | ); 367 | defaultConfigurationIsVisible = 0; 368 | defaultConfigurationName = Release; 369 | }; 370 | /* End XCConfigurationList section */ 371 | }; 372 | rootObject = E9F4A6AA2508D4D9002EDC02 /* Project object */; 373 | } 374 | -------------------------------------------------------------------------------- /Demo/Blurberry-Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demo/Blurberry-Demo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 Pavel Puzyrev 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 13 | all 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 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Blurberry 2 | 3 | Transparent blur using UIVisualEffectView without subclassing. 4 | 5 | ![GIF Demo](https://github.com/unboxme/Blurberry/blob/master/Resources/demo.gif) 6 | 7 | [[video demo]](https://vimeo.com/457206677) 8 | 9 | [[appetize demo]](https://appetize.io/app/u2udhgwh0cgm12at0rmgjxtphr) 10 | 11 | ## Features 12 | - Based on UIVisualEffectView 13 | - Supports **iOS 14** and animation blocks 14 | - Super safe and super easy 15 | 16 | ## Usage 17 | 18 | Just create a `UIVisualEffectView` in any way. Code, storyboards, XIBs, etc. 19 | 20 | Customize it like example bellow via `blur` wrapper: 21 | ```swift 22 | visualEffectView.blur.radius = 5.0 23 | visualEffectView.blur.tintColor = .clear 24 | ``` 25 | 26 | Don't forget to set a `tintColor` value, otherwise it will be 30% white like `UIBlurEffect.Style.Light` by default. 27 | 28 | ## Installation 29 | 30 | ### Cocoapods 31 | 32 | Add the Blurberry pod to your Podfile: 33 | ```ruby 34 | platform :ios, '10.0' 35 | 36 | use_frameworks! 37 | 38 | target 'BlurryApp' do 39 | pod 'Blurberry' 40 | end 41 | ``` 42 | 43 | ## Next Steps 44 | 45 | - [x] iOS 10, 11, 12 support 46 | - [ ] Other platform support (such as macOS) 47 | - [ ] Remove ObjC code or make it private 48 | - [ ] Add manager to check blur availability and other service info 49 | - [ ] Hide private API class names, method names, etc. 50 | 51 | ## Disclaimer 52 | 53 | This framework uses private API, so just keep in mind it before submitting to the AppStore. 54 | 55 | ## Requirements 56 | 57 | - iOS 10.0+ 58 | - Swift 5 59 | -------------------------------------------------------------------------------- /Resources/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unboxme/Blurberry/df33a04e403e092ed29fc1ee878a56a659ebb966/Resources/demo.gif -------------------------------------------------------------------------------- /Sources/Blurberry.h: -------------------------------------------------------------------------------- 1 | // 2 | // Blurberry.h 3 | // Blurberry 4 | // 5 | // Created by Pavel Puzyrev on 09.09.2020. 6 | // 7 | // Copyright (c) 2020 Pavel Puzyrev 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | 27 | #import 28 | 29 | //! Project version number for Blurberry. 30 | FOUNDATION_EXPORT double BlurberryVersionNumber; 31 | 32 | //! Project version string for Blurberry. 33 | FOUNDATION_EXPORT const unsigned char BlurberryVersionString[]; 34 | 35 | // In this header, you should import all the public headers of your framework using statements like #import 36 | 37 | #import 38 | -------------------------------------------------------------------------------- /Sources/Extensions/NSObject+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Extension.h 3 | // Blurberry 4 | // 5 | // Created by Pavel Puzyrev on 07.09.2020. 6 | // 7 | // Copyright (c) 2020 Pavel Puzyrev 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | 27 | #import 28 | 29 | @class UIColor; 30 | 31 | NS_ASSUME_NONNULL_BEGIN 32 | 33 | @interface NSObject (Extension) 34 | 35 | #pragma mark *** Values getting *** 36 | 37 | - (nullable NSArray *)arrayValueByGetterNamed:(NSString *)getterName NS_SWIFT_NAME(arrayValue(getter:)); 38 | - (nullable NSDictionary *)dictionaryValueByGetterNamed:(NSString *)getterName NS_SWIFT_NAME(dictionaryValue(getter:)); 39 | - (nullable NSString *)stringValueByGetterNamed:(NSString *)getterName NS_SWIFT_NAME(stringValue(getter:)); 40 | - (nullable UIColor *)colorValueByGetterNamed:(NSString *)getterName NS_SWIFT_NAME(colorValue(getter:)); 41 | 42 | #pragma mark *** Values setting *** 43 | 44 | - (void)setIVarValue:(nullable id)value getterNamed:(NSString *)getterName NS_SWIFT_NAME(setIVarValue(value:getter:)); 45 | - (void)setValueUsingSetter:(nullable id)value getterNamed:(NSString *)getterName NS_SWIFT_NAME(setValueUsingSetter(value:getter:)); 46 | - (void)setObjectInDictionary:(id)object 47 | forKey:(NSString *)key 48 | getterNamed:(NSString *)getterName NS_SWIFT_NAME(setObjectInDictionary(object:key:getter:)); 49 | 50 | - (nullable id)valueSafeForKey:(NSString *)key NS_SWIFT_NAME(valueSafe(key:)); 51 | - (void)setValueSafe:(id)value forKey:(NSString *)key NS_SWIFT_NAME(setValueSafe(value:key:)); 52 | 53 | #pragma mark *** Methods calling *** 54 | 55 | - (void)callMethodNamed:(NSString *)methodName NS_SWIFT_NAME(callMethod(named:)); 56 | - (void)callMethodNamed:(NSString *)methodName withObject:(nullable id)argument NS_SWIFT_NAME(callMethod(named:with:)); 57 | 58 | @end 59 | 60 | NS_ASSUME_NONNULL_END 61 | -------------------------------------------------------------------------------- /Sources/Extensions/NSObject+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Extension.m 3 | // Blurberry 4 | // 5 | // Created by Pavel Puzyrev on 07.09.2020. 6 | // 7 | // Copyright (c) 2020 Pavel Puzyrev 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | 27 | #import "NSObject+Extension.h" 28 | #import 29 | #import 30 | 31 | NS_ASSUME_NONNULL_BEGIN 32 | 33 | @implementation NSObject (Extension) 34 | 35 | #pragma mark - Public Methods 36 | 37 | #pragma mark *** Values getting *** 38 | 39 | - (nullable NSArray *)arrayValueByGetterNamed:(NSString *)getterName { 40 | return [self valueOfType:[NSArray class] getterNamed:getterName]; 41 | } 42 | 43 | - (nullable NSDictionary *)dictionaryValueByGetterNamed:(NSString *)getterName { 44 | return [self valueOfType:[NSDictionary class] getterNamed:getterName]; 45 | } 46 | 47 | - (nullable NSString *)stringValueByGetterNamed:(NSString *)getterName { 48 | return [self valueOfType:[NSString class] getterNamed:getterName]; 49 | } 50 | 51 | - (nullable UIColor *)colorValueByGetterNamed:(NSString *)getterName { 52 | return [self valueOfType:[UIColor class] getterNamed:getterName]; 53 | } 54 | 55 | #pragma mark *** Values setting *** 56 | 57 | - (void)setIVarValue:(nullable id)value getterNamed:(NSString *)getterName { 58 | @try { 59 | SEL getterSelector = NSSelectorFromString(getterName); 60 | SEL setterSelector = NSSelectorFromString([self setterMethodName:getterName]); 61 | NSString *ivarName = [NSString stringWithFormat:@"_%@", getterName]; 62 | if ([self respondsToSelector:getterSelector] && [self respondsToSelector:setterSelector]) { 63 | [self setValue:value forKey:ivarName]; 64 | } 65 | } @catch (NSException *exception) { 66 | 67 | } 68 | } 69 | 70 | - (void)setValueUsingSetter:(nullable id)value getterNamed:(NSString *)getterName { 71 | [self callMethodNamed:[self setterMethodName:getterName] withObject:value]; 72 | } 73 | 74 | - (void)setObjectInDictionary:(id)object forKey:(NSString *)key getterNamed:(NSString *)getterName { 75 | NSMutableDictionary *dictionary = [[self dictionaryValueByGetterNamed:getterName] mutableCopy]; 76 | if (!dictionary) { 77 | return; 78 | } 79 | 80 | dictionary[key] = object; 81 | 82 | [self callMethodNamed:[self setterMethodName:getterName] withObject:[dictionary copy]]; 83 | } 84 | 85 | - (nullable id)valueSafeForKey:(NSString *)key { 86 | @try { 87 | return [self valueForKey:key]; 88 | } @catch (NSException *exception) { 89 | return nil; 90 | } 91 | } 92 | 93 | - (void)setValueSafe:(id)value forKey:(NSString *)key { 94 | @try { 95 | [self setValue:value forKey:key]; 96 | } @catch (NSException *exception) { 97 | 98 | } 99 | } 100 | 101 | #pragma mark *** Methods calling *** 102 | 103 | - (void)callMethodNamed:(NSString *)methodName { 104 | [self callMethodNamed:methodName withObject:nil]; 105 | } 106 | 107 | - (void)callMethodNamed:(NSString *)methodName withObject:(nullable id)argument { 108 | @try { 109 | SEL selector = NSSelectorFromString(methodName); 110 | if ([self respondsToSelector:selector]) { 111 | _Pragma("clang diagnostic push") 112 | _Pragma("clang diagnostic ignored \"-Warc-performSelector-leaks\"") 113 | if (argument) { 114 | [self performSelector:selector withObject:argument]; 115 | } else { 116 | [self performSelector:selector]; 117 | } 118 | _Pragma("clang diagnostic pop") 119 | } 120 | } @catch (NSException *exception) { 121 | 122 | } 123 | } 124 | 125 | 126 | #pragma mark - Private Methods 127 | 128 | - (nullable id)valueOfType:(Class)type getterNamed:(NSString *)getterName { 129 | id typedValue; 130 | @try { 131 | SEL selector = NSSelectorFromString(getterName); 132 | if ([self respondsToSelector:selector]) { 133 | _Pragma("clang diagnostic push") 134 | _Pragma("clang diagnostic ignored \"-Warc-performSelector-leaks\"") 135 | id value = [self performSelector:selector]; 136 | if ([value isKindOfClass:type]) { 137 | typedValue = value; 138 | }_Pragma("clang diagnostic pop") 139 | } 140 | } @catch (NSException *exception) { 141 | 142 | } @finally { 143 | return typedValue; 144 | } 145 | } 146 | 147 | - (NSString *)setterMethodName:(NSString *)getterMethodName { 148 | NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en-US"]; 149 | NSString *firstChar = [getterMethodName substringToIndex:1]; 150 | NSString *folded = [firstChar stringByFoldingWithOptions:NSDiacriticInsensitiveSearch locale:locale]; 151 | NSString *pascalCasedResult = [folded.uppercaseString stringByAppendingString:[getterMethodName substringFromIndex:1]]; 152 | 153 | return [NSString stringWithFormat:@"set%@:", pascalCasedResult]; 154 | } 155 | 156 | @end 157 | 158 | NS_ASSUME_NONNULL_END 159 | -------------------------------------------------------------------------------- /Sources/General/Blurberry.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Blurberry.swift 3 | // Blurberry 4 | // 5 | // Created by Pavel Puzyrev on 09.09.2020. 6 | // 7 | // Copyright (c) 2020 Pavel Puzyrev 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | 27 | import UIKit 28 | 29 | public struct BlurWrapper { 30 | 31 | public let base: Base 32 | 33 | public init(_ base: Base) { 34 | self.base = base 35 | } 36 | } 37 | 38 | public protocol BlurCompatible: AnyObject { } 39 | 40 | public extension BlurCompatible { 41 | 42 | var blur: BlurWrapper { 43 | get { 44 | BlurWrapper(self) 45 | } 46 | set { } 47 | } 48 | } 49 | 50 | extension UIVisualEffectView: BlurCompatible { } 51 | -------------------------------------------------------------------------------- /Sources/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 | $(MARKETING_VERSION) 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | 22 | 23 | -------------------------------------------------------------------------------- /Sources/Views/VisualEffectView+Internal.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VisualEffectView+Internal.swift 3 | // Blurberry 4 | // 5 | // Created by Pavel Puzyrev on 07.09.2020. 6 | // 7 | // Copyright (c) 2020 Pavel Puzyrev 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | 27 | import UIKit 28 | 29 | internal extension BlurWrapper where Base: UIVisualEffectView { 30 | 31 | // MARK: iOS 13, 14 32 | 33 | var backdropView: UIView? { 34 | base.subviews.first { 35 | type(of: $0) == NSClassFromString("_UIVisualEffectBackdropView") 36 | } 37 | } 38 | 39 | var overlayView: UIView? { 40 | base.subviews.first { 41 | type(of: $0) == NSClassFromString("_UIVisualEffectSubview") 42 | } 43 | } 44 | 45 | var gaussianBlurFilter: NSObject? { 46 | backdropView?.arrayValue(getter: "filters")?.first { 47 | $0.stringValue(getter: "filterType") == "gaussianBlur" 48 | } 49 | } 50 | 51 | var sourceOverEffect: NSObject? { 52 | overlayView?.arrayValue(getter: "viewEffects")?.first { 53 | $0.stringValue(getter: "filterType") == "sourceOver" 54 | } 55 | } 56 | 57 | // MARK: iOS 10, 11, 12 58 | 59 | var blurEffect: NSObject? { 60 | guard let effect = base.effect, type(of: effect) == NSClassFromString("_UICustomBlurEffect") else { 61 | return nil 62 | } 63 | return base.effect 64 | } 65 | 66 | func updateBlurEffect(blurRadius: CGFloat, tintColor: UIColor?) { 67 | let effect = (NSClassFromString("_UICustomBlurEffect") as? UIBlurEffect.Type)?.init() 68 | effect?.setValueSafe(value: blurRadius, key: "blurRadius") 69 | effect?.setValueSafe(value: tintColor ?? UIColor(white: 1.0, alpha: 0.3), key: "colorTint") 70 | effect?.setValueSafe(value: 1.0, key: "scale") 71 | effect?.setValueSafe(value: 1.0, key: "colorTintAlpha") 72 | base.effect = effect 73 | } 74 | 75 | // MARK: Changes 76 | 77 | func prepareForChanges() { 78 | if #available(iOS 13, *) { 79 | base.effect = UIBlurEffect(style: .light) 80 | gaussianBlurFilter?.setIVarValue(value: 1.0, getter: "requestedScaleHint") 81 | } 82 | } 83 | 84 | func applyChanges() { 85 | if #available(iOS 13, *) { 86 | backdropView?.callMethod(named: "applyRequestedFilterEffects") 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Sources/Views/VisualEffectView+Public.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VisualEffectView+Public.swift 3 | // Blurberry 4 | // 5 | // Created by Pavel Puzyrev on 09.09.2020. 6 | // 7 | // Copyright (c) 2020 Pavel Puzyrev 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | 27 | import UIKit 28 | 29 | public extension BlurWrapper where Base: UIVisualEffectView { 30 | 31 | var radius: CGFloat { 32 | get { 33 | if #available(iOS 13, *) { 34 | return gaussianBlurFilter?.dictionaryValue(getter: "requestedValues")?["inputRadius"] as? CGFloat ?? 0.0 35 | } else { 36 | return blurEffect?.valueSafe(key: "blurRadius") as? CGFloat ?? 0.0 37 | } 38 | } 39 | set { 40 | prepareForChanges() 41 | 42 | if #available(iOS 13, *) { 43 | gaussianBlurFilter?.setObjectInDictionary(object: newValue, key: "inputRadius", getter: "requestedValues") 44 | } else { 45 | updateBlurEffect(blurRadius: newValue, tintColor: tintColor) 46 | } 47 | 48 | applyChanges() 49 | } 50 | } 51 | 52 | var tintColor: UIColor? { 53 | get { 54 | if #available(iOS 13, *) { 55 | return sourceOverEffect?.colorValue(getter: "color") 56 | } else { 57 | return blurEffect?.colorValue(getter: "colorTint") 58 | } 59 | } 60 | set { 61 | prepareForChanges() 62 | 63 | if #available(iOS 13, *) { 64 | sourceOverEffect?.setValueUsingSetter(value: newValue, getter: "color") 65 | sourceOverEffect?.callMethod(named: "applyRequestedEffectToView:", with: overlayView) 66 | } else { 67 | updateBlurEffect(blurRadius: radius, tintColor: newValue) 68 | } 69 | 70 | applyChanges() 71 | } 72 | } 73 | } 74 | --------------------------------------------------------------------------------