├── .gitignore ├── Example ├── VariableBlurViewExample.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── VariableBlurViewExample │ ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ ├── Image.imageset │ │ ├── Contents.json │ │ └── Gradient.png │ └── Sky.imageset │ │ ├── Contents.json │ │ └── marek-piwnicki-py3GLPFvmpg-unsplash (1).jpg │ ├── ContentView.swift │ └── VariableBlurViewExampleApp.swift ├── LICENSE ├── Package.swift ├── README.md └── Sources └── VariableBlurView.swift /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/config/registries.json 8 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 9 | .netrc 10 | .swiftpm 11 | -------------------------------------------------------------------------------- /Example/VariableBlurViewExample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 56; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 3C3BADF82A25D8BD00DF4748 /* VariableBlurView in Frameworks */ = {isa = PBXBuildFile; productRef = 3C3BADF72A25D8BD00DF4748 /* VariableBlurView */; }; 11 | 3CC0DE6E2A25D87800FAFF19 /* VariableBlurViewExampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CC0DE6D2A25D87800FAFF19 /* VariableBlurViewExampleApp.swift */; }; 12 | 3CC0DE702A25D87800FAFF19 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CC0DE6F2A25D87800FAFF19 /* ContentView.swift */; }; 13 | 3CC0DE722A25D87A00FAFF19 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3CC0DE712A25D87A00FAFF19 /* Assets.xcassets */; }; 14 | /* End PBXBuildFile section */ 15 | 16 | /* Begin PBXFileReference section */ 17 | 3C39B7802A25D8EB0013E6F6 /* VariableBlurView */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = VariableBlurView; path = ..; sourceTree = ""; }; 18 | 3CC0DE6A2A25D87800FAFF19 /* VariableBlurViewExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = VariableBlurViewExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 19 | 3CC0DE6D2A25D87800FAFF19 /* VariableBlurViewExampleApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VariableBlurViewExampleApp.swift; sourceTree = ""; }; 20 | 3CC0DE6F2A25D87800FAFF19 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 21 | 3CC0DE712A25D87A00FAFF19 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 22 | /* End PBXFileReference section */ 23 | 24 | /* Begin PBXFrameworksBuildPhase section */ 25 | 3CC0DE672A25D87800FAFF19 /* Frameworks */ = { 26 | isa = PBXFrameworksBuildPhase; 27 | buildActionMask = 2147483647; 28 | files = ( 29 | 3C3BADF82A25D8BD00DF4748 /* VariableBlurView in Frameworks */, 30 | ); 31 | runOnlyForDeploymentPostprocessing = 0; 32 | }; 33 | /* End PBXFrameworksBuildPhase section */ 34 | 35 | /* Begin PBXGroup section */ 36 | 3CC0DE612A25D87800FAFF19 = { 37 | isa = PBXGroup; 38 | children = ( 39 | 3C39B7802A25D8EB0013E6F6 /* VariableBlurView */, 40 | 3CC0DE6C2A25D87800FAFF19 /* VariableBlurViewExample */, 41 | 3CC0DE6B2A25D87800FAFF19 /* Products */, 42 | ); 43 | sourceTree = ""; 44 | }; 45 | 3CC0DE6B2A25D87800FAFF19 /* Products */ = { 46 | isa = PBXGroup; 47 | children = ( 48 | 3CC0DE6A2A25D87800FAFF19 /* VariableBlurViewExample.app */, 49 | ); 50 | name = Products; 51 | sourceTree = ""; 52 | }; 53 | 3CC0DE6C2A25D87800FAFF19 /* VariableBlurViewExample */ = { 54 | isa = PBXGroup; 55 | children = ( 56 | 3CC0DE6D2A25D87800FAFF19 /* VariableBlurViewExampleApp.swift */, 57 | 3CC0DE6F2A25D87800FAFF19 /* ContentView.swift */, 58 | 3CC0DE712A25D87A00FAFF19 /* Assets.xcassets */, 59 | ); 60 | path = VariableBlurViewExample; 61 | sourceTree = ""; 62 | }; 63 | /* End PBXGroup section */ 64 | 65 | /* Begin PBXNativeTarget section */ 66 | 3CC0DE692A25D87800FAFF19 /* VariableBlurViewExample */ = { 67 | isa = PBXNativeTarget; 68 | buildConfigurationList = 3CC0DE782A25D87A00FAFF19 /* Build configuration list for PBXNativeTarget "VariableBlurViewExample" */; 69 | buildPhases = ( 70 | 3CC0DE662A25D87800FAFF19 /* Sources */, 71 | 3CC0DE672A25D87800FAFF19 /* Frameworks */, 72 | 3CC0DE682A25D87800FAFF19 /* Resources */, 73 | ); 74 | buildRules = ( 75 | ); 76 | dependencies = ( 77 | ); 78 | name = VariableBlurViewExample; 79 | packageProductDependencies = ( 80 | 3C3BADF72A25D8BD00DF4748 /* VariableBlurView */, 81 | ); 82 | productName = VariableBlurViewExample; 83 | productReference = 3CC0DE6A2A25D87800FAFF19 /* VariableBlurViewExample.app */; 84 | productType = "com.apple.product-type.application"; 85 | }; 86 | /* End PBXNativeTarget section */ 87 | 88 | /* Begin PBXProject section */ 89 | 3CC0DE622A25D87800FAFF19 /* Project object */ = { 90 | isa = PBXProject; 91 | attributes = { 92 | BuildIndependentTargetsInParallel = 1; 93 | LastSwiftUpdateCheck = 1430; 94 | LastUpgradeCheck = 1430; 95 | TargetAttributes = { 96 | 3CC0DE692A25D87800FAFF19 = { 97 | CreatedOnToolsVersion = 14.3; 98 | }; 99 | }; 100 | }; 101 | buildConfigurationList = 3CC0DE652A25D87800FAFF19 /* Build configuration list for PBXProject "VariableBlurViewExample" */; 102 | compatibilityVersion = "Xcode 14.0"; 103 | developmentRegion = en; 104 | hasScannedForEncodings = 0; 105 | knownRegions = ( 106 | en, 107 | Base, 108 | ); 109 | mainGroup = 3CC0DE612A25D87800FAFF19; 110 | packageReferences = ( 111 | 3C3BADF62A25D8BC00DF4748 /* XCRemoteSwiftPackageReference "VariableBlurView" */, 112 | ); 113 | productRefGroup = 3CC0DE6B2A25D87800FAFF19 /* Products */; 114 | projectDirPath = ""; 115 | projectRoot = ""; 116 | targets = ( 117 | 3CC0DE692A25D87800FAFF19 /* VariableBlurViewExample */, 118 | ); 119 | }; 120 | /* End PBXProject section */ 121 | 122 | /* Begin PBXResourcesBuildPhase section */ 123 | 3CC0DE682A25D87800FAFF19 /* Resources */ = { 124 | isa = PBXResourcesBuildPhase; 125 | buildActionMask = 2147483647; 126 | files = ( 127 | 3CC0DE722A25D87A00FAFF19 /* Assets.xcassets in Resources */, 128 | ); 129 | runOnlyForDeploymentPostprocessing = 0; 130 | }; 131 | /* End PBXResourcesBuildPhase section */ 132 | 133 | /* Begin PBXSourcesBuildPhase section */ 134 | 3CC0DE662A25D87800FAFF19 /* Sources */ = { 135 | isa = PBXSourcesBuildPhase; 136 | buildActionMask = 2147483647; 137 | files = ( 138 | 3CC0DE702A25D87800FAFF19 /* ContentView.swift in Sources */, 139 | 3CC0DE6E2A25D87800FAFF19 /* VariableBlurViewExampleApp.swift in Sources */, 140 | ); 141 | runOnlyForDeploymentPostprocessing = 0; 142 | }; 143 | /* End PBXSourcesBuildPhase section */ 144 | 145 | /* Begin XCBuildConfiguration section */ 146 | 3CC0DE762A25D87A00FAFF19 /* Debug */ = { 147 | isa = XCBuildConfiguration; 148 | buildSettings = { 149 | ALWAYS_SEARCH_USER_PATHS = NO; 150 | CLANG_ANALYZER_NONNULL = YES; 151 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 152 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 153 | CLANG_ENABLE_MODULES = YES; 154 | CLANG_ENABLE_OBJC_ARC = YES; 155 | CLANG_ENABLE_OBJC_WEAK = YES; 156 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 157 | CLANG_WARN_BOOL_CONVERSION = YES; 158 | CLANG_WARN_COMMA = YES; 159 | CLANG_WARN_CONSTANT_CONVERSION = YES; 160 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 161 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 162 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 163 | CLANG_WARN_EMPTY_BODY = YES; 164 | CLANG_WARN_ENUM_CONVERSION = YES; 165 | CLANG_WARN_INFINITE_RECURSION = YES; 166 | CLANG_WARN_INT_CONVERSION = YES; 167 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 168 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 169 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 170 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 171 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 172 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 173 | CLANG_WARN_STRICT_PROTOTYPES = YES; 174 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 175 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 176 | CLANG_WARN_UNREACHABLE_CODE = YES; 177 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 178 | COPY_PHASE_STRIP = NO; 179 | DEBUG_INFORMATION_FORMAT = dwarf; 180 | ENABLE_STRICT_OBJC_MSGSEND = YES; 181 | ENABLE_TESTABILITY = YES; 182 | GCC_C_LANGUAGE_STANDARD = gnu11; 183 | GCC_DYNAMIC_NO_PIC = NO; 184 | GCC_NO_COMMON_BLOCKS = YES; 185 | GCC_OPTIMIZATION_LEVEL = 0; 186 | GCC_PREPROCESSOR_DEFINITIONS = ( 187 | "DEBUG=1", 188 | "$(inherited)", 189 | ); 190 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 191 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 192 | GCC_WARN_UNDECLARED_SELECTOR = YES; 193 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 194 | GCC_WARN_UNUSED_FUNCTION = YES; 195 | GCC_WARN_UNUSED_VARIABLE = YES; 196 | IPHONEOS_DEPLOYMENT_TARGET = 16.4; 197 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 198 | MTL_FAST_MATH = YES; 199 | ONLY_ACTIVE_ARCH = YES; 200 | SDKROOT = iphoneos; 201 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 202 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 203 | }; 204 | name = Debug; 205 | }; 206 | 3CC0DE772A25D87A00FAFF19 /* Release */ = { 207 | isa = XCBuildConfiguration; 208 | buildSettings = { 209 | ALWAYS_SEARCH_USER_PATHS = NO; 210 | CLANG_ANALYZER_NONNULL = YES; 211 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 212 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 213 | CLANG_ENABLE_MODULES = YES; 214 | CLANG_ENABLE_OBJC_ARC = YES; 215 | CLANG_ENABLE_OBJC_WEAK = YES; 216 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 217 | CLANG_WARN_BOOL_CONVERSION = YES; 218 | CLANG_WARN_COMMA = YES; 219 | CLANG_WARN_CONSTANT_CONVERSION = YES; 220 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 221 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 222 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 223 | CLANG_WARN_EMPTY_BODY = YES; 224 | CLANG_WARN_ENUM_CONVERSION = YES; 225 | CLANG_WARN_INFINITE_RECURSION = YES; 226 | CLANG_WARN_INT_CONVERSION = YES; 227 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 228 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 229 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 230 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 231 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 232 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 233 | CLANG_WARN_STRICT_PROTOTYPES = YES; 234 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 235 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 236 | CLANG_WARN_UNREACHABLE_CODE = YES; 237 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 238 | COPY_PHASE_STRIP = NO; 239 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 240 | ENABLE_NS_ASSERTIONS = NO; 241 | ENABLE_STRICT_OBJC_MSGSEND = YES; 242 | GCC_C_LANGUAGE_STANDARD = gnu11; 243 | GCC_NO_COMMON_BLOCKS = YES; 244 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 245 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 246 | GCC_WARN_UNDECLARED_SELECTOR = YES; 247 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 248 | GCC_WARN_UNUSED_FUNCTION = YES; 249 | GCC_WARN_UNUSED_VARIABLE = YES; 250 | IPHONEOS_DEPLOYMENT_TARGET = 16.4; 251 | MTL_ENABLE_DEBUG_INFO = NO; 252 | MTL_FAST_MATH = YES; 253 | SDKROOT = iphoneos; 254 | SWIFT_COMPILATION_MODE = wholemodule; 255 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 256 | VALIDATE_PRODUCT = YES; 257 | }; 258 | name = Release; 259 | }; 260 | 3CC0DE792A25D87A00FAFF19 /* Debug */ = { 261 | isa = XCBuildConfiguration; 262 | buildSettings = { 263 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 264 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 265 | CODE_SIGN_STYLE = Automatic; 266 | CURRENT_PROJECT_VERSION = 1; 267 | DEVELOPMENT_TEAM = WV6XDLHK3W; 268 | ENABLE_PREVIEWS = YES; 269 | GENERATE_INFOPLIST_FILE = YES; 270 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 271 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 272 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 273 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 274 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 275 | LD_RUNPATH_SEARCH_PATHS = ( 276 | "$(inherited)", 277 | "@executable_path/Frameworks", 278 | ); 279 | MARKETING_VERSION = 1.0; 280 | PRODUCT_BUNDLE_IDENTIFIER = day.midnight.VariableBlurViewExample; 281 | PRODUCT_NAME = "$(TARGET_NAME)"; 282 | SWIFT_EMIT_LOC_STRINGS = YES; 283 | SWIFT_VERSION = 5.0; 284 | TARGETED_DEVICE_FAMILY = "1,2"; 285 | }; 286 | name = Debug; 287 | }; 288 | 3CC0DE7A2A25D87A00FAFF19 /* Release */ = { 289 | isa = XCBuildConfiguration; 290 | buildSettings = { 291 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 292 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 293 | CODE_SIGN_STYLE = Automatic; 294 | CURRENT_PROJECT_VERSION = 1; 295 | DEVELOPMENT_TEAM = WV6XDLHK3W; 296 | ENABLE_PREVIEWS = YES; 297 | GENERATE_INFOPLIST_FILE = YES; 298 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 299 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 300 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 301 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 302 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 303 | LD_RUNPATH_SEARCH_PATHS = ( 304 | "$(inherited)", 305 | "@executable_path/Frameworks", 306 | ); 307 | MARKETING_VERSION = 1.0; 308 | PRODUCT_BUNDLE_IDENTIFIER = day.midnight.VariableBlurViewExample; 309 | PRODUCT_NAME = "$(TARGET_NAME)"; 310 | SWIFT_EMIT_LOC_STRINGS = YES; 311 | SWIFT_VERSION = 5.0; 312 | TARGETED_DEVICE_FAMILY = "1,2"; 313 | }; 314 | name = Release; 315 | }; 316 | /* End XCBuildConfiguration section */ 317 | 318 | /* Begin XCConfigurationList section */ 319 | 3CC0DE652A25D87800FAFF19 /* Build configuration list for PBXProject "VariableBlurViewExample" */ = { 320 | isa = XCConfigurationList; 321 | buildConfigurations = ( 322 | 3CC0DE762A25D87A00FAFF19 /* Debug */, 323 | 3CC0DE772A25D87A00FAFF19 /* Release */, 324 | ); 325 | defaultConfigurationIsVisible = 0; 326 | defaultConfigurationName = Release; 327 | }; 328 | 3CC0DE782A25D87A00FAFF19 /* Build configuration list for PBXNativeTarget "VariableBlurViewExample" */ = { 329 | isa = XCConfigurationList; 330 | buildConfigurations = ( 331 | 3CC0DE792A25D87A00FAFF19 /* Debug */, 332 | 3CC0DE7A2A25D87A00FAFF19 /* Release */, 333 | ); 334 | defaultConfigurationIsVisible = 0; 335 | defaultConfigurationName = Release; 336 | }; 337 | /* End XCConfigurationList section */ 338 | 339 | /* Begin XCRemoteSwiftPackageReference section */ 340 | 3C3BADF62A25D8BC00DF4748 /* XCRemoteSwiftPackageReference "VariableBlurView" */ = { 341 | isa = XCRemoteSwiftPackageReference; 342 | repositoryURL = "https://github.com/aheze/VariableBlurView"; 343 | requirement = { 344 | kind = upToNextMajorVersion; 345 | minimumVersion = 0.0.1; 346 | }; 347 | }; 348 | /* End XCRemoteSwiftPackageReference section */ 349 | 350 | /* Begin XCSwiftPackageProductDependency section */ 351 | 3C3BADF72A25D8BD00DF4748 /* VariableBlurView */ = { 352 | isa = XCSwiftPackageProductDependency; 353 | package = 3C3BADF62A25D8BC00DF4748 /* XCRemoteSwiftPackageReference "VariableBlurView" */; 354 | productName = VariableBlurView; 355 | }; 356 | /* End XCSwiftPackageProductDependency section */ 357 | }; 358 | rootObject = 3CC0DE622A25D87800FAFF19 /* Project object */; 359 | } 360 | -------------------------------------------------------------------------------- /Example/VariableBlurViewExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/VariableBlurViewExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/VariableBlurViewExample/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Example/VariableBlurViewExample/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Example/VariableBlurViewExample/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Example/VariableBlurViewExample/Assets.xcassets/Image.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Gradient.png", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Example/VariableBlurViewExample/Assets.xcassets/Image.imageset/Gradient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheze/VariableBlurView/aac95d7a528b8aa37bf2228d0e2d13fa0ed11f9d/Example/VariableBlurViewExample/Assets.xcassets/Image.imageset/Gradient.png -------------------------------------------------------------------------------- /Example/VariableBlurViewExample/Assets.xcassets/Sky.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "marek-piwnicki-py3GLPFvmpg-unsplash (1).jpg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Example/VariableBlurViewExample/Assets.xcassets/Sky.imageset/marek-piwnicki-py3GLPFvmpg-unsplash (1).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheze/VariableBlurView/aac95d7a528b8aa37bf2228d0e2d13fa0ed11f9d/Example/VariableBlurViewExample/Assets.xcassets/Sky.imageset/marek-piwnicki-py3GLPFvmpg-unsplash (1).jpg -------------------------------------------------------------------------------- /Example/VariableBlurViewExample/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // VariableBlurViewExample 4 | // 5 | // Created by A. Zheng (github.com/aheze) on 5/30/23. 6 | // Copyright © 2023 A. Zheng. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import VariableBlurView 11 | 12 | struct ContentView: View { 13 | var body: some View { 14 | ZStack { 15 | ScrollView(.vertical) { 16 | VStack { 17 | Image("Sky") 18 | .resizable() 19 | .aspectRatio(contentMode: .fit) 20 | .clipShape(RoundedRectangle(cornerRadius: 6, style: .continuous)) 21 | .padding() 22 | } 23 | .padding(.top, 50) 24 | } 25 | 26 | VStack { 27 | VariableBlurView() 28 | .frame(height: 200) 29 | .allowsHitTesting(false) 30 | 31 | Spacer() 32 | } 33 | } 34 | .ignoresSafeArea(.all) 35 | } 36 | } 37 | 38 | struct ContentView_Previews: PreviewProvider { 39 | static var previews: some View { 40 | ContentView() 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Example/VariableBlurViewExample/VariableBlurViewExampleApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VariableBlurViewExampleApp.swift 3 | // VariableBlurViewExample 4 | // 5 | // Created by A. Zheng (github.com/aheze) on 5/30/23. 6 | // Copyright © 2023 A. Zheng. All rights reserved. 7 | // 8 | 9 | 10 | import SwiftUI 11 | 12 | @main 13 | struct VariableBlurViewExampleApp: App { 14 | var body: some Scene { 15 | WindowGroup { 16 | ContentView() 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 A. Zheng 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.8 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "VariableBlurView", 8 | platforms: [ 9 | .iOS(.v13), .macOS(.v11) 10 | ], 11 | products: [ 12 | // Products define the executables and libraries a package produces, and make them visible to other packages. 13 | .library( 14 | name: "VariableBlurView", 15 | targets: ["VariableBlurView"] 16 | ), 17 | ], 18 | dependencies: [ 19 | // Dependencies declare other packages that this package depends on. 20 | // .package(url: /* package url */, from: "1.0.0"), 21 | ], 22 | targets: [ 23 | // Targets are the basic building blocks of a package. A target can define a module or a test suite. 24 | // Targets can depend on other targets in this package, and on products in packages this package depends on. 25 | .target( 26 | name: "VariableBlurView", 27 | dependencies: [], 28 | path: "Sources" 29 | ) 30 | ] 31 | ) 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VariableBlurView 2 | 3 | A one-file, App Store upload-safe version of Janum Trivedi's variable blur effect. 4 | 5 | (use at your own risk - Apple can still reject it). 6 | 7 | Original author: [@jtrivedi](https://github.com/jtrivedi) 8 | 9 | Original repository: https://github.com/jtrivedi/VariableBlurView 10 | 11 | React Native port: https://github.com/candlefinance/blur-view 12 | 13 | https://github.com/aheze/VariableBlurView/assets/49819455/4400f76d-7d85-4e3f-9757-19bc99297524 14 | 15 | ### Installation 16 | 17 | Just drag [`VariableBlurView.swift`](https://github.com/aheze/VariableBlurView/blob/main/Sources/VariableBlurView.swift) into your project. Or, add the package URL: 18 | 19 | ``` 20 | https://github.com/aheze/VariableBlurView 21 | ``` 22 | 23 | ### How is it App Store upload-safe? 24 | 25 | Well it still uses the `CAFilter` private API, but I obfuscated it as a base64 string. I've used this method in [Midnight](https://midnight.day) and it worked just fine. 26 | 27 | Also, this version gets past App Review — Janum's original version included a objc briding header, which gets auto-rejected. This version uses a bunch of runtime objc selectors instead. 28 | 29 | However, it's still possible that Apple detects this, so use at your own risk. 30 | 31 | ### License 32 | 33 | Original license [here](https://github.com/jtrivedi/VariableBlurView/blob/main/LICENSE.md). 34 | 35 | ``` 36 | MIT License 37 | 38 | Copyright (c) 2023 A. Zheng 39 | 40 | Permission is hereby granted, free of charge, to any person obtaining a copy 41 | of this software and associated documentation files (the "Software"), to deal 42 | in the Software without restriction, including without limitation the rights 43 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 44 | copies of the Software, and to permit persons to whom the Software is 45 | furnished to do so, subject to the following conditions: 46 | 47 | The above copyright notice and this permission notice shall be included in all 48 | copies or substantial portions of the Software. 49 | 50 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 51 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 52 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 53 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 54 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 55 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 56 | SOFTWARE. 57 | ``` 58 | -------------------------------------------------------------------------------- /Sources/VariableBlurView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VariableBlurView.swift 3 | // VariableBlurView 4 | // 5 | // Created by A. Zheng (github.com/aheze) on 5/29/23. 6 | // Copyright © 2023 A. Zheng. All rights reserved. 7 | // 8 | // --- 9 | // 10 | // MIT License 11 | // 12 | // Copyright (c) 2023 A. Zheng 13 | // 14 | // Permission is hereby granted, free of charge, to any person obtaining a copy 15 | // of this software and associated documentation files (the "Software"), to deal 16 | // in the Software without restriction, including without limitation the rights 17 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | // copies of the Software, and to permit persons to whom the Software is 19 | // furnished to do so, subject to the following conditions: 20 | // 21 | // The above copyright notice and this permission notice shall be included in all 22 | // copies or substantial portions of the Software. 23 | // 24 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | // SOFTWARE. 31 | // 32 | // --- 33 | // 34 | // This work is based off VariableBlurView by Janum Trivedi. 35 | // Original repository: https://github.com/jtrivedi/VariableBlurView 36 | // Original license: 37 | // 38 | // Copyright (c) 2012-2023 Scott Chacon and others 39 | // 40 | // Permission is hereby granted, free of charge, to any person obtaining 41 | // a copy of this software and associated documentation files (the 42 | // "Software"), to deal in the Software without restriction, including 43 | // without limitation the rights to use, copy, modify, merge, publish, 44 | // distribute, sublicense, and/or sell copies of the Software, and to 45 | // permit persons to whom the Software is furnished to do so, subject to 46 | // the following conditions: 47 | // 48 | // The above copyright notice and this permission notice shall be 49 | // included in all copies or substantial portions of the Software. 50 | // 51 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 52 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 53 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 54 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 55 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 56 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 57 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 58 | 59 | import SwiftUI 60 | 61 | /// A variable blur view. 62 | public class VariableBlurUIView: UIVisualEffectView { 63 | public init( 64 | gradientMask: UIImage, 65 | maxBlurRadius: CGFloat = 20, 66 | filterType: String = "variableBlur" 67 | ) { 68 | super.init(effect: UIBlurEffect(style: .regular)) 69 | 70 | /// This is a private QuartzCore class, encoded in base64. 71 | /// 72 | /// CAFilter 73 | let filterClassStringEncoded = "Q0FGaWx0ZXI=" 74 | 75 | let filterClassString: String = { 76 | if 77 | let data = Data(base64Encoded: filterClassStringEncoded), 78 | let string = String(data: data, encoding: .utf8) 79 | { 80 | return string 81 | } 82 | 83 | print("[VariableBlurView] couldn't decode the filter class string.") 84 | return "" 85 | }() 86 | 87 | /// This is the magic class method that we want to invoke, encoded in base64. 88 | /// 89 | /// filterWithType: 90 | let filterWithTypeStringEncoded = "ZmlsdGVyV2l0aFR5cGU6" 91 | 92 | /// Decode the base64. 93 | let filterWithTypeString: String = { 94 | if 95 | let data = Data(base64Encoded: filterWithTypeStringEncoded), 96 | let string = String(data: data, encoding: .utf8) 97 | { 98 | return string 99 | } 100 | 101 | print("[VariableBlurView] couldn't decode the filter method string.") 102 | return "" 103 | }() 104 | 105 | /// Create the selector. 106 | let filterWithTypeSelector = Selector(filterWithTypeString) 107 | 108 | /// Create the class object. 109 | guard let filterClass = NSClassFromString(filterClassString) as AnyObject as? NSObjectProtocol else { 110 | print("[VariableBlurView] couldn't create CAFilter class.") 111 | return 112 | } 113 | 114 | /// Make sure the filter class responds to the selector. 115 | guard filterClass.responds(to: filterWithTypeSelector) else { 116 | print("[VariableBlurView] Doesn't respond to selector \(filterWithTypeSelector)") 117 | return 118 | } 119 | 120 | /// Create the blur effect. 121 | let variableBlur = filterClass 122 | .perform(filterWithTypeSelector, with: filterType) 123 | .takeUnretainedValue() 124 | 125 | guard let variableBlur = variableBlur as? NSObject else { 126 | print("[VariableBlurView] Couldn't cast the blur filter.") 127 | return 128 | } 129 | 130 | /// The blur radius at each pixel depends on the alpha value of the corresponding pixel in the gradient mask. 131 | /// An alpha of 1 results in the max blur radius, while an alpha of 0 is completely unblurred. 132 | guard let gradientImageRef = gradientMask.cgImage else { 133 | fatalError("Could not decode gradient image") 134 | } 135 | 136 | variableBlur.setValue(maxBlurRadius, forKey: "inputRadius") 137 | variableBlur.setValue(gradientImageRef, forKey: "inputMaskImage") 138 | variableBlur.setValue(true, forKey: "inputNormalizeEdges") 139 | 140 | /// Get rid of the visual effect view's dimming/tint view, so we don't see a hard line. 141 | if subviews.indices.contains(1) { 142 | let tintOverlayView = subviews[1] 143 | tintOverlayView.alpha = 0 144 | } 145 | 146 | /// We use a `UIVisualEffectView` here purely to get access to its `CABackdropLayer`, 147 | /// which is able to apply various, real-time CAFilters onto the views underneath. 148 | let backdropLayer = subviews.first?.layer 149 | 150 | /// Replace the standard filters (i.e. `gaussianBlur`, `colorSaturate`, etc.) with only the variableBlur. 151 | backdropLayer?.filters = [variableBlur] 152 | } 153 | 154 | @available(*, unavailable) 155 | required init?(coder: NSCoder) { 156 | fatalError("init(coder:) has not been implemented") 157 | } 158 | } 159 | 160 | /// A variable blur view. 161 | public struct VariableBlurView: UIViewRepresentable { 162 | public var gradientMask: UIImage 163 | public var maxBlurRadius: CGFloat 164 | public var filterType: String 165 | 166 | /// A variable blur view. 167 | public init( 168 | gradientMask: UIImage = VariableBlurViewConstants.defaultGradientMask, 169 | maxBlurRadius: CGFloat = 20, 170 | filterType: String = "variableBlur" 171 | ) { 172 | self.gradientMask = gradientMask 173 | self.maxBlurRadius = maxBlurRadius 174 | self.filterType = filterType 175 | } 176 | 177 | public func makeUIView(context: Context) -> VariableBlurUIView { 178 | let view = VariableBlurUIView( 179 | gradientMask: gradientMask, 180 | maxBlurRadius: maxBlurRadius, 181 | filterType: filterType 182 | ) 183 | return view 184 | } 185 | 186 | public func updateUIView(_ uiView: VariableBlurUIView, context: Context) {} 187 | } 188 | 189 | public enum VariableBlurViewConstants { 190 | 191 | /// A gradient mask image (top is opaque, bottom is clear). The gradient includes easing. 192 | public static var defaultGradientMask: UIImage = { 193 | if 194 | let data = Data(base64Encoded: defaultMaskImageString, options: .ignoreUnknownCharacters), 195 | let image = UIImage(data: data) 196 | { 197 | return image 198 | } else { 199 | print("[VariableBlurView] Couldn't create the gradient mask image.") 200 | return UIImage(systemName: "xmark")! 201 | } 202 | }() 203 | 204 | /// The image encoded in base64 (from PNG data). 205 | public static let defaultMaskImageString = """ 206 | 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 362 | """ 363 | } 364 | --------------------------------------------------------------------------------