├── CoreBlurView.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── CoreBlurView.xccheckout │ └── xcuserdata │ │ └── Charlin.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── Charlin.xcuserdatad │ └── xcschemes │ ├── CoreBlurView.xcscheme │ └── xcschememanagement.plist ├── CoreBlurView ├── 1.gif ├── 1@2x.png ├── AppDelegate.h ├── AppDelegate.m ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── CoreBlurView │ └── Lib │ │ ├── CoreBlurView.h │ │ ├── CoreBlurView.m │ │ └── FXBlurView │ │ ├── FXBlurView.h │ │ └── FXBlurView.m ├── Images.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── LaunchImage.launchimage │ │ └── Contents.json ├── Info.plist ├── ViewController.h ├── ViewController.m └── main.m ├── CoreBlurViewTests ├── CoreBlurViewTests.m └── Info.plist └── README.md /CoreBlurView.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 89B67C731B1406E9002D98B1 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 89B67C721B1406E9002D98B1 /* main.m */; }; 11 | 89B67C761B1406E9002D98B1 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 89B67C751B1406E9002D98B1 /* AppDelegate.m */; }; 12 | 89B67C791B1406E9002D98B1 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 89B67C781B1406E9002D98B1 /* ViewController.m */; }; 13 | 89B67C7C1B1406E9002D98B1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 89B67C7A1B1406E9002D98B1 /* Main.storyboard */; }; 14 | 89B67C7E1B1406E9002D98B1 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 89B67C7D1B1406E9002D98B1 /* Images.xcassets */; }; 15 | 89B67C811B1406E9002D98B1 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 89B67C7F1B1406E9002D98B1 /* LaunchScreen.xib */; }; 16 | 89B67C8D1B1406E9002D98B1 /* CoreBlurViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 89B67C8C1B1406E9002D98B1 /* CoreBlurViewTests.m */; }; 17 | 89B67C9B1B140711002D98B1 /* FXBlurView.m in Sources */ = {isa = PBXBuildFile; fileRef = 89B67C9A1B140711002D98B1 /* FXBlurView.m */; }; 18 | 89B67C9D1B140B53002D98B1 /* 1@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 89B67C9C1B140B53002D98B1 /* 1@2x.png */; }; 19 | 89B67CA01B14145A002D98B1 /* CoreBlurView.m in Sources */ = {isa = PBXBuildFile; fileRef = 89B67C9F1B14145A002D98B1 /* CoreBlurView.m */; }; 20 | 89B67CA21B141E6D002D98B1 /* 1.gif in Resources */ = {isa = PBXBuildFile; fileRef = 89B67CA11B141E6D002D98B1 /* 1.gif */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXContainerItemProxy section */ 24 | 89B67C871B1406E9002D98B1 /* PBXContainerItemProxy */ = { 25 | isa = PBXContainerItemProxy; 26 | containerPortal = 89B67C651B1406E9002D98B1 /* Project object */; 27 | proxyType = 1; 28 | remoteGlobalIDString = 89B67C6C1B1406E9002D98B1; 29 | remoteInfo = CoreBlurView; 30 | }; 31 | /* End PBXContainerItemProxy section */ 32 | 33 | /* Begin PBXFileReference section */ 34 | 89B67C6D1B1406E9002D98B1 /* CoreBlurView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CoreBlurView.app; sourceTree = BUILT_PRODUCTS_DIR; }; 35 | 89B67C711B1406E9002D98B1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 36 | 89B67C721B1406E9002D98B1 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 37 | 89B67C741B1406E9002D98B1 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 38 | 89B67C751B1406E9002D98B1 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 39 | 89B67C771B1406E9002D98B1 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 40 | 89B67C781B1406E9002D98B1 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 41 | 89B67C7B1B1406E9002D98B1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 42 | 89B67C7D1B1406E9002D98B1 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 43 | 89B67C801B1406E9002D98B1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 44 | 89B67C861B1406E9002D98B1 /* CoreBlurViewTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CoreBlurViewTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 45 | 89B67C8B1B1406E9002D98B1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 46 | 89B67C8C1B1406E9002D98B1 /* CoreBlurViewTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CoreBlurViewTests.m; sourceTree = ""; }; 47 | 89B67C991B140711002D98B1 /* FXBlurView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FXBlurView.h; sourceTree = ""; }; 48 | 89B67C9A1B140711002D98B1 /* FXBlurView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FXBlurView.m; sourceTree = ""; }; 49 | 89B67C9C1B140B53002D98B1 /* 1@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "1@2x.png"; sourceTree = ""; }; 50 | 89B67C9E1B14145A002D98B1 /* CoreBlurView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CoreBlurView.h; sourceTree = ""; }; 51 | 89B67C9F1B14145A002D98B1 /* CoreBlurView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CoreBlurView.m; sourceTree = ""; }; 52 | 89B67CA11B141E6D002D98B1 /* 1.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = 1.gif; sourceTree = ""; }; 53 | /* End PBXFileReference section */ 54 | 55 | /* Begin PBXFrameworksBuildPhase section */ 56 | 89B67C6A1B1406E9002D98B1 /* Frameworks */ = { 57 | isa = PBXFrameworksBuildPhase; 58 | buildActionMask = 2147483647; 59 | files = ( 60 | ); 61 | runOnlyForDeploymentPostprocessing = 0; 62 | }; 63 | 89B67C831B1406E9002D98B1 /* Frameworks */ = { 64 | isa = PBXFrameworksBuildPhase; 65 | buildActionMask = 2147483647; 66 | files = ( 67 | ); 68 | runOnlyForDeploymentPostprocessing = 0; 69 | }; 70 | /* End PBXFrameworksBuildPhase section */ 71 | 72 | /* Begin PBXGroup section */ 73 | 89B67C641B1406E9002D98B1 = { 74 | isa = PBXGroup; 75 | children = ( 76 | 89B67C6F1B1406E9002D98B1 /* CoreBlurView */, 77 | 89B67C891B1406E9002D98B1 /* CoreBlurViewTests */, 78 | 89B67C6E1B1406E9002D98B1 /* Products */, 79 | ); 80 | sourceTree = ""; 81 | }; 82 | 89B67C6E1B1406E9002D98B1 /* Products */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | 89B67C6D1B1406E9002D98B1 /* CoreBlurView.app */, 86 | 89B67C861B1406E9002D98B1 /* CoreBlurViewTests.xctest */, 87 | ); 88 | name = Products; 89 | sourceTree = ""; 90 | }; 91 | 89B67C6F1B1406E9002D98B1 /* CoreBlurView */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | 89B67C961B140711002D98B1 /* CoreBlurView */, 95 | 89B67C741B1406E9002D98B1 /* AppDelegate.h */, 96 | 89B67C751B1406E9002D98B1 /* AppDelegate.m */, 97 | 89B67C771B1406E9002D98B1 /* ViewController.h */, 98 | 89B67C781B1406E9002D98B1 /* ViewController.m */, 99 | 89B67C7A1B1406E9002D98B1 /* Main.storyboard */, 100 | 89B67C7D1B1406E9002D98B1 /* Images.xcassets */, 101 | 89B67C7F1B1406E9002D98B1 /* LaunchScreen.xib */, 102 | 89B67C701B1406E9002D98B1 /* Supporting Files */, 103 | ); 104 | path = CoreBlurView; 105 | sourceTree = ""; 106 | }; 107 | 89B67C701B1406E9002D98B1 /* Supporting Files */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 89B67CA11B141E6D002D98B1 /* 1.gif */, 111 | 89B67C9C1B140B53002D98B1 /* 1@2x.png */, 112 | 89B67C711B1406E9002D98B1 /* Info.plist */, 113 | 89B67C721B1406E9002D98B1 /* main.m */, 114 | ); 115 | name = "Supporting Files"; 116 | sourceTree = ""; 117 | }; 118 | 89B67C891B1406E9002D98B1 /* CoreBlurViewTests */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | 89B67C8C1B1406E9002D98B1 /* CoreBlurViewTests.m */, 122 | 89B67C8A1B1406E9002D98B1 /* Supporting Files */, 123 | ); 124 | path = CoreBlurViewTests; 125 | sourceTree = ""; 126 | }; 127 | 89B67C8A1B1406E9002D98B1 /* Supporting Files */ = { 128 | isa = PBXGroup; 129 | children = ( 130 | 89B67C8B1B1406E9002D98B1 /* Info.plist */, 131 | ); 132 | name = "Supporting Files"; 133 | sourceTree = ""; 134 | }; 135 | 89B67C961B140711002D98B1 /* CoreBlurView */ = { 136 | isa = PBXGroup; 137 | children = ( 138 | 89B67C971B140711002D98B1 /* Lib */, 139 | ); 140 | path = CoreBlurView; 141 | sourceTree = ""; 142 | }; 143 | 89B67C971B140711002D98B1 /* Lib */ = { 144 | isa = PBXGroup; 145 | children = ( 146 | 89B67C981B140711002D98B1 /* FXBlurView */, 147 | 89B67C9E1B14145A002D98B1 /* CoreBlurView.h */, 148 | 89B67C9F1B14145A002D98B1 /* CoreBlurView.m */, 149 | ); 150 | path = Lib; 151 | sourceTree = ""; 152 | }; 153 | 89B67C981B140711002D98B1 /* FXBlurView */ = { 154 | isa = PBXGroup; 155 | children = ( 156 | 89B67C991B140711002D98B1 /* FXBlurView.h */, 157 | 89B67C9A1B140711002D98B1 /* FXBlurView.m */, 158 | ); 159 | path = FXBlurView; 160 | sourceTree = ""; 161 | }; 162 | /* End PBXGroup section */ 163 | 164 | /* Begin PBXNativeTarget section */ 165 | 89B67C6C1B1406E9002D98B1 /* CoreBlurView */ = { 166 | isa = PBXNativeTarget; 167 | buildConfigurationList = 89B67C901B1406E9002D98B1 /* Build configuration list for PBXNativeTarget "CoreBlurView" */; 168 | buildPhases = ( 169 | 89B67C691B1406E9002D98B1 /* Sources */, 170 | 89B67C6A1B1406E9002D98B1 /* Frameworks */, 171 | 89B67C6B1B1406E9002D98B1 /* Resources */, 172 | ); 173 | buildRules = ( 174 | ); 175 | dependencies = ( 176 | ); 177 | name = CoreBlurView; 178 | productName = CoreBlurView; 179 | productReference = 89B67C6D1B1406E9002D98B1 /* CoreBlurView.app */; 180 | productType = "com.apple.product-type.application"; 181 | }; 182 | 89B67C851B1406E9002D98B1 /* CoreBlurViewTests */ = { 183 | isa = PBXNativeTarget; 184 | buildConfigurationList = 89B67C931B1406E9002D98B1 /* Build configuration list for PBXNativeTarget "CoreBlurViewTests" */; 185 | buildPhases = ( 186 | 89B67C821B1406E9002D98B1 /* Sources */, 187 | 89B67C831B1406E9002D98B1 /* Frameworks */, 188 | 89B67C841B1406E9002D98B1 /* Resources */, 189 | ); 190 | buildRules = ( 191 | ); 192 | dependencies = ( 193 | 89B67C881B1406E9002D98B1 /* PBXTargetDependency */, 194 | ); 195 | name = CoreBlurViewTests; 196 | productName = CoreBlurViewTests; 197 | productReference = 89B67C861B1406E9002D98B1 /* CoreBlurViewTests.xctest */; 198 | productType = "com.apple.product-type.bundle.unit-test"; 199 | }; 200 | /* End PBXNativeTarget section */ 201 | 202 | /* Begin PBXProject section */ 203 | 89B67C651B1406E9002D98B1 /* Project object */ = { 204 | isa = PBXProject; 205 | attributes = { 206 | LastUpgradeCheck = 0630; 207 | ORGANIZATIONNAME = "冯成林"; 208 | TargetAttributes = { 209 | 89B67C6C1B1406E9002D98B1 = { 210 | CreatedOnToolsVersion = 6.3.1; 211 | }; 212 | 89B67C851B1406E9002D98B1 = { 213 | CreatedOnToolsVersion = 6.3.1; 214 | TestTargetID = 89B67C6C1B1406E9002D98B1; 215 | }; 216 | }; 217 | }; 218 | buildConfigurationList = 89B67C681B1406E9002D98B1 /* Build configuration list for PBXProject "CoreBlurView" */; 219 | compatibilityVersion = "Xcode 3.2"; 220 | developmentRegion = English; 221 | hasScannedForEncodings = 0; 222 | knownRegions = ( 223 | en, 224 | Base, 225 | ); 226 | mainGroup = 89B67C641B1406E9002D98B1; 227 | productRefGroup = 89B67C6E1B1406E9002D98B1 /* Products */; 228 | projectDirPath = ""; 229 | projectRoot = ""; 230 | targets = ( 231 | 89B67C6C1B1406E9002D98B1 /* CoreBlurView */, 232 | 89B67C851B1406E9002D98B1 /* CoreBlurViewTests */, 233 | ); 234 | }; 235 | /* End PBXProject section */ 236 | 237 | /* Begin PBXResourcesBuildPhase section */ 238 | 89B67C6B1B1406E9002D98B1 /* Resources */ = { 239 | isa = PBXResourcesBuildPhase; 240 | buildActionMask = 2147483647; 241 | files = ( 242 | 89B67C7C1B1406E9002D98B1 /* Main.storyboard in Resources */, 243 | 89B67C811B1406E9002D98B1 /* LaunchScreen.xib in Resources */, 244 | 89B67C9D1B140B53002D98B1 /* 1@2x.png in Resources */, 245 | 89B67CA21B141E6D002D98B1 /* 1.gif in Resources */, 246 | 89B67C7E1B1406E9002D98B1 /* Images.xcassets in Resources */, 247 | ); 248 | runOnlyForDeploymentPostprocessing = 0; 249 | }; 250 | 89B67C841B1406E9002D98B1 /* Resources */ = { 251 | isa = PBXResourcesBuildPhase; 252 | buildActionMask = 2147483647; 253 | files = ( 254 | ); 255 | runOnlyForDeploymentPostprocessing = 0; 256 | }; 257 | /* End PBXResourcesBuildPhase section */ 258 | 259 | /* Begin PBXSourcesBuildPhase section */ 260 | 89B67C691B1406E9002D98B1 /* Sources */ = { 261 | isa = PBXSourcesBuildPhase; 262 | buildActionMask = 2147483647; 263 | files = ( 264 | 89B67C791B1406E9002D98B1 /* ViewController.m in Sources */, 265 | 89B67CA01B14145A002D98B1 /* CoreBlurView.m in Sources */, 266 | 89B67C9B1B140711002D98B1 /* FXBlurView.m in Sources */, 267 | 89B67C761B1406E9002D98B1 /* AppDelegate.m in Sources */, 268 | 89B67C731B1406E9002D98B1 /* main.m in Sources */, 269 | ); 270 | runOnlyForDeploymentPostprocessing = 0; 271 | }; 272 | 89B67C821B1406E9002D98B1 /* Sources */ = { 273 | isa = PBXSourcesBuildPhase; 274 | buildActionMask = 2147483647; 275 | files = ( 276 | 89B67C8D1B1406E9002D98B1 /* CoreBlurViewTests.m in Sources */, 277 | ); 278 | runOnlyForDeploymentPostprocessing = 0; 279 | }; 280 | /* End PBXSourcesBuildPhase section */ 281 | 282 | /* Begin PBXTargetDependency section */ 283 | 89B67C881B1406E9002D98B1 /* PBXTargetDependency */ = { 284 | isa = PBXTargetDependency; 285 | target = 89B67C6C1B1406E9002D98B1 /* CoreBlurView */; 286 | targetProxy = 89B67C871B1406E9002D98B1 /* PBXContainerItemProxy */; 287 | }; 288 | /* End PBXTargetDependency section */ 289 | 290 | /* Begin PBXVariantGroup section */ 291 | 89B67C7A1B1406E9002D98B1 /* Main.storyboard */ = { 292 | isa = PBXVariantGroup; 293 | children = ( 294 | 89B67C7B1B1406E9002D98B1 /* Base */, 295 | ); 296 | name = Main.storyboard; 297 | sourceTree = ""; 298 | }; 299 | 89B67C7F1B1406E9002D98B1 /* LaunchScreen.xib */ = { 300 | isa = PBXVariantGroup; 301 | children = ( 302 | 89B67C801B1406E9002D98B1 /* Base */, 303 | ); 304 | name = LaunchScreen.xib; 305 | sourceTree = ""; 306 | }; 307 | /* End PBXVariantGroup section */ 308 | 309 | /* Begin XCBuildConfiguration section */ 310 | 89B67C8E1B1406E9002D98B1 /* Debug */ = { 311 | isa = XCBuildConfiguration; 312 | buildSettings = { 313 | ALWAYS_SEARCH_USER_PATHS = NO; 314 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 315 | CLANG_CXX_LIBRARY = "libc++"; 316 | CLANG_ENABLE_MODULES = YES; 317 | CLANG_ENABLE_OBJC_ARC = YES; 318 | CLANG_WARN_BOOL_CONVERSION = YES; 319 | CLANG_WARN_CONSTANT_CONVERSION = YES; 320 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 321 | CLANG_WARN_EMPTY_BODY = YES; 322 | CLANG_WARN_ENUM_CONVERSION = YES; 323 | CLANG_WARN_INT_CONVERSION = YES; 324 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 325 | CLANG_WARN_UNREACHABLE_CODE = YES; 326 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 327 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 328 | COPY_PHASE_STRIP = NO; 329 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 330 | ENABLE_STRICT_OBJC_MSGSEND = YES; 331 | GCC_C_LANGUAGE_STANDARD = gnu99; 332 | GCC_DYNAMIC_NO_PIC = NO; 333 | GCC_NO_COMMON_BLOCKS = YES; 334 | GCC_OPTIMIZATION_LEVEL = 0; 335 | GCC_PREPROCESSOR_DEFINITIONS = ( 336 | "DEBUG=1", 337 | "$(inherited)", 338 | ); 339 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 340 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 341 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 342 | GCC_WARN_UNDECLARED_SELECTOR = YES; 343 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 344 | GCC_WARN_UNUSED_FUNCTION = YES; 345 | GCC_WARN_UNUSED_VARIABLE = YES; 346 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 347 | MTL_ENABLE_DEBUG_INFO = YES; 348 | ONLY_ACTIVE_ARCH = YES; 349 | SDKROOT = iphoneos; 350 | }; 351 | name = Debug; 352 | }; 353 | 89B67C8F1B1406E9002D98B1 /* Release */ = { 354 | isa = XCBuildConfiguration; 355 | buildSettings = { 356 | ALWAYS_SEARCH_USER_PATHS = NO; 357 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 358 | CLANG_CXX_LIBRARY = "libc++"; 359 | CLANG_ENABLE_MODULES = YES; 360 | CLANG_ENABLE_OBJC_ARC = YES; 361 | CLANG_WARN_BOOL_CONVERSION = YES; 362 | CLANG_WARN_CONSTANT_CONVERSION = YES; 363 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 364 | CLANG_WARN_EMPTY_BODY = YES; 365 | CLANG_WARN_ENUM_CONVERSION = YES; 366 | CLANG_WARN_INT_CONVERSION = YES; 367 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 368 | CLANG_WARN_UNREACHABLE_CODE = YES; 369 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 370 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 371 | COPY_PHASE_STRIP = NO; 372 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 373 | ENABLE_NS_ASSERTIONS = NO; 374 | ENABLE_STRICT_OBJC_MSGSEND = YES; 375 | GCC_C_LANGUAGE_STANDARD = gnu99; 376 | GCC_NO_COMMON_BLOCKS = YES; 377 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 378 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 379 | GCC_WARN_UNDECLARED_SELECTOR = YES; 380 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 381 | GCC_WARN_UNUSED_FUNCTION = YES; 382 | GCC_WARN_UNUSED_VARIABLE = YES; 383 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 384 | MTL_ENABLE_DEBUG_INFO = NO; 385 | SDKROOT = iphoneos; 386 | VALIDATE_PRODUCT = YES; 387 | }; 388 | name = Release; 389 | }; 390 | 89B67C911B1406E9002D98B1 /* Debug */ = { 391 | isa = XCBuildConfiguration; 392 | buildSettings = { 393 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 394 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 395 | INFOPLIST_FILE = CoreBlurView/Info.plist; 396 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 397 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 398 | PRODUCT_NAME = "$(TARGET_NAME)"; 399 | }; 400 | name = Debug; 401 | }; 402 | 89B67C921B1406E9002D98B1 /* Release */ = { 403 | isa = XCBuildConfiguration; 404 | buildSettings = { 405 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 406 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 407 | INFOPLIST_FILE = CoreBlurView/Info.plist; 408 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 409 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 410 | PRODUCT_NAME = "$(TARGET_NAME)"; 411 | }; 412 | name = Release; 413 | }; 414 | 89B67C941B1406E9002D98B1 /* Debug */ = { 415 | isa = XCBuildConfiguration; 416 | buildSettings = { 417 | BUNDLE_LOADER = "$(TEST_HOST)"; 418 | FRAMEWORK_SEARCH_PATHS = ( 419 | "$(SDKROOT)/Developer/Library/Frameworks", 420 | "$(inherited)", 421 | ); 422 | GCC_PREPROCESSOR_DEFINITIONS = ( 423 | "DEBUG=1", 424 | "$(inherited)", 425 | ); 426 | INFOPLIST_FILE = CoreBlurViewTests/Info.plist; 427 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 428 | PRODUCT_NAME = "$(TARGET_NAME)"; 429 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CoreBlurView.app/CoreBlurView"; 430 | }; 431 | name = Debug; 432 | }; 433 | 89B67C951B1406E9002D98B1 /* Release */ = { 434 | isa = XCBuildConfiguration; 435 | buildSettings = { 436 | BUNDLE_LOADER = "$(TEST_HOST)"; 437 | FRAMEWORK_SEARCH_PATHS = ( 438 | "$(SDKROOT)/Developer/Library/Frameworks", 439 | "$(inherited)", 440 | ); 441 | INFOPLIST_FILE = CoreBlurViewTests/Info.plist; 442 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 443 | PRODUCT_NAME = "$(TARGET_NAME)"; 444 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CoreBlurView.app/CoreBlurView"; 445 | }; 446 | name = Release; 447 | }; 448 | /* End XCBuildConfiguration section */ 449 | 450 | /* Begin XCConfigurationList section */ 451 | 89B67C681B1406E9002D98B1 /* Build configuration list for PBXProject "CoreBlurView" */ = { 452 | isa = XCConfigurationList; 453 | buildConfigurations = ( 454 | 89B67C8E1B1406E9002D98B1 /* Debug */, 455 | 89B67C8F1B1406E9002D98B1 /* Release */, 456 | ); 457 | defaultConfigurationIsVisible = 0; 458 | defaultConfigurationName = Release; 459 | }; 460 | 89B67C901B1406E9002D98B1 /* Build configuration list for PBXNativeTarget "CoreBlurView" */ = { 461 | isa = XCConfigurationList; 462 | buildConfigurations = ( 463 | 89B67C911B1406E9002D98B1 /* Debug */, 464 | 89B67C921B1406E9002D98B1 /* Release */, 465 | ); 466 | defaultConfigurationIsVisible = 0; 467 | defaultConfigurationName = Release; 468 | }; 469 | 89B67C931B1406E9002D98B1 /* Build configuration list for PBXNativeTarget "CoreBlurViewTests" */ = { 470 | isa = XCConfigurationList; 471 | buildConfigurations = ( 472 | 89B67C941B1406E9002D98B1 /* Debug */, 473 | 89B67C951B1406E9002D98B1 /* Release */, 474 | ); 475 | defaultConfigurationIsVisible = 0; 476 | defaultConfigurationName = Release; 477 | }; 478 | /* End XCConfigurationList section */ 479 | }; 480 | rootObject = 89B67C651B1406E9002D98B1 /* Project object */; 481 | } 482 | -------------------------------------------------------------------------------- /CoreBlurView.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CoreBlurView.xcodeproj/project.xcworkspace/xcshareddata/CoreBlurView.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | E09F6E72-43CD-48F6-94CF-E9E1251E578B 9 | IDESourceControlProjectName 10 | CoreBlurView 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 43F2E01506F9DCF23A6D2EBA030342DBF954FBE4 14 | https://github.com/nsdictionary/CoreBlurView.git 15 | 16 | IDESourceControlProjectPath 17 | CoreBlurView.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 43F2E01506F9DCF23A6D2EBA030342DBF954FBE4 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/nsdictionary/CoreBlurView.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | 43F2E01506F9DCF23A6D2EBA030342DBF954FBE4 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 43F2E01506F9DCF23A6D2EBA030342DBF954FBE4 36 | IDESourceControlWCCName 37 | CoreBlurView 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /CoreBlurView.xcodeproj/project.xcworkspace/xcuserdata/Charlin.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlinFeng/CoreBlurView/322202b673a47603db557f6337486145f3219797/CoreBlurView.xcodeproj/project.xcworkspace/xcuserdata/Charlin.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /CoreBlurView.xcodeproj/xcuserdata/Charlin.xcuserdatad/xcschemes/CoreBlurView.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 77 | 83 | 84 | 85 | 86 | 87 | 88 | 94 | 96 | 102 | 103 | 104 | 105 | 107 | 108 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /CoreBlurView.xcodeproj/xcuserdata/Charlin.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | CoreBlurView.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 89B67C6C1B1406E9002D98B1 16 | 17 | primary 18 | 19 | 20 | 89B67C851B1406E9002D98B1 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /CoreBlurView/1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlinFeng/CoreBlurView/322202b673a47603db557f6337486145f3219797/CoreBlurView/1.gif -------------------------------------------------------------------------------- /CoreBlurView/1@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlinFeng/CoreBlurView/322202b673a47603db557f6337486145f3219797/CoreBlurView/1@2x.png -------------------------------------------------------------------------------- /CoreBlurView/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // CoreBlurView 4 | // 5 | // Created by 冯成林 on 15/5/26. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /CoreBlurView/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // CoreBlurView 4 | // 5 | // Created by 冯成林 on 15/5/26. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /CoreBlurView/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /CoreBlurView/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 | 73 | -------------------------------------------------------------------------------- /CoreBlurView/CoreBlurView/Lib/CoreBlurView.h: -------------------------------------------------------------------------------- 1 | // 2 | // CoreBlurView.h 3 | // CoreBlurView 4 | // 5 | // Created by 冯成林 on 15/5/26. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | 10 | /* 11 | * iterations 2 12 | * blurRadius 40 13 | */ 14 | 15 | 16 | 17 | #import "FXBlurView.h" 18 | 19 | @interface CoreBlurView : FXBlurView 20 | 21 | 22 | 23 | 24 | 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /CoreBlurView/CoreBlurView/Lib/CoreBlurView.m: -------------------------------------------------------------------------------- 1 | // 2 | // CoreBlurView.m 3 | // CoreBlurView 4 | // 5 | // Created by 冯成林 on 15/5/26. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "CoreBlurView.h" 10 | 11 | @implementation CoreBlurView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreBlurView/CoreBlurView/Lib/FXBlurView/FXBlurView.h: -------------------------------------------------------------------------------- 1 | // 2 | // FXBlurView.h 3 | // 4 | // Version 1.6.3 5 | // 6 | // Created by Nick Lockwood on 25/08/2013. 7 | // Copyright (c) 2013 Charcoal Design 8 | // 9 | // Distributed under the permissive zlib License 10 | // Get the latest version from here: 11 | // 12 | // https://github.com/nicklockwood/FXBlurView 13 | // 14 | // This software is provided 'as-is', without any express or implied 15 | // warranty. In no event will the authors be held liable for any damages 16 | // arising from the use of this software. 17 | // 18 | // Permission is granted to anyone to use this software for any purpose, 19 | // including commercial applications, and to alter it and redistribute it 20 | // freely, subject to the following restrictions: 21 | // 22 | // 1. The origin of this software must not be misrepresented; you must not 23 | // claim that you wrote the original software. If you use this software 24 | // in a product, an acknowledgment in the product documentation would be 25 | // appreciated but is not required. 26 | // 27 | // 2. Altered source versions must be plainly marked as such, and must not be 28 | // misrepresented as being the original software. 29 | // 30 | // 3. This notice may not be removed or altered from any source distribution. 31 | // 32 | 33 | 34 | #import 35 | #import 36 | #import 37 | 38 | 39 | #pragma GCC diagnostic push 40 | #pragma GCC diagnostic ignored "-Wobjc-missing-property-synthesis" 41 | 42 | 43 | #import 44 | #undef weak_ref 45 | #if __has_feature(objc_arc) && __has_feature(objc_arc_weak) 46 | #define weak_ref weak 47 | #else 48 | #define weak_ref unsafe_unretained 49 | #endif 50 | 51 | 52 | @interface UIImage (FXBlurView) 53 | 54 | - (UIImage *)blurredImageWithRadius:(CGFloat)radius iterations:(NSUInteger)iterations tintColor:(UIColor *)tintColor; 55 | 56 | @end 57 | 58 | 59 | @interface FXBlurView : UIView 60 | 61 | + (void)setBlurEnabled:(BOOL)blurEnabled; 62 | + (void)setUpdatesEnabled; 63 | + (void)setUpdatesDisabled; 64 | 65 | @property (nonatomic, getter = isBlurEnabled) BOOL blurEnabled; 66 | @property (nonatomic, getter = isDynamic) BOOL dynamic; 67 | @property (nonatomic, assign) NSUInteger iterations; 68 | @property (nonatomic, assign) NSTimeInterval updateInterval; 69 | @property (nonatomic, assign) CGFloat blurRadius; 70 | @property (nonatomic, strong) UIColor *tintColor; 71 | @property (nonatomic, weak_ref) IBOutlet UIView *underlyingView; 72 | 73 | - (void)updateAsynchronously:(BOOL)async completion:(void (^)())completion; 74 | 75 | @end 76 | 77 | 78 | #pragma GCC diagnostic pop 79 | 80 | -------------------------------------------------------------------------------- /CoreBlurView/CoreBlurView/Lib/FXBlurView/FXBlurView.m: -------------------------------------------------------------------------------- 1 | // 2 | // FXBlurView.m 3 | // 4 | // Version 1.6.3 5 | // 6 | // Created by Nick Lockwood on 25/08/2013. 7 | // Copyright (c) 2013 Charcoal Design 8 | // 9 | // Distributed under the permissive zlib License 10 | // Get the latest version from here: 11 | // 12 | // https://github.com/nicklockwood/FXBlurView 13 | // 14 | // This software is provided 'as-is', without any express or implied 15 | // warranty. In no event will the authors be held liable for any damages 16 | // arising from the use of this software. 17 | // 18 | // Permission is granted to anyone to use this software for any purpose, 19 | // including commercial applications, and to alter it and redistribute it 20 | // freely, subject to the following restrictions: 21 | // 22 | // 1. The origin of this software must not be misrepresented; you must not 23 | // claim that you wrote the original software. If you use this software 24 | // in a product, an acknowledgment in the product documentation would be 25 | // appreciated but is not required. 26 | // 27 | // 2. Altered source versions must be plainly marked as such, and must not be 28 | // misrepresented as being the original software. 29 | // 30 | // 3. This notice may not be removed or altered from any source distribution. 31 | // 32 | 33 | 34 | #import "FXBlurView.h" 35 | #import 36 | 37 | 38 | #pragma GCC diagnostic ignored "-Wobjc-missing-property-synthesis" 39 | #pragma GCC diagnostic ignored "-Wdirect-ivar-access" 40 | #pragma GCC diagnostic ignored "-Wgnu" 41 | 42 | 43 | #import 44 | #if !__has_feature(objc_arc) 45 | #error This class requires automatic reference counting 46 | #endif 47 | 48 | 49 | @implementation UIImage (FXBlurView) 50 | 51 | - (UIImage *)blurredImageWithRadius:(CGFloat)radius iterations:(NSUInteger)iterations tintColor:(UIColor *)tintColor 52 | { 53 | //image must be nonzero size 54 | if (floorf(self.size.width) * floorf(self.size.height) <= 0.0f) return self; 55 | 56 | //boxsize must be an odd integer 57 | uint32_t boxSize = (uint32_t)(radius * self.scale); 58 | if (boxSize % 2 == 0) boxSize ++; 59 | 60 | //create image buffers 61 | CGImageRef imageRef = self.CGImage; 62 | vImage_Buffer buffer1, buffer2; 63 | buffer1.width = buffer2.width = CGImageGetWidth(imageRef); 64 | buffer1.height = buffer2.height = CGImageGetHeight(imageRef); 65 | buffer1.rowBytes = buffer2.rowBytes = CGImageGetBytesPerRow(imageRef); 66 | size_t bytes = buffer1.rowBytes * buffer1.height; 67 | buffer1.data = malloc(bytes); 68 | buffer2.data = malloc(bytes); 69 | 70 | //create temp buffer 71 | void *tempBuffer = malloc((size_t)vImageBoxConvolve_ARGB8888(&buffer1, &buffer2, NULL, 0, 0, boxSize, boxSize, 72 | NULL, kvImageEdgeExtend + kvImageGetTempBufferSize)); 73 | 74 | //copy image data 75 | CFDataRef dataSource = CGDataProviderCopyData(CGImageGetDataProvider(imageRef)); 76 | memcpy(buffer1.data, CFDataGetBytePtr(dataSource), bytes); 77 | CFRelease(dataSource); 78 | 79 | for (NSUInteger i = 0; i < iterations; i++) 80 | { 81 | //perform blur 82 | vImageBoxConvolve_ARGB8888(&buffer1, &buffer2, tempBuffer, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend); 83 | 84 | //swap buffers 85 | void *temp = buffer1.data; 86 | buffer1.data = buffer2.data; 87 | buffer2.data = temp; 88 | } 89 | 90 | //free buffers 91 | free(buffer2.data); 92 | free(tempBuffer); 93 | 94 | //create image context from buffer 95 | CGContextRef ctx = CGBitmapContextCreate(buffer1.data, buffer1.width, buffer1.height, 96 | 8, buffer1.rowBytes, CGImageGetColorSpace(imageRef), 97 | CGImageGetBitmapInfo(imageRef)); 98 | 99 | //apply tint 100 | if (tintColor && CGColorGetAlpha(tintColor.CGColor) > 0.0f) 101 | { 102 | CGContextSetFillColorWithColor(ctx, [tintColor colorWithAlphaComponent:0.25].CGColor); 103 | CGContextSetBlendMode(ctx, kCGBlendModePlusLighter); 104 | CGContextFillRect(ctx, CGRectMake(0, 0, buffer1.width, buffer1.height)); 105 | } 106 | 107 | //create image from context 108 | imageRef = CGBitmapContextCreateImage(ctx); 109 | UIImage *image = [UIImage imageWithCGImage:imageRef scale:self.scale orientation:self.imageOrientation]; 110 | CGImageRelease(imageRef); 111 | CGContextRelease(ctx); 112 | free(buffer1.data); 113 | return image; 114 | } 115 | 116 | @end 117 | 118 | 119 | @interface FXBlurScheduler : NSObject 120 | 121 | @property (nonatomic, strong) NSMutableArray *views; 122 | @property (nonatomic, assign) NSUInteger viewIndex; 123 | @property (nonatomic, assign) NSUInteger updatesEnabled; 124 | @property (nonatomic, assign) BOOL blurEnabled; 125 | @property (nonatomic, assign) BOOL updating; 126 | 127 | @end 128 | 129 | 130 | @interface FXBlurLayer: CALayer 131 | 132 | @property (nonatomic, assign) CGFloat blurRadius; 133 | 134 | @end 135 | 136 | 137 | @implementation FXBlurLayer 138 | 139 | @dynamic blurRadius; 140 | 141 | + (BOOL)needsDisplayForKey:(NSString *)key 142 | { 143 | if ([@[@"blurRadius", @"bounds", @"position"] containsObject:key]) 144 | { 145 | return YES; 146 | } 147 | return [super needsDisplayForKey:key]; 148 | } 149 | 150 | @end 151 | 152 | 153 | @interface FXBlurView () 154 | 155 | @property (nonatomic, assign) BOOL iterationsSet; 156 | @property (nonatomic, assign) BOOL blurRadiusSet; 157 | @property (nonatomic, assign) BOOL dynamicSet; 158 | @property (nonatomic, assign) BOOL blurEnabledSet; 159 | @property (nonatomic, strong) NSDate *lastUpdate; 160 | 161 | - (UIImage *)snapshotOfUnderlyingView; 162 | - (BOOL)shouldUpdate; 163 | 164 | @end 165 | 166 | 167 | @implementation FXBlurScheduler 168 | 169 | + (instancetype)sharedInstance 170 | { 171 | static FXBlurScheduler *sharedInstance = nil; 172 | if (!sharedInstance) 173 | { 174 | sharedInstance = [[FXBlurScheduler alloc] init]; 175 | } 176 | return sharedInstance; 177 | } 178 | 179 | - (instancetype)init 180 | { 181 | if ((self = [super init])) 182 | { 183 | _updatesEnabled = 1; 184 | _blurEnabled = YES; 185 | _views = [[NSMutableArray alloc] init]; 186 | } 187 | return self; 188 | } 189 | 190 | - (void)setBlurEnabled:(BOOL)blurEnabled 191 | { 192 | _blurEnabled = blurEnabled; 193 | if (blurEnabled) 194 | { 195 | for (FXBlurView *view in self.views) 196 | { 197 | [view setNeedsDisplay]; 198 | } 199 | [self updateAsynchronously]; 200 | } 201 | } 202 | 203 | - (void)setUpdatesEnabled 204 | { 205 | _updatesEnabled ++; 206 | [self updateAsynchronously]; 207 | } 208 | 209 | - (void)setUpdatesDisabled 210 | { 211 | _updatesEnabled --; 212 | } 213 | 214 | - (void)addView:(FXBlurView *)view 215 | { 216 | if (![self.views containsObject:view]) 217 | { 218 | [self.views addObject:view]; 219 | [self updateAsynchronously]; 220 | } 221 | } 222 | 223 | - (void)removeView:(FXBlurView *)view 224 | { 225 | NSUInteger index = [self.views indexOfObject:view]; 226 | if (index != NSNotFound) 227 | { 228 | if (index <= self.viewIndex) 229 | { 230 | self.viewIndex --; 231 | } 232 | [self.views removeObjectAtIndex:index]; 233 | } 234 | } 235 | 236 | - (void)updateAsynchronously 237 | { 238 | if (self.blurEnabled && !self.updating && self.updatesEnabled > 0 && [self.views count]) 239 | { 240 | NSTimeInterval timeUntilNextUpdate = 1.0 / 60; 241 | 242 | //loop through until we find a view that's ready to be drawn 243 | self.viewIndex = self.viewIndex % [self.views count]; 244 | for (NSUInteger i = self.viewIndex; i < [self.views count]; i++) 245 | { 246 | FXBlurView *view = self.views[i]; 247 | if (view.dynamic && !view.hidden && view.window && [view shouldUpdate]) 248 | { 249 | NSTimeInterval nextUpdate = [view.lastUpdate timeIntervalSinceNow] + view.updateInterval; 250 | if (!view.lastUpdate || nextUpdate <= 0) 251 | { 252 | self.updating = YES; 253 | [view updateAsynchronously:YES completion:^{ 254 | 255 | //render next view 256 | self.updating = NO; 257 | self.viewIndex = i + 1; 258 | [self updateAsynchronously]; 259 | }]; 260 | return; 261 | } 262 | else 263 | { 264 | timeUntilNextUpdate = MIN(timeUntilNextUpdate, nextUpdate); 265 | } 266 | } 267 | } 268 | 269 | //try again, delaying until the time when the next view needs an update. 270 | self.viewIndex = 0; 271 | [self performSelector:@selector(updateAsynchronously) 272 | withObject:nil 273 | afterDelay:timeUntilNextUpdate 274 | inModes:@[NSDefaultRunLoopMode, UITrackingRunLoopMode]]; 275 | } 276 | } 277 | 278 | @end 279 | 280 | 281 | @implementation FXBlurView 282 | 283 | + (void)setBlurEnabled:(BOOL)blurEnabled 284 | { 285 | [FXBlurScheduler sharedInstance].blurEnabled = blurEnabled; 286 | } 287 | 288 | + (void)setUpdatesEnabled 289 | { 290 | [[FXBlurScheduler sharedInstance] setUpdatesEnabled]; 291 | } 292 | 293 | + (void)setUpdatesDisabled 294 | { 295 | [[FXBlurScheduler sharedInstance] setUpdatesDisabled]; 296 | } 297 | 298 | + (Class)layerClass 299 | { 300 | return [FXBlurLayer class]; 301 | } 302 | 303 | - (void)setUp 304 | { 305 | if (!_iterationsSet) _iterations = 3; 306 | if (!_blurRadiusSet) [self blurLayer].blurRadius = 40; 307 | if (!_dynamicSet) _dynamic = YES; 308 | if (!_blurEnabledSet) _blurEnabled = YES; 309 | self.updateInterval = _updateInterval; 310 | self.layer.magnificationFilter = @"linear"; // kCAFilterLinear 311 | 312 | unsigned int numberOfMethods; 313 | Method *methods = class_copyMethodList([UIView class], &numberOfMethods); 314 | for (unsigned int i = 0; i < numberOfMethods; i++) 315 | { 316 | Method method = methods[i]; 317 | SEL selector = method_getName(method); 318 | if (selector == @selector(tintColor)) 319 | { 320 | _tintColor = ((id (*)(id,SEL))method_getImplementation(method))(self, selector); 321 | break; 322 | } 323 | } 324 | free(methods); 325 | } 326 | 327 | - (id)initWithFrame:(CGRect)frame 328 | { 329 | if ((self = [super initWithFrame:frame])) 330 | { 331 | [self setUp]; 332 | self.clipsToBounds = YES; 333 | } 334 | return self; 335 | } 336 | 337 | - (id)initWithCoder:(NSCoder *)aDecoder 338 | { 339 | if ((self = [super initWithCoder:aDecoder])) 340 | { 341 | [self setUp]; 342 | } 343 | return self; 344 | } 345 | 346 | - (void)dealloc 347 | { 348 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 349 | } 350 | 351 | - (void)setIterations:(NSUInteger)iterations 352 | { 353 | _iterationsSet = YES; 354 | _iterations = iterations; 355 | [self setNeedsDisplay]; 356 | } 357 | 358 | - (void)setBlurRadius:(CGFloat)blurRadius 359 | { 360 | _blurRadiusSet = YES; 361 | [self blurLayer].blurRadius = blurRadius; 362 | } 363 | 364 | - (CGFloat)blurRadius 365 | { 366 | return [self blurLayer].blurRadius; 367 | } 368 | 369 | - (void)setBlurEnabled:(BOOL)blurEnabled 370 | { 371 | _blurEnabledSet = YES; 372 | if (_blurEnabled != blurEnabled) 373 | { 374 | _blurEnabled = blurEnabled; 375 | [self schedule]; 376 | if (_blurEnabled) 377 | { 378 | [self setNeedsDisplay]; 379 | } 380 | } 381 | } 382 | 383 | - (void)setDynamic:(BOOL)dynamic 384 | { 385 | _dynamicSet = YES; 386 | if (_dynamic != dynamic) 387 | { 388 | _dynamic = dynamic; 389 | [self schedule]; 390 | if (!dynamic) 391 | { 392 | [self setNeedsDisplay]; 393 | } 394 | } 395 | } 396 | 397 | - (UIView *)underlyingView 398 | { 399 | return _underlyingView ?: self.superview; 400 | } 401 | 402 | - (CALayer *)underlyingLayer 403 | { 404 | return self.underlyingView.layer; 405 | } 406 | 407 | - (FXBlurLayer *)blurLayer 408 | { 409 | return (FXBlurLayer *)self.layer; 410 | } 411 | 412 | - (FXBlurLayer *)blurPresentationLayer 413 | { 414 | FXBlurLayer *blurLayer = [self blurLayer]; 415 | return (FXBlurLayer *)blurLayer.presentationLayer ?: blurLayer; 416 | } 417 | 418 | - (void)setUpdateInterval:(NSTimeInterval)updateInterval 419 | { 420 | _updateInterval = updateInterval; 421 | if (_updateInterval <= 0) _updateInterval = 1.0/60; 422 | } 423 | 424 | - (void)setTintColor:(UIColor *)tintColor 425 | { 426 | _tintColor = tintColor; 427 | [self setNeedsDisplay]; 428 | } 429 | 430 | - (void)didMoveToSuperview 431 | { 432 | [super didMoveToSuperview]; 433 | [self.layer setNeedsDisplay]; 434 | } 435 | 436 | - (void)didMoveToWindow 437 | { 438 | [super didMoveToWindow]; 439 | [self schedule]; 440 | } 441 | 442 | - (void)schedule 443 | { 444 | if (self.window && self.dynamic && self.blurEnabled) 445 | { 446 | [[FXBlurScheduler sharedInstance] addView:self]; 447 | } 448 | else 449 | { 450 | [[FXBlurScheduler sharedInstance] removeView:self]; 451 | } 452 | } 453 | 454 | - (void)setNeedsDisplay 455 | { 456 | [super setNeedsDisplay]; 457 | [self.layer setNeedsDisplay]; 458 | } 459 | 460 | - (BOOL)shouldUpdate 461 | { 462 | __strong CALayer *underlyingLayer = [self underlyingLayer]; 463 | 464 | return 465 | underlyingLayer && !underlyingLayer.hidden && 466 | self.blurEnabled && [FXBlurScheduler sharedInstance].blurEnabled && 467 | !CGRectIsEmpty([self.layer.presentationLayer ?: self.layer bounds]) && !CGRectIsEmpty(underlyingLayer.bounds); 468 | } 469 | 470 | - (void)displayLayer:(__unused CALayer *)layer 471 | { 472 | [self updateAsynchronously:NO completion:NULL]; 473 | } 474 | 475 | - (id)actionForLayer:(CALayer *)layer forKey:(NSString *)key 476 | { 477 | if ([key isEqualToString:@"blurRadius"]) 478 | { 479 | //animations are enabled 480 | CAAnimation *action = (CAAnimation *)[super actionForLayer:layer forKey:@"backgroundColor"]; 481 | if ((NSNull *)action != [NSNull null]) 482 | { 483 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:key]; 484 | animation.fromValue = [layer.presentationLayer valueForKey:key]; 485 | 486 | //CAMediatiming attributes 487 | animation.beginTime = action.beginTime; 488 | animation.duration = action.duration; 489 | animation.speed = action.speed; 490 | animation.timeOffset = action.timeOffset; 491 | animation.repeatCount = action.repeatCount; 492 | animation.repeatDuration = action.repeatDuration; 493 | animation.autoreverses = action.autoreverses; 494 | animation.fillMode = action.fillMode; 495 | 496 | //CAAnimation attributes 497 | animation.timingFunction = action.timingFunction; 498 | animation.delegate = action.delegate; 499 | 500 | return animation; 501 | } 502 | } 503 | return [super actionForLayer:layer forKey:key]; 504 | } 505 | 506 | - (UIImage *)snapshotOfUnderlyingView 507 | { 508 | __strong FXBlurLayer *blurLayer = [self blurPresentationLayer]; 509 | __strong CALayer *underlyingLayer = [self underlyingLayer]; 510 | CGRect bounds = [blurLayer convertRect:blurLayer.bounds toLayer:underlyingLayer]; 511 | 512 | self.lastUpdate = [NSDate date]; 513 | CGFloat scale = 0.5; 514 | if (self.iterations) 515 | { 516 | CGFloat blockSize = 12.0f/self.iterations; 517 | scale = blockSize/MAX(blockSize * 2, blurLayer.blurRadius); 518 | scale = 1.0f/floorf(1.0f/scale); 519 | } 520 | CGSize size = bounds.size; 521 | if (self.contentMode == UIViewContentModeScaleToFill || 522 | self.contentMode == UIViewContentModeScaleAspectFill || 523 | self.contentMode == UIViewContentModeScaleAspectFit || 524 | self.contentMode == UIViewContentModeRedraw) 525 | { 526 | //prevents edge artefacts 527 | size.width = floorf(size.width * scale) / scale; 528 | size.height = floorf(size.height * scale) / scale; 529 | } 530 | else if ([[UIDevice currentDevice].systemVersion floatValue] < 7.0f && [UIScreen mainScreen].scale == 1.0f) 531 | { 532 | //prevents pixelation on old devices 533 | scale = 1.0f; 534 | } 535 | UIGraphicsBeginImageContextWithOptions(size, NO, scale); 536 | CGContextRef context = UIGraphicsGetCurrentContext(); 537 | CGContextTranslateCTM(context, -bounds.origin.x, -bounds.origin.y); 538 | 539 | NSArray *hiddenViews = [self prepareUnderlyingViewForSnapshot]; 540 | [underlyingLayer renderInContext:context]; 541 | [self restoreSuperviewAfterSnapshot:hiddenViews]; 542 | UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext(); 543 | UIGraphicsEndImageContext(); 544 | return snapshot; 545 | } 546 | 547 | - (NSArray *)prepareUnderlyingViewForSnapshot 548 | { 549 | __strong CALayer *blurlayer = [self blurLayer]; 550 | __strong CALayer *underlyingLayer = [self underlyingLayer]; 551 | while (blurlayer.superlayer && blurlayer.superlayer != underlyingLayer) 552 | { 553 | blurlayer = blurlayer.superlayer; 554 | } 555 | NSMutableArray *layers = [NSMutableArray array]; 556 | NSUInteger index = [underlyingLayer.sublayers indexOfObject:blurlayer]; 557 | if (index != NSNotFound) 558 | { 559 | for (NSUInteger i = index; i < [underlyingLayer.sublayers count]; i++) 560 | { 561 | CALayer *layer = underlyingLayer.sublayers[i]; 562 | if (!layer.hidden) 563 | { 564 | layer.hidden = YES; 565 | [layers addObject:layer]; 566 | } 567 | } 568 | } 569 | return layers; 570 | } 571 | 572 | - (void)restoreSuperviewAfterSnapshot:(NSArray *)hiddenLayers 573 | { 574 | for (CALayer *layer in hiddenLayers) 575 | { 576 | layer.hidden = NO; 577 | } 578 | } 579 | 580 | - (UIImage *)blurredSnapshot:(UIImage *)snapshot radius:(CGFloat)blurRadius 581 | { 582 | return [snapshot blurredImageWithRadius:blurRadius 583 | iterations:self.iterations 584 | tintColor:self.tintColor]; 585 | } 586 | 587 | - (void)setLayerContents:(UIImage *)image 588 | { 589 | self.layer.contents = (id)image.CGImage; 590 | self.layer.contentsScale = image.scale; 591 | } 592 | 593 | - (void)updateAsynchronously:(BOOL)async completion:(void (^)())completion 594 | { 595 | if ([self shouldUpdate]) 596 | { 597 | NSLog(@"来了"); 598 | UIImage *snapshot = [self snapshotOfUnderlyingView]; 599 | if (async) 600 | { 601 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 602 | 603 | UIImage *blurredImage = [self blurredSnapshot:snapshot radius:self.blurRadius]; 604 | dispatch_sync(dispatch_get_main_queue(), ^{ 605 | 606 | [self setLayerContents:blurredImage]; 607 | if (completion) completion(); 608 | }); 609 | }); 610 | } 611 | else 612 | { 613 | [self setLayerContents:[self blurredSnapshot:snapshot radius:[self blurPresentationLayer].blurRadius]]; 614 | if (completion) completion(); 615 | } 616 | } 617 | else if (completion) 618 | { 619 | completion(); 620 | } 621 | } 622 | 623 | @end 624 | -------------------------------------------------------------------------------- /CoreBlurView/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /CoreBlurView/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "minimum-system-version" : "7.0", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "orientation" : "portrait", 11 | "idiom" : "iphone", 12 | "minimum-system-version" : "7.0", 13 | "subtype" : "retina4", 14 | "scale" : "2x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /CoreBlurView/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | HM.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /CoreBlurView/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // CoreBlurView 4 | // 5 | // Created by 冯成林 on 15/5/26. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /CoreBlurView/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // CoreBlurView 4 | // 5 | // Created by 冯成林 on 15/5/26. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "CoreBlurView.h" 11 | 12 | 13 | 14 | @interface ViewController () 15 | 16 | @property (nonatomic,weak) CoreBlurView *blurView; 17 | 18 | @property (weak, nonatomic) IBOutlet UIImageView *imageV; 19 | 20 | 21 | @end 22 | 23 | @implementation ViewController 24 | 25 | - (void)viewDidLoad { 26 | [super viewDidLoad]; 27 | 28 | CoreBlurView *blurView = [[CoreBlurView alloc] initWithFrame:CGRectMake(20, 40, 100, 100)]; 29 | 30 | blurView.layer.borderColor = [UIColor redColor].CGColor; 31 | 32 | blurView.layer.borderWidth = .5f; 33 | 34 | //开启动态模糊 35 | blurView.blurEnabled = YES; 36 | 37 | blurView.dynamic =NO; 38 | 39 | blurView.blurRadius = 16; 40 | 41 | blurView.tintColor = [UIColor clearColor]; 42 | 43 | blurView.underlyingView = self.view.window; 44 | 45 | _blurView = blurView; 46 | 47 | [self.view addSubview:blurView]; 48 | 49 | 50 | // [CoreBlurView setBlurEnabled:NO]; 51 | 52 | 53 | _imageV.layer.borderColor = [UIColor redColor].CGColor; 54 | 55 | _imageV.layer.borderWidth = .5f; 56 | 57 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 58 | 59 | NSLog(@"开始"); 60 | _imageV.image = [[UIImage imageNamed:@"1"] blurredImageWithRadius:20 iterations:10 tintColor:[UIColor clearColor]]; 61 | NSLog(@"结束"); 62 | }); 63 | } 64 | 65 | 66 | //-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ 67 | // 68 | // UIViewController *vc= [[UIViewController alloc] init]; 69 | // 70 | // [self.navigationController pushViewController:vc animated:YES]; 71 | //} 72 | 73 | 74 | 75 | -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{ 76 | 77 | UITouch *touch = touches.anyObject; 78 | 79 | self.blurView.center = [touch locationInView:touch.view]; 80 | 81 | [_blurView updateAsynchronously:NO completion:^{ 82 | NSLog(@"完成"); 83 | }]; 84 | 85 | } 86 | 87 | 88 | 89 | 90 | @end 91 | -------------------------------------------------------------------------------- /CoreBlurView/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // CoreBlurView 4 | // 5 | // Created by 冯成林 on 15/5/26. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /CoreBlurViewTests/CoreBlurViewTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // CoreBlurViewTests.m 3 | // CoreBlurViewTests 4 | // 5 | // Created by 冯成林 on 15/5/26. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface CoreBlurViewTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation CoreBlurViewTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /CoreBlurViewTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | HM.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | Charlin出框架的目标:简单、易用、实用、高度封装、绝对解耦! 3 | 4 | # CoreBlurView 5 | 第二牛B的模糊视图(含图片模糊) 6 |
7 | ####框架特性:
8 | >1.那么问题来了,第一牛B的是谁?GPUImage,由于我还没涉及专业图形处理,暂时没详细研究这个。
9 | >2.自用。 10 | 11 |

12 | 13 | ####.效果图片
14 | ![image](./CoreBlurView/1.gif)

15 | 16 | 17 | ----- 18 | CoreBlurView 第二牛B的模糊视图(含图片模糊) 19 | ----- 20 | 21 |

22 | 23 | #### 版权说明 RIGHTS
24 | 作品说明:本框架由iOS开发攻城狮Charlin制作。
25 | 作品时间: 2013.05.26 18:07
26 | 27 | 28 | #### 关于Chariln INTRODUCE
29 | 作者简介:Charlin-四川成都华西都市报旗下华西都市网络有限公司技术部iOS工程师!

30 | 31 | 32 | #### 联系方式 CONTACT
33 | Q Q:1761904945(请注明缘由)
34 | Mail:1761904945@qq.com
35 | --------------------------------------------------------------------------------