├── BAPrivacyManager.podspec ├── BAPrivacyManager.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── boai.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── boai.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ └── xcschememanagement.plist ├── BAPrivacyManager ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── BAPrivacyManager │ ├── BAKit_ConfigurationDefine.h │ ├── BAKit_PrivacyManager.h │ ├── BAKit_Singleton.h │ ├── BAPrivacyManager.h │ ├── BAPrivacyManager.m │ └── BAPrivacyManager_Version.h ├── Base.lproj │ └── Main.storyboard ├── Info.plist ├── LaunchScreen.storyboard ├── ViewController.h ├── ViewController.m └── main.m ├── Images ├── BAPrivacyManager.png └── BAPrivacyManager1.png ├── LICENSE └── README.md /BAPrivacyManager.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'BAPrivacyManager' 3 | s.version = '1.0.1' 4 | s.summary = 'iOS 所有隐私权限封装,定位、蓝牙、通知、运动、日历、相册、相机等 14 种权限封装!详见 demo!' 5 | s.homepage = 'https://github.com/BAHome/BAPrivacyManager' 6 | s.license = 'MIT' 7 | s.authors = { 'boai' => 'sunboyan@outlook.com' } 8 | s.platform = :ios, '8.0' 9 | s.source = { :git => 'https://github.com/BAHome/BAPrivacyManager.git', :tag => s.version.to_s } 10 | s.source_files = 'BAPrivacyManager/BAPrivacyManager/*.{h,m}' 11 | s.requires_arc = true 12 | end 13 | -------------------------------------------------------------------------------- /BAPrivacyManager.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | C4BBF8F11F89D10F008C6622 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C4BBF8F01F89D10F008C6622 /* LaunchScreen.storyboard */; }; 11 | C4C49D201F7C914200D93C48 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = C4C49D1F1F7C914200D93C48 /* AppDelegate.m */; }; 12 | C4C49D231F7C914200D93C48 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C4C49D221F7C914200D93C48 /* ViewController.m */; }; 13 | C4C49D261F7C914200D93C48 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C4C49D241F7C914200D93C48 /* Main.storyboard */; }; 14 | C4C49D281F7C914200D93C48 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C4C49D271F7C914200D93C48 /* Assets.xcassets */; }; 15 | C4C49D2E1F7C914200D93C48 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C4C49D2D1F7C914200D93C48 /* main.m */; }; 16 | C4C49D371F7C931C00D93C48 /* BAPrivacyManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C4C49D351F7C930D00D93C48 /* BAPrivacyManager.m */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | C41DD9A71F88604B00817D5B /* BAKit_Singleton.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BAKit_Singleton.h; sourceTree = ""; }; 21 | C4BBF8F01F89D10F008C6622 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; 22 | C4C49D1B1F7C914200D93C48 /* BAPrivacyManager.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BAPrivacyManager.app; sourceTree = BUILT_PRODUCTS_DIR; }; 23 | C4C49D1E1F7C914200D93C48 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 24 | C4C49D1F1F7C914200D93C48 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 25 | C4C49D211F7C914200D93C48 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 26 | C4C49D221F7C914200D93C48 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 27 | C4C49D251F7C914200D93C48 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 28 | C4C49D271F7C914200D93C48 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 29 | C4C49D2C1F7C914200D93C48 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 30 | C4C49D2D1F7C914200D93C48 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 31 | C4C49D351F7C930D00D93C48 /* BAPrivacyManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BAPrivacyManager.m; sourceTree = ""; }; 32 | C4C49D361F7C930D00D93C48 /* BAPrivacyManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BAPrivacyManager.h; sourceTree = ""; }; 33 | C4C49D381F7C936C00D93C48 /* BAKit_ConfigurationDefine.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BAKit_ConfigurationDefine.h; sourceTree = ""; }; 34 | C4C49D391F7C938900D93C48 /* BAPrivacyManager_Version.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BAPrivacyManager_Version.h; sourceTree = ""; }; 35 | C4C49D3A1F7C93C600D93C48 /* BAKit_PrivacyManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BAKit_PrivacyManager.h; sourceTree = ""; }; 36 | /* End PBXFileReference section */ 37 | 38 | /* Begin PBXFrameworksBuildPhase section */ 39 | C4C49D181F7C914200D93C48 /* Frameworks */ = { 40 | isa = PBXFrameworksBuildPhase; 41 | buildActionMask = 2147483647; 42 | files = ( 43 | ); 44 | runOnlyForDeploymentPostprocessing = 0; 45 | }; 46 | /* End PBXFrameworksBuildPhase section */ 47 | 48 | /* Begin PBXGroup section */ 49 | C4C49D121F7C914200D93C48 = { 50 | isa = PBXGroup; 51 | children = ( 52 | C4C49D1D1F7C914200D93C48 /* BAPrivacyManager */, 53 | C4C49D1C1F7C914200D93C48 /* Products */, 54 | ); 55 | sourceTree = ""; 56 | }; 57 | C4C49D1C1F7C914200D93C48 /* Products */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | C4C49D1B1F7C914200D93C48 /* BAPrivacyManager.app */, 61 | ); 62 | name = Products; 63 | sourceTree = ""; 64 | }; 65 | C4C49D1D1F7C914200D93C48 /* BAPrivacyManager */ = { 66 | isa = PBXGroup; 67 | children = ( 68 | C4C49D341F7C930200D93C48 /* BAPrivacyManager */, 69 | C4C49D1E1F7C914200D93C48 /* AppDelegate.h */, 70 | C4C49D1F1F7C914200D93C48 /* AppDelegate.m */, 71 | C4C49D211F7C914200D93C48 /* ViewController.h */, 72 | C4C49D221F7C914200D93C48 /* ViewController.m */, 73 | C4C49D241F7C914200D93C48 /* Main.storyboard */, 74 | C4C49D271F7C914200D93C48 /* Assets.xcassets */, 75 | C4C49D2C1F7C914200D93C48 /* Info.plist */, 76 | C4BBF8F01F89D10F008C6622 /* LaunchScreen.storyboard */, 77 | C4C49D2D1F7C914200D93C48 /* main.m */, 78 | ); 79 | path = BAPrivacyManager; 80 | sourceTree = ""; 81 | }; 82 | C4C49D341F7C930200D93C48 /* BAPrivacyManager */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | C4C49D381F7C936C00D93C48 /* BAKit_ConfigurationDefine.h */, 86 | C4C49D3A1F7C93C600D93C48 /* BAKit_PrivacyManager.h */, 87 | C4C49D361F7C930D00D93C48 /* BAPrivacyManager.h */, 88 | C4C49D351F7C930D00D93C48 /* BAPrivacyManager.m */, 89 | C4C49D391F7C938900D93C48 /* BAPrivacyManager_Version.h */, 90 | C41DD9A71F88604B00817D5B /* BAKit_Singleton.h */, 91 | ); 92 | path = BAPrivacyManager; 93 | sourceTree = ""; 94 | }; 95 | /* End PBXGroup section */ 96 | 97 | /* Begin PBXNativeTarget section */ 98 | C4C49D1A1F7C914200D93C48 /* BAPrivacyManager */ = { 99 | isa = PBXNativeTarget; 100 | buildConfigurationList = C4C49D311F7C914200D93C48 /* Build configuration list for PBXNativeTarget "BAPrivacyManager" */; 101 | buildPhases = ( 102 | C4C49D171F7C914200D93C48 /* Sources */, 103 | C4C49D181F7C914200D93C48 /* Frameworks */, 104 | C4C49D191F7C914200D93C48 /* Resources */, 105 | ); 106 | buildRules = ( 107 | ); 108 | dependencies = ( 109 | ); 110 | name = BAPrivacyManager; 111 | productName = BAPrivacyManager; 112 | productReference = C4C49D1B1F7C914200D93C48 /* BAPrivacyManager.app */; 113 | productType = "com.apple.product-type.application"; 114 | }; 115 | /* End PBXNativeTarget section */ 116 | 117 | /* Begin PBXProject section */ 118 | C4C49D131F7C914200D93C48 /* Project object */ = { 119 | isa = PBXProject; 120 | attributes = { 121 | LastUpgradeCheck = 0900; 122 | ORGANIZATIONNAME = boai; 123 | TargetAttributes = { 124 | C4C49D1A1F7C914200D93C48 = { 125 | CreatedOnToolsVersion = 9.0; 126 | ProvisioningStyle = Automatic; 127 | }; 128 | }; 129 | }; 130 | buildConfigurationList = C4C49D161F7C914200D93C48 /* Build configuration list for PBXProject "BAPrivacyManager" */; 131 | compatibilityVersion = "Xcode 8.0"; 132 | developmentRegion = en; 133 | hasScannedForEncodings = 0; 134 | knownRegions = ( 135 | en, 136 | Base, 137 | ); 138 | mainGroup = C4C49D121F7C914200D93C48; 139 | productRefGroup = C4C49D1C1F7C914200D93C48 /* Products */; 140 | projectDirPath = ""; 141 | projectRoot = ""; 142 | targets = ( 143 | C4C49D1A1F7C914200D93C48 /* BAPrivacyManager */, 144 | ); 145 | }; 146 | /* End PBXProject section */ 147 | 148 | /* Begin PBXResourcesBuildPhase section */ 149 | C4C49D191F7C914200D93C48 /* Resources */ = { 150 | isa = PBXResourcesBuildPhase; 151 | buildActionMask = 2147483647; 152 | files = ( 153 | C4BBF8F11F89D10F008C6622 /* LaunchScreen.storyboard in Resources */, 154 | C4C49D281F7C914200D93C48 /* Assets.xcassets in Resources */, 155 | C4C49D261F7C914200D93C48 /* Main.storyboard in Resources */, 156 | ); 157 | runOnlyForDeploymentPostprocessing = 0; 158 | }; 159 | /* End PBXResourcesBuildPhase section */ 160 | 161 | /* Begin PBXSourcesBuildPhase section */ 162 | C4C49D171F7C914200D93C48 /* Sources */ = { 163 | isa = PBXSourcesBuildPhase; 164 | buildActionMask = 2147483647; 165 | files = ( 166 | C4C49D231F7C914200D93C48 /* ViewController.m in Sources */, 167 | C4C49D371F7C931C00D93C48 /* BAPrivacyManager.m in Sources */, 168 | C4C49D2E1F7C914200D93C48 /* main.m in Sources */, 169 | C4C49D201F7C914200D93C48 /* AppDelegate.m in Sources */, 170 | ); 171 | runOnlyForDeploymentPostprocessing = 0; 172 | }; 173 | /* End PBXSourcesBuildPhase section */ 174 | 175 | /* Begin PBXVariantGroup section */ 176 | C4C49D241F7C914200D93C48 /* Main.storyboard */ = { 177 | isa = PBXVariantGroup; 178 | children = ( 179 | C4C49D251F7C914200D93C48 /* Base */, 180 | ); 181 | name = Main.storyboard; 182 | sourceTree = ""; 183 | }; 184 | /* End PBXVariantGroup section */ 185 | 186 | /* Begin XCBuildConfiguration section */ 187 | C4C49D2F1F7C914200D93C48 /* Debug */ = { 188 | isa = XCBuildConfiguration; 189 | buildSettings = { 190 | ALWAYS_SEARCH_USER_PATHS = NO; 191 | CLANG_ANALYZER_NONNULL = YES; 192 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 193 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 194 | CLANG_CXX_LIBRARY = "libc++"; 195 | CLANG_ENABLE_MODULES = YES; 196 | CLANG_ENABLE_OBJC_ARC = YES; 197 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 198 | CLANG_WARN_BOOL_CONVERSION = YES; 199 | CLANG_WARN_COMMA = YES; 200 | CLANG_WARN_CONSTANT_CONVERSION = YES; 201 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 202 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 203 | CLANG_WARN_EMPTY_BODY = YES; 204 | CLANG_WARN_ENUM_CONVERSION = YES; 205 | CLANG_WARN_INFINITE_RECURSION = YES; 206 | CLANG_WARN_INT_CONVERSION = YES; 207 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 208 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 209 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 210 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 211 | CLANG_WARN_STRICT_PROTOTYPES = YES; 212 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 213 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 214 | CLANG_WARN_UNREACHABLE_CODE = YES; 215 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 216 | CODE_SIGN_IDENTITY = "iPhone Developer"; 217 | COPY_PHASE_STRIP = NO; 218 | DEBUG_INFORMATION_FORMAT = dwarf; 219 | ENABLE_STRICT_OBJC_MSGSEND = YES; 220 | ENABLE_TESTABILITY = YES; 221 | GCC_C_LANGUAGE_STANDARD = gnu11; 222 | GCC_DYNAMIC_NO_PIC = NO; 223 | GCC_NO_COMMON_BLOCKS = YES; 224 | GCC_OPTIMIZATION_LEVEL = 0; 225 | GCC_PREPROCESSOR_DEFINITIONS = ( 226 | "DEBUG=1", 227 | "$(inherited)", 228 | ); 229 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 230 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 231 | GCC_WARN_UNDECLARED_SELECTOR = YES; 232 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 233 | GCC_WARN_UNUSED_FUNCTION = YES; 234 | GCC_WARN_UNUSED_VARIABLE = YES; 235 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 236 | MTL_ENABLE_DEBUG_INFO = YES; 237 | ONLY_ACTIVE_ARCH = YES; 238 | SDKROOT = iphoneos; 239 | }; 240 | name = Debug; 241 | }; 242 | C4C49D301F7C914200D93C48 /* Release */ = { 243 | isa = XCBuildConfiguration; 244 | buildSettings = { 245 | ALWAYS_SEARCH_USER_PATHS = NO; 246 | CLANG_ANALYZER_NONNULL = YES; 247 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 248 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 249 | CLANG_CXX_LIBRARY = "libc++"; 250 | CLANG_ENABLE_MODULES = YES; 251 | CLANG_ENABLE_OBJC_ARC = YES; 252 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 253 | CLANG_WARN_BOOL_CONVERSION = YES; 254 | CLANG_WARN_COMMA = YES; 255 | CLANG_WARN_CONSTANT_CONVERSION = YES; 256 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 257 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 258 | CLANG_WARN_EMPTY_BODY = YES; 259 | CLANG_WARN_ENUM_CONVERSION = YES; 260 | CLANG_WARN_INFINITE_RECURSION = YES; 261 | CLANG_WARN_INT_CONVERSION = YES; 262 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 263 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 264 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 265 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 266 | CLANG_WARN_STRICT_PROTOTYPES = YES; 267 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 268 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 269 | CLANG_WARN_UNREACHABLE_CODE = YES; 270 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 271 | CODE_SIGN_IDENTITY = "iPhone Developer"; 272 | COPY_PHASE_STRIP = NO; 273 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 274 | ENABLE_NS_ASSERTIONS = NO; 275 | ENABLE_STRICT_OBJC_MSGSEND = YES; 276 | GCC_C_LANGUAGE_STANDARD = gnu11; 277 | GCC_NO_COMMON_BLOCKS = YES; 278 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 279 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 280 | GCC_WARN_UNDECLARED_SELECTOR = YES; 281 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 282 | GCC_WARN_UNUSED_FUNCTION = YES; 283 | GCC_WARN_UNUSED_VARIABLE = YES; 284 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 285 | MTL_ENABLE_DEBUG_INFO = NO; 286 | SDKROOT = iphoneos; 287 | VALIDATE_PRODUCT = YES; 288 | }; 289 | name = Release; 290 | }; 291 | C4C49D321F7C914200D93C48 /* Debug */ = { 292 | isa = XCBuildConfiguration; 293 | buildSettings = { 294 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 295 | CODE_SIGN_STYLE = Automatic; 296 | DEVELOPMENT_TEAM = JB3QR65942; 297 | INFOPLIST_FILE = BAPrivacyManager/Info.plist; 298 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 299 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 300 | PRODUCT_BUNDLE_IDENTIFIER = com.boaihome.BAPrivacyManager; 301 | PRODUCT_NAME = "$(TARGET_NAME)"; 302 | TARGETED_DEVICE_FAMILY = "1,2"; 303 | }; 304 | name = Debug; 305 | }; 306 | C4C49D331F7C914200D93C48 /* Release */ = { 307 | isa = XCBuildConfiguration; 308 | buildSettings = { 309 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 310 | CODE_SIGN_STYLE = Automatic; 311 | DEVELOPMENT_TEAM = JB3QR65942; 312 | INFOPLIST_FILE = BAPrivacyManager/Info.plist; 313 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 314 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 315 | PRODUCT_BUNDLE_IDENTIFIER = com.boaihome.BAPrivacyManager; 316 | PRODUCT_NAME = "$(TARGET_NAME)"; 317 | TARGETED_DEVICE_FAMILY = "1,2"; 318 | }; 319 | name = Release; 320 | }; 321 | /* End XCBuildConfiguration section */ 322 | 323 | /* Begin XCConfigurationList section */ 324 | C4C49D161F7C914200D93C48 /* Build configuration list for PBXProject "BAPrivacyManager" */ = { 325 | isa = XCConfigurationList; 326 | buildConfigurations = ( 327 | C4C49D2F1F7C914200D93C48 /* Debug */, 328 | C4C49D301F7C914200D93C48 /* Release */, 329 | ); 330 | defaultConfigurationIsVisible = 0; 331 | defaultConfigurationName = Release; 332 | }; 333 | C4C49D311F7C914200D93C48 /* Build configuration list for PBXNativeTarget "BAPrivacyManager" */ = { 334 | isa = XCConfigurationList; 335 | buildConfigurations = ( 336 | C4C49D321F7C914200D93C48 /* Debug */, 337 | C4C49D331F7C914200D93C48 /* Release */, 338 | ); 339 | defaultConfigurationIsVisible = 0; 340 | defaultConfigurationName = Release; 341 | }; 342 | /* End XCConfigurationList section */ 343 | }; 344 | rootObject = C4C49D131F7C914200D93C48 /* Project object */; 345 | } 346 | -------------------------------------------------------------------------------- /BAPrivacyManager.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /BAPrivacyManager.xcodeproj/project.xcworkspace/xcuserdata/boai.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BAHome/BAPrivacyManager/fafa3fa6afb900923c9806e456c01b7f07e34fb0/BAPrivacyManager.xcodeproj/project.xcworkspace/xcuserdata/boai.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /BAPrivacyManager.xcodeproj/xcuserdata/boai.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /BAPrivacyManager.xcodeproj/xcuserdata/boai.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | BAPrivacyManager.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /BAPrivacyManager/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // BAPrivacyManager 4 | // 5 | // Created by boai on 2017/9/28. 6 | // Copyright © 2017年 boai. 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 | -------------------------------------------------------------------------------- /BAPrivacyManager/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // BAPrivacyManager 4 | // 5 | // Created by boai on 2017/9/28. 6 | // Copyright © 2017年 boai. 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 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // 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. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // 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. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // 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. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /BAPrivacyManager/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /BAPrivacyManager/BAPrivacyManager/BAKit_ConfigurationDefine.h: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | * @header BAKit.h 4 | * 5 | * @brief BAKit 6 | * 7 | * @author 博爱 8 | * @copyright Copyright © 2016年 博爱. All rights reserved. 9 | * @version V1.0 10 | */ 11 | 12 | // _ooOoo_ 13 | // o8888888o 14 | // 88" . "88 15 | // (| -_- |) 16 | // O\ = /O 17 | // ____/`---'\____ 18 | // . ' \\| |// `. 19 | // / \\||| : |||// \ 20 | // / _||||| -:- |||||- \ 21 | // | | \\\ - /// | | 22 | // | \_| ''\---/'' | | 23 | // \ .-\__ `-` ___/-. / 24 | // ___`. .' /--.--\ `. . __ 25 | // ."" '< `.___\_<|>_/___.' >'"". 26 | // | | : `- \`.;`\ _ /`;.`/ - ` : | | 27 | // \ \ `-. \_ __\ /__ _/ .-` / / 28 | // ======`-.____`-.___\_____/___.-`____.-'====== 29 | // `=---=' 30 | // 31 | // ............................................. 32 | // 佛祖镇楼 BUG辟易 33 | // 佛曰: 34 | // 写字楼里写字间,写字间里程序员; 35 | // 程序人员写程序,又拿程序换酒钱。 36 | // 酒醒只在网上坐,酒醉还来网下眠; 37 | // 酒醉酒醒日复日,网上网下年复年。 38 | // 但愿老死电脑间,不愿鞠躬老板前; 39 | // 奔驰宝马贵者趣,公交自行程序员。 40 | // 别人笑我忒疯癫,我笑自己命太贱; 41 | // 不见满街漂亮妹,哪个归得程序员? 42 | 43 | /* 44 | 45 | ********************************************************************************* 46 | * 47 | * 在使用 BAKit 的过程中如果出现 bug 请及时以以下任意一种方式联系我,我会及时修复 bug 48 | * 49 | * QQ : 可以添加ios开发技术群 479663605 在这里找到我(博爱1616【137361770】) 50 | * 微博 : 博爱1616 51 | * Email : 137361770@qq.com 52 | * GitHub : https://github.com/boai 53 | * BAHome : https://github.com/BAHome 54 | * 博客 : http://boaihome.com 55 | 56 | ********************************************************************************* 57 | 58 | */ 59 | 60 | 61 | #ifndef BAKit_ConfigurationDefine_h 62 | #define BAKit_ConfigurationDefine_h 63 | 64 | 65 | #ifndef __OPTIMIZE__ 66 | #define NSLog(...) NSLog(__VA_ARGS__) 67 | #else 68 | #define NSLog(...){} 69 | #endif 70 | 71 | #pragma mark - weak / strong 72 | #define BAKit_WeakSelf @BAKit_Weakify(self); 73 | #define BAKit_StrongSelf @BAKit_Strongify(self); 74 | 75 | /*! 76 | * 强弱引用转换,用于解决代码块(block)与强引用self之间的循环引用问题 77 | * 调用方式: `@BAKit_Weakify`实现弱引用转换,`@BAKit_Strongify`实现强引用转换 78 | * 79 | * 示例: 80 | * @BAKit_Weakify 81 | * [obj block:^{ 82 | * @strongify_self 83 | * self.property = something; 84 | * }]; 85 | */ 86 | #ifndef BAKit_Weakify 87 | #if DEBUG 88 | #if __has_feature(objc_arc) 89 | #define BAKit_Weakify(object) autoreleasepool{} __weak __typeof__(object) weak##_##object = object; 90 | #else 91 | #define BAKit_Weakify(object) autoreleasepool{} __block __typeof__(object) block##_##object = object; 92 | #endif 93 | #else 94 | #if __has_feature(objc_arc) 95 | #define BAKit_Weakify(object) try{} @finally{} {} __weak __typeof__(object) weak##_##object = object; 96 | #else 97 | #define BAKit_Weakify(object) try{} @finally{} {} __block __typeof__(object) block##_##object = object; 98 | #endif 99 | #endif 100 | #endif 101 | 102 | /*! 103 | * 强弱引用转换,用于解决代码块(block)与强引用对象之间的循环引用问题 104 | * 调用方式: `@BAKit_Weakify(object)`实现弱引用转换,`@BAKit_Strongify(object)`实现强引用转换 105 | * 106 | * 示例: 107 | * @BAKit_Weakify(object) 108 | * [obj block:^{ 109 | * @BAKit_Strongify(object) 110 | * strong_object = something; 111 | * }]; 112 | */ 113 | #ifndef BAKit_Strongify 114 | #if DEBUG 115 | #if __has_feature(objc_arc) 116 | #define BAKit_Strongify(object) autoreleasepool{} __typeof__(object) object = weak##_##object; 117 | #else 118 | #define BAKit_Strongify(object) autoreleasepool{} __typeof__(object) object = block##_##object; 119 | #endif 120 | #else 121 | #if __has_feature(objc_arc) 122 | #define BAKit_Strongify(object) try{} @finally{} __typeof__(object) object = weak##_##object; 123 | #else 124 | #define BAKit_Strongify(object) try{} @finally{} __typeof__(object) object = block##_##object; 125 | #endif 126 | #endif 127 | #endif 128 | 129 | /*! 获取sharedApplication */ 130 | #define BAKit_SharedApplication [UIApplication sharedApplication] 131 | 132 | #pragma mark - iOS 版本判断 133 | 134 | // 操作系统版本号 135 | #define BAKit_IOS_VERSION ([[[UIDevice currentDevice] systemVersion] floatValue]) 136 | 137 | #define BAKit_isIOS8 (([UIDevice currentDevice].systemVersion.floatValue >= 8.0f && [UIDevice currentDevice].systemVersion.floatValue < 9.0f) ? YES : NO) 138 | #define BAKit_isIOS8_Or_Later (([UIDevice currentDevice].systemVersion.floatValue >= 8.0f) ? YES : NO) 139 | #define BAKit_isIOS9 (([UIDevice currentDevice].systemVersion.floatValue >= 9.0f && [UIDevice currentDevice].systemVersion.floatValue < 10.0f) ? YES : NO) 140 | #define BAKit_isIOS9_Or_Later (([UIDevice currentDevice].systemVersion.floatValue >= 9.0f) ? YES : NO) 141 | #define BAKit_isIOS10 (([UIDevice currentDevice].systemVersion.floatValue >= 10.0f && [UIDevice currentDevice].systemVersion.floatValue < 11.0f) ? YES : NO) 142 | #define BAKit_isIOS10_Or_Later (([UIDevice currentDevice].systemVersion.floatValue >= 10.0f) ? YES : NO) 143 | 144 | /*! 主线程同步队列 */ 145 | #define dispatch_main_sync_safe(block)\ 146 | if ([NSThread isMainThread]) {\ 147 | block();\ 148 | } else {\ 149 | dispatch_sync(dispatch_get_main_queue(), block);\ 150 | } 151 | /*! 主线程异步队列 */ 152 | #define dispatch_main_async_safe(block)\ 153 | if ([NSThread isMainThread]) {\ 154 | block();\ 155 | } else {\ 156 | dispatch_async(dispatch_get_main_queue(), block);\ 157 | } 158 | 159 | 160 | #pragma mark - runtime 161 | #import 162 | /*! runtime set */ 163 | #define BAKit_Objc_setObj(key, value) objc_setAssociatedObject(self, key, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC) 164 | 165 | /*! runtime setCopy */ 166 | #define BAKit_Objc_setObjCOPY(key, value) objc_setAssociatedObject(self, key, value, OBJC_ASSOCIATION_COPY) 167 | 168 | /*! runtime get */ 169 | #define BAKit_Objc_getObj objc_getAssociatedObject(self, _cmd) 170 | 171 | /*! runtime exchangeMethod */ 172 | #define BAKit_Objc_exchangeMethodAToB(originalSelector,swizzledSelector) { \ 173 | Method originalMethod = class_getInstanceMethod(self, originalSelector); \ 174 | Method swizzledMethod = class_getInstanceMethod(self, swizzledSelector); \ 175 | if (class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))) { \ 176 | class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)); \ 177 | } else { \ 178 | method_exchangeImplementations(originalMethod, swizzledMethod); \ 179 | } \ 180 | } 181 | 182 | #pragma mark - 简单警告框 183 | /*! view 用 BAKit_ShowAlertWithMsg */ 184 | #define BAKit_ShowAlertWithMsg(msg) [[[UIAlertView alloc] initWithTitle:@"温馨提示" message:(msg) delegate:nil cancelButtonTitle:@"确 定" otherButtonTitles:nil] show]; 185 | /*! VC 用 BAKit_ShowAlertWithMsg */ 186 | #define BAKit_ShowAlertWithMsg_ios8(msg) UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"温馨提示" message:msg preferredStyle:UIAlertControllerStyleAlert];\ 187 | UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"确 定" style:UIAlertActionStyleDefault handler:nil];\ 188 | [alert addAction:sureAction];\ 189 | [self presentViewController:alert animated:YES completion:nil]; 190 | 191 | #pragma mark - color 192 | CG_INLINE UIColor * 193 | BAKit_Color_RGBA_pod(u_char r,u_char g, u_char b, u_char a) { 194 | return [UIColor colorWithRed:r/255.0f green:g/255.0f blue:b/255.0f alpha:a]; 195 | } 196 | 197 | CG_INLINE UIColor * 198 | BAKit_Color_RGB_pod(u_char r,u_char g, u_char b) { 199 | return BAKit_Color_RGBA_pod(r, g, b, 1.0); 200 | } 201 | 202 | CG_INLINE UIColor * 203 | BAKit_Color_RGBValue_pod(UInt32 rgbValue){ 204 | return [UIColor colorWithRed:((rgbValue & 0xff0000) >> 16) / 255.0f 205 | green:((rgbValue & 0xff00) >> 8) / 255.0f 206 | blue:(rgbValue & 0xff) / 255.0f 207 | alpha:1.0f]; 208 | } 209 | 210 | CG_INLINE UIColor * 211 | BAKit_Color_RGBAValue_pod(UInt32 rgbaValue){ 212 | return [UIColor colorWithRed:((rgbaValue & 0xff000000) >> 24) / 255.0f 213 | green:((rgbaValue & 0xff0000) >> 16) / 255.0f 214 | blue:((rgbaValue & 0xff00) >> 8) / 255.0f 215 | alpha:(rgbaValue & 0xff) / 255.0f]; 216 | } 217 | 218 | CG_INLINE UIColor * 219 | BAKit_Color_RandomRGB_pod(){ 220 | return BAKit_Color_RGBValue_pod(arc4random_uniform(0xffffff)); 221 | } 222 | 223 | CG_INLINE UIColor * 224 | BAKit_Color_RandomRGBA_pod(){ 225 | return BAKit_Color_RGBAValue_pod(arc4random_uniform(0xffffffff)); 226 | } 227 | 228 | 229 | #define BAKit_Color_Translucent_pod [UIColor colorWithRed:0.3f green:0.3f blue:0.3f alpha:0.5f] 230 | #define BAKit_Color_White_pod [UIColor whiteColor] 231 | #define BAKit_Color_Clear_pod [UIColor clearColor] 232 | #define BAKit_Color_Black_pod [UIColor blackColor] 233 | #define BAKit_Color_White_pod [UIColor whiteColor] 234 | #define BAKit_Color_Red_pod [UIColor redColor] 235 | #define BAKit_Color_Green_pod [UIColor greenColor] 236 | #define BAKit_Color_Orange_pod [UIColor orangeColor] 237 | #define BAKit_Color_Yellow_pod [UIColor yellowColor] 238 | 239 | 240 | /*! 灰色 */ 241 | #define BAKit_Color_Gray_1_pod BAKit_Color_RGB_pod(53, 60, 70) 242 | #define BAKit_Color_Gray_2_pod BAKit_Color_RGB_pod(73, 80, 90) 243 | #define BAKit_Color_Gray_3_pod BAKit_Color_RGB_pod(93, 100, 110) 244 | #define BAKit_Color_Gray_4_pod BAKit_Color_RGB_pod(113, 120, 130) 245 | #define BAKit_Color_Gray_5_pod BAKit_Color_RGB_pod(133, 140, 150) 246 | #define BAKit_Color_Gray_6_pod BAKit_Color_RGB_pod(153, 160, 170) 247 | #define BAKit_Color_Gray_7_pod BAKit_Color_RGB_pod(173, 180, 190) 248 | #define BAKit_Color_Gray_8_pod BAKit_Color_RGB_pod(196, 200, 208) 249 | #define BAKit_Color_Gray_9_pod BAKit_Color_RGB_pod(216, 220, 228) 250 | #define BAKit_Color_Gray_10_pod BAKit_Color_RGB_pod(240, 240, 240) 251 | #define BAKit_Color_Gray_11_pod BAKit_Color_RGB_pod(248, 248, 248) 252 | 253 | #pragma mark - Margin 254 | #define BAKit_Margin_1_pod BAKit_Flat_pod(1) 255 | #define BAKit_Margin_2_pod BAKit_Flat_pod(2) 256 | #define BAKit_Margin_5_pod BAKit_Flat_pod(5) 257 | #define BAKit_Margin_10_pod BAKit_Flat_pod(10) 258 | #define BAKit_Margin_15_pod BAKit_Flat_pod(15) 259 | #define BAKit_Margin_20_pod BAKit_Flat_pod(20) 260 | #define BAKit_Margin_25_pod BAKit_Flat_pod(25) 261 | #define BAKit_Margin_30_pod BAKit_Flat_pod(30) 262 | #define BAKit_Margin_35_pod BAKit_Flat_pod(35) 263 | #define BAKit_Margin_40_pod BAKit_Flat_pod(40) 264 | #define BAKit_Margin_44_pod BAKit_Flat_pod(44) 265 | #define BAKit_Margin_50_pod BAKit_Flat_pod(50) 266 | #define BAKit_Margin_100_pod BAKit_Flat_pod(100) 267 | #define BAKit_Margin_150_pod BAKit_Flat_pod(150) 268 | 269 | 270 | #define BAKit_ImageName(imageName) [UIImage imageNamed:imageName] 271 | 272 | #pragma mark - NotiCenter other 273 | #define BAKit_NotiCenter [NSNotificationCenter defaultCenter] 274 | 275 | #define BAKit_NSUserDefaults [NSUserDefaults standardUserDefaults] 276 | 277 | /*! 获取sharedApplication */ 278 | #define BAKit_SharedApplication [UIApplication sharedApplication] 279 | 280 | /*! 用safari打开URL */ 281 | #define BAKit_OpenUrl(urlStr) [BAKit_SharedApplication openURL:[NSURL URLWithString:urlStr]] 282 | 283 | /*! 复制文字内容 */ 284 | #define BAKit_CopyContent(content) [[UIPasteboard generalPasteboard] setString:content] 285 | 286 | 287 | /*! 288 | * 获取屏幕宽度和高度 289 | */ 290 | #define BAKit_SCREEN_WIDTH ((([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait) || ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortraitUpsideDown)) ? [[UIScreen mainScreen] bounds].size.width : [[UIScreen mainScreen] bounds].size.height) 291 | 292 | #define BAKit_SCREEN_HEIGHT ((([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait) || ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortraitUpsideDown)) ? [[UIScreen mainScreen] bounds].size.height : [[UIScreen mainScreen] bounds].size.width) 293 | 294 | #define BAKit_BaseScreenWidth 320.0f 295 | #define BAKit_BaseScreenHeight 568.0f 296 | 297 | /*! 屏幕适配(5S标准屏幕:320 * 568) */ 298 | // iPhone 7 屏幕:375 * 667 299 | //376/320 = 300 | //667/568 = 301 | #define BAKit_ScaleXAndWidth BAKit_SCREEN_WIDTH/BAKit_BaseScreenWidth 302 | #define BAKit_ScaleYAndHeight BAKit_SCREEN_HEIGHT/BAKit_BaseScreenHeight 303 | 304 | #define BAKit_ScreenScale ([[UIScreen mainScreen] scale]) 305 | 306 | CG_INLINE BOOL 307 | BAKit_stringIsBlank_pod(NSString *string) { 308 | NSCharacterSet *blank = [NSCharacterSet whitespaceAndNewlineCharacterSet]; 309 | for (NSInteger i = 0; i < string.length; ++i) { 310 | unichar c = [string characterAtIndex:i]; 311 | if (![blank characterIsMember:c]) { 312 | return NO; 313 | } 314 | } 315 | return YES; 316 | } 317 | 318 | /** 319 | * 基于指定的倍数,对传进来的 floatValue 进行像素取整。若指定倍数为0,则表示以当前设备的屏幕倍数为准。 320 | * 321 | * 例如传进来 “2.1”,在 2x 倍数下会返回 2.5(0.5pt 对应 1px),在 3x 倍数下会返回 2.333(0.333pt 对应 1px)。 322 | */ 323 | CG_INLINE CGFloat 324 | BAKit_FlatSpecificScale_pod(CGFloat floatValue, CGFloat scale) { 325 | scale = scale == 0 ? BAKit_ScreenScale : scale; 326 | CGFloat flattedValue = ceil(floatValue * scale) / scale; 327 | return flattedValue; 328 | } 329 | 330 | /** 331 | * 基于当前设备的屏幕倍数,对传进来的 floatValue 进行像素取整。 332 | * 333 | * 注意如果在 Core Graphic 绘图里使用时,要注意当前画布的倍数是否和设备屏幕倍数一致,若不一致,不可使用 flat() 函数,而应该用 flatSpecificScale 334 | */ 335 | CG_INLINE CGFloat 336 | BAKit_Flat_pod(CGFloat floatValue) { 337 | return BAKit_FlatSpecificScale_pod(floatValue, 0); 338 | } 339 | 340 | /// 将一个CGSize像素对齐 341 | CG_INLINE CGSize 342 | BAKit_CGSizeFlatted_pod(CGSize size) { 343 | return CGSizeMake(BAKit_Flat_pod(size.width), BAKit_Flat_pod(size.height)); 344 | } 345 | 346 | /// 创建一个像素对齐的CGRect 347 | CG_INLINE CGRect 348 | BAKit_CGRectFlatMake_pod(CGFloat x, CGFloat y, CGFloat width, CGFloat height) { 349 | return CGRectMake(BAKit_Flat_pod(x), BAKit_Flat_pod(y), BAKit_Flat_pod(width), BAKit_Flat_pod(height)); 350 | } 351 | 352 | /** 353 | 计算列数【根据 array.count、每行多少个 item,计算列数】 354 | 355 | @param array array 356 | @param rowCount 每行多少个 item 357 | @return 列数 358 | */ 359 | CG_INLINE NSInteger 360 | BAKit_getColumnCountWithArrayAndRowCount_pod(NSArray *array, NSInteger rowCount){ 361 | NSUInteger count = array.count; 362 | 363 | NSUInteger i = 0; 364 | if (count % rowCount == 0) 365 | { 366 | i = count / rowCount; 367 | } 368 | else 369 | { 370 | i = count / rowCount + 1; 371 | } 372 | return i; 373 | } 374 | 375 | 376 | #endif /* BAKit_ConfigurationDefine_h */ 377 | -------------------------------------------------------------------------------- /BAPrivacyManager/BAPrivacyManager/BAKit_PrivacyManager.h: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | * @header BAKit.h 4 | * 5 | * @brief BAKit 6 | * 7 | * @author 博爱 8 | * @copyright Copyright © 2016年 博爱. All rights reserved. 9 | * @version V1.0 10 | */ 11 | 12 | // _ooOoo_ 13 | // o8888888o 14 | // 88" . "88 15 | // (| -_- |) 16 | // O\ = /O 17 | // ____/`---'\____ 18 | // . ' \\| |// `. 19 | // / \\||| : |||// \ 20 | // / _||||| -:- |||||- \ 21 | // | | \\\ - /// | | 22 | // | \_| ''\---/'' | | 23 | // \ .-\__ `-` ___/-. / 24 | // ___`. .' /--.--\ `. . __ 25 | // ."" '< `.___\_<|>_/___.' >'"". 26 | // | | : `- \`.;`\ _ /`;.`/ - ` : | | 27 | // \ \ `-. \_ __\ /__ _/ .-` / / 28 | // ======`-.____`-.___\_____/___.-`____.-'====== 29 | // `=---=' 30 | // 31 | // ............................................. 32 | // 佛祖镇楼 BUG辟易 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 | * 在使用 BAKit 的过程中如果出现 bug 请及时以以下任意一种方式联系我,我会及时修复 bug 63 | * 64 | * QQ : 可以添加ios开发技术群 479663605 在这里找到我(博爱1616【137361770】) 65 | * 微博 : 博爱1616 66 | * Email : 137361770@qq.com 67 | * GitHub : https://github.com/boai 68 | * BAHome : https://github.com/BAHome 69 | * 博客 : http://boaihome.com 70 | 71 | ********************************************************************************* 72 | 73 | */ 74 | 75 | #ifndef BAKit_PrivacyManager_h 76 | #define BAKit_PrivacyManager_h 77 | 78 | #import "BAPrivacyManager.h" 79 | #import "BAKit_ConfigurationDefine.h" 80 | #import "BAPrivacyManager_Version.h" 81 | 82 | #endif /* BAKit_PrivacyManager_h */ 83 | -------------------------------------------------------------------------------- /BAPrivacyManager/BAPrivacyManager/BAKit_Singleton.h: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | * @header BAKit.h 4 | * BABaseProject 5 | * 6 | * @brief BAKit 7 | * 8 | * @author 博爱 9 | * @copyright Copyright © 2016年 博爱. All rights reserved. 10 | * @version V1.0 11 | */ 12 | 13 | // _ooOoo_ 14 | // o8888888o 15 | // 88" . "88 16 | // (| -_- |) 17 | // O\ = /O 18 | // ____/`---'\____ 19 | // . ' \\| |// `. 20 | // / \\||| : |||// \ 21 | // / _||||| -:- |||||- \ 22 | // | | \\\ - /// | | 23 | // | \_| ''\---/'' | | 24 | // \ .-\__ `-` ___/-. / 25 | // ___`. .' /--.--\ `. . __ 26 | // ."" '< `.___\_<|>_/___.' >'"". 27 | // | | : `- \`.;`\ _ /`;.`/ - ` : | | 28 | // \ \ `-. \_ __\ /__ _/ .-` / / 29 | // ======`-.____`-.___\_____/___.-`____.-'====== 30 | // `=---=' 31 | // 32 | // ............................................. 33 | // 佛祖镇楼 BUG辟易 34 | // 佛曰: 35 | // 写字楼里写字间,写字间里程序员; 36 | // 程序人员写程序,又拿程序换酒钱。 37 | // 酒醒只在网上坐,酒醉还来网下眠; 38 | // 酒醉酒醒日复日,网上网下年复年。 39 | // 但愿老死电脑间,不愿鞠躬老板前; 40 | // 奔驰宝马贵者趣,公交自行程序员。 41 | // 别人笑我忒疯癫,我笑自己命太贱; 42 | // 不见满街漂亮妹,哪个归得程序员? 43 | 44 | /* 45 | 46 | ********************************************************************************* 47 | * 48 | * 在使用BAKit的过程中如果出现bug请及时以以下任意一种方式联系我,我会及时修复bug 49 | * 50 | * QQ : 可以添加ios开发技术群 479663605 在这里找到我(博爱1616【137361770】) 51 | * 微博 : 博爱1616 52 | * Email : 137361770@qq.com 53 | * GitHub : https://github.com/boai 54 | * 博客 : http://boaihome.com 55 | 56 | ********************************************************************************* 57 | 58 | */ 59 | // 帮助实现单例设计模式 60 | 61 | // .h文件的实现 62 | #define BAKit_SingletonH(methodName) + (instancetype)shared##methodName; 63 | 64 | // .m文件的实现 65 | #if __has_feature(objc_arc) // 是ARC 66 | #define BAKit_SingletonM(methodName) \ 67 | static id _instace = nil; \ 68 | + (id)allocWithZone:(struct _NSZone *)zone \ 69 | { \ 70 | if (_instace == nil) { \ 71 | static dispatch_once_t onceToken; \ 72 | dispatch_once(&onceToken, ^{ \ 73 | _instace = [super allocWithZone:zone]; \ 74 | }); \ 75 | } \ 76 | return _instace; \ 77 | } \ 78 | \ 79 | - (id)init \ 80 | { \ 81 | static dispatch_once_t onceToken; \ 82 | dispatch_once(&onceToken, ^{ \ 83 | _instace = [super init]; \ 84 | }); \ 85 | return _instace; \ 86 | } \ 87 | \ 88 | + (instancetype)shared##methodName \ 89 | { \ 90 | return [[self alloc] init]; \ 91 | } \ 92 | + (id)copyWithZone:(struct _NSZone *)zone \ 93 | { \ 94 | return _instace; \ 95 | } \ 96 | \ 97 | + (id)mutableCopyWithZone:(struct _NSZone *)zone \ 98 | { \ 99 | return _instace; \ 100 | } 101 | 102 | #else // 不是ARC 103 | 104 | #define BAKit_SingletonM(methodName) \ 105 | static id _instace = nil; \ 106 | + (id)allocWithZone:(struct _NSZone *)zone \ 107 | { \ 108 | if (_instace == nil) { \ 109 | static dispatch_once_t onceToken; \ 110 | dispatch_once(&onceToken, ^{ \ 111 | _instace = [super allocWithZone:zone]; \ 112 | }); \ 113 | } \ 114 | return _instace; \ 115 | } \ 116 | \ 117 | - (id)init \ 118 | { \ 119 | static dispatch_once_t onceToken; \ 120 | dispatch_once(&onceToken, ^{ \ 121 | _instace = [super init]; \ 122 | }); \ 123 | return _instace; \ 124 | } \ 125 | \ 126 | + (instancetype)shared##methodName \ 127 | { \ 128 | return [[self alloc] init]; \ 129 | } \ 130 | \ 131 | - (oneway void)release \ 132 | { \ 133 | \ 134 | } \ 135 | \ 136 | - (id)retain \ 137 | { \ 138 | return self; \ 139 | } \ 140 | \ 141 | - (NSUInteger)retainCount \ 142 | { \ 143 | return 1; \ 144 | } \ 145 | + (id)copyWithZone:(struct _NSZone *)zone \ 146 | { \ 147 | return _instace; \ 148 | } \ 149 | \ 150 | + (id)mutableCopyWithZone:(struct _NSZone *)zone \ 151 | { \ 152 | return _instace; \ 153 | } 154 | 155 | #endif 156 | -------------------------------------------------------------------------------- /BAPrivacyManager/BAPrivacyManager/BAPrivacyManager.h: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | * @header BAKit.h 4 | * 5 | * @brief BAKit 6 | * 7 | * @author 博爱 8 | * @copyright Copyright © 2016年 博爱. All rights reserved. 9 | * @version V1.0 10 | */ 11 | 12 | // _ooOoo_ 13 | // o8888888o 14 | // 88" . "88 15 | // (| -_- |) 16 | // O\ = /O 17 | // ____/`---'\____ 18 | // . ' \\| |// `. 19 | // / \\||| : |||// \ 20 | // / _||||| -:- |||||- \ 21 | // | | \\\ - /// | | 22 | // | \_| ''\---/'' | | 23 | // \ .-\__ `-` ___/-. / 24 | // ___`. .' /--.--\ `. . __ 25 | // ."" '< `.___\_<|>_/___.' >'"". 26 | // | | : `- \`.;`\ _ /`;.`/ - ` : | | 27 | // \ \ `-. \_ __\ /__ _/ .-` / / 28 | // ======`-.____`-.___\_____/___.-`____.-'====== 29 | // `=---=' 30 | // 31 | // ............................................. 32 | // 佛祖镇楼 BUG辟易 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 | * 在使用 BAKit 的过程中如果出现 bug 请及时以以下任意一种方式联系我,我会及时修复 bug 63 | * 64 | * QQ : 可以添加ios开发技术群 479663605 在这里找到我(博爱1616【137361770】) 65 | * 微博 : 博爱1616 66 | * Email : 137361770@qq.com 67 | * GitHub : https://github.com/boai 68 | * BAHome : https://github.com/BAHome 69 | * 博客 : http://boaihome.com 70 | 71 | ********************************************************************************* 72 | 73 | */ 74 | 75 | #import 76 | #import "BAKit_Singleton.h" 77 | 78 | // Import required frameworks 79 | #import 80 | #import 81 | #import 82 | #import 83 | #import 84 | #import 85 | #import 86 | #import 87 | #import 88 | #import 89 | #import 90 | #import 91 | // 相册 92 | #import 93 | // 通知 94 | #import 95 | 96 | 97 | /** 98 | 隐私类型 99 | 100 | - BAKit_PrivacyType_None: 无 101 | - BAKit_PrivacyType_LocationServices: 定位 102 | - BAKit_PrivacyType_Contacts: 通讯录 103 | - BAKit_PrivacyType_Calendars: 日历 104 | - BAKit_PrivacyType_Reminders: 提醒事项 105 | - BAKit_PrivacyType_Photos: 照片 106 | - BAKit_PrivacyType_Camera: 相机 107 | - BAKit_PrivacyType_BluetoothSharing: 蓝牙共享 108 | - BAKit_PrivacyType_Microphone: 麦克风 109 | - BAKit_PrivacyType_SpeechRecognition: 语音识别 >= iOS 10.0 110 | - BAKit_PrivacyType_Health: 健康 >= iOS 8.0 111 | - BAKit_PrivacyType_HomeKit: 家庭 >= iOS 8.0 112 | - BAKit_PrivacyType_MediaAndAppleMusic: 媒体与 Apple Music >= iOS 9.3 113 | - BAKit_PrivacyType_MotionAndFitness: 运动与健身 114 | - BAKit_PrivacyType_MessageNotification: 消息通知 115 | */ 116 | typedef NS_ENUM(NSUInteger, BAKit_PrivacyType){ 117 | BAKit_PrivacyType_None = 0, 118 | BAKit_PrivacyType_LocationServices, 119 | BAKit_PrivacyType_Contacts, 120 | BAKit_PrivacyType_Calendars, 121 | BAKit_PrivacyType_Reminders, 122 | BAKit_PrivacyType_Photos, 123 | BAKit_PrivacyType_Camera, 124 | BAKit_PrivacyType_BluetoothSharing, 125 | BAKit_PrivacyType_Microphone, 126 | BAKit_PrivacyType_SpeechRecognition, 127 | BAKit_PrivacyType_Health, 128 | BAKit_PrivacyType_HomeKit, 129 | BAKit_PrivacyType_MediaAndAppleMusic, 130 | BAKit_PrivacyType_MotionAndFitness, 131 | BAKit_PrivacyType_MessageNotification, 132 | }; 133 | 134 | /** 135 | 权限状态,参考:PHAuthorizationStatus 等,可以根据返回的不同状态做相应的处理 136 | 137 | - BAKit_PrivacyStatus_NotDetermined: 用户从未进行过授权等处理,首次访问相应内容会提示用户进行授权 138 | - BAKit_PrivacyStatus_Authorized: 已授权 139 | - BAKit_PrivacyStatus_Denied: 拒绝 140 | - BAKit_PrivacyStatus_Restricted: 应用没有相关权限,且当前用户无法改变这个权限,比如:家长控制 141 | - BAKit_PrivacyStatus_NotSupport: 硬件等不支持 142 | */ 143 | typedef NS_ENUM(NSUInteger, BAKit_PrivacyStatus){ 144 | BAKit_PrivacyStatus_NotDetermined = 0, 145 | BAKit_PrivacyStatus_Authorized = 1, 146 | BAKit_PrivacyStatus_Denied = 2, 147 | BAKit_PrivacyStatus_Restricted = 3, 148 | BAKit_PrivacyStatus_NotSupport = 4, 149 | }; 150 | 151 | /** 152 | 定位权限状态,参考:CLAuthorizationStatus 153 | 154 | - BAKit_LocationAuthorizationStatus_NotDetermined: 用户从未进行过授权等处理,首次访问相应内容会提示用户进行授权 155 | - BAKit_LocationAuthorizationStatus_Authorized: 一直允许获取定位 ps:< iOS8用 156 | - BAKit_LocationAuthorizationStatus_Denied: 拒绝 157 | - BAKit_LocationAuthorizationStatus_Restricted: 应用没有相关权限,且当前用户无法改变这个权限,比如:家长控制 158 | - BAKit_LocationAuthorizationStatus_NotSupport: 硬件等不支持 159 | - BAKit_LocationAuthorizationStatus_AuthorizedAlways: 一直允许获取定位 160 | - BAKit_LocationAuthorizationStatus_AuthorizedWhenInUse: 在使用时允许获取定位 161 | */ 162 | typedef NS_ENUM(NSUInteger, BAKit_LocationAuthorizationStatus){ 163 | BAKit_LocationAuthorizationStatus_NotDetermined = 0, 164 | BAKit_LocationAuthorizationStatus_Authorized = 1, 165 | BAKit_LocationAuthorizationStatus_Denied = 2, 166 | BAKit_LocationAuthorizationStatus_Restricted = 3, 167 | BAKit_LocationAuthorizationStatus_NotSupport = 4, 168 | BAKit_LocationAuthorizationStatus_AuthorizedAlways = 5, 169 | BAKit_LocationAuthorizationStatus_AuthorizedWhenInUse = 6, 170 | }; 171 | 172 | /** 173 | 蓝牙连接状态,参考:CBManagerState 174 | 175 | - BAKit_CBManagerStatus_Unknown: 未知状态 176 | - BAKit_CBManagerStatus_Resetting: 正在重置,与系统服务暂时丢失 177 | - BAKit_CBManagerStatus_Unsupported: 不支持蓝牙 178 | - BAKit_CBManagerStatus_Unauthorized: 未授权 179 | - BAKit_CBManagerStatus_PoweredOff: 关闭 180 | - BAKit_CBManagerStatus_PoweredOn: 开启并可用 181 | */ 182 | typedef NS_ENUM(NSUInteger, BAKit_CBManagerStatus){ 183 | BAKit_CBManagerStatus_Unknown = 0, 184 | BAKit_CBManagerStatus_Resetting = 1, 185 | BAKit_CBManagerStatus_Unsupported = 2, 186 | BAKit_CBManagerStatus_Unauthorized = 3, 187 | BAKit_CBManagerStatus_PoweredOff = 4, 188 | BAKit_CBManagerStatus_PoweredOn = 5, 189 | }; 190 | 191 | /* 192 | 定义权限状态回调 block 193 | */ 194 | typedef void(^BAKit_PrivacyResultBlock)(BAKit_PrivacyStatus status, BAKit_PrivacyType type); 195 | 196 | /** 197 | 定位权限 block 198 | 199 | @param status 定位权限状态 200 | */ 201 | typedef void(^BAKit_PrivacyOfLocationResultBlock)(BAKit_LocationAuthorizationStatus status); 202 | 203 | /** 204 | 蓝牙连接状态 block 205 | 206 | @param status 蓝牙连接状态 207 | */ 208 | typedef void(^BAKit_PrivacyOfBluetoothResultBlock)(BAKit_CBManagerStatus status); 209 | 210 | /** 211 | 家庭状态 block 212 | 213 | @param isHaveHomeAccess HomeKit 状态 214 | */ 215 | typedef void(^BAKit_PrivacyOfHomeResultBlock)(BOOL isHaveHomeAccess); 216 | 217 | /** 218 | 运动与健身状态 block 219 | 220 | @param isHaveMotionAccess 运动与健身状态 221 | */ 222 | typedef void(^BAKit_PrivacyOfMotionResultBlock)(BOOL isHaveMotionAccess); 223 | 224 | /** 225 | 是否开启通知 226 | 227 | @param isOpenMessageNotification 开启通知状态 228 | @param type 通知类型 229 | */ 230 | typedef void(^BAKit_PrivacyOfMessageNotificationResultBlock)(BOOL isOpenMessageNotification, UIUserNotificationType type); 231 | 232 | #define BAPrivacyManagerShared [BAPrivacyManager sharedBAPrivacyManager] 233 | 234 | @interface BAPrivacyManager : NSObject 235 | BAKit_SingletonH(BAPrivacyManager) 236 | 237 | 238 | #pragma mark - checkAndRequestAccessForType 239 | - (void)ba_authorizationManagerCheckAccessForType:(BAKit_PrivacyType)type 240 | block:(BAKit_PrivacyResultBlock)block; 241 | 242 | #pragma mark - Contacts 243 | - (void)ba_checkAndRequestPrivacyOfContactsWithBlock:(BAKit_PrivacyResultBlock)block; 244 | 245 | #pragma mark - Calendars 246 | - (void)ba_checkAndRequestPrivacyOfCalendarsWithBlock:(BAKit_PrivacyResultBlock)block; 247 | 248 | #pragma mark - Reminders 249 | - (void)ba_checkAndRequestPrivacyOfRemindersWithBlock:(BAKit_PrivacyResultBlock)block; 250 | 251 | #pragma mark - Photos 252 | - (void)ba_checkAndRequestPrivacyOfPhotosWithBlock:(BAKit_PrivacyResultBlock)block; 253 | 254 | #pragma mark - Microphone 255 | - (void)ba_checkAndRequestPrivacyOfMicrophoneWithBlock:(BAKit_PrivacyResultBlock)block; 256 | 257 | #pragma mark - SpeechRecognition 258 | - (void)ba_checkAndRequestPrivacyOfSpeechRecognitionWithBlock:(BAKit_PrivacyResultBlock)block; 259 | 260 | #pragma mark - Camera 261 | - (void)ba_checkAndRequestPrivacyOfCameraWithBlock:(BAKit_PrivacyResultBlock)block; 262 | 263 | #pragma mark - Health,注意:需要证书支持 healthkit 264 | - (void)ba_checkAndRequestPrivacyOfHealthWithBlock:(BAKit_PrivacyResultBlock)block; 265 | 266 | #pragma mark - HomeKit,注意:需要证书支持 HomeKit 267 | - (void)ba_checkAndRequestPrivacyOfHomeWithBlock:(BAKit_PrivacyOfHomeResultBlock)block; 268 | 269 | #pragma mark - HMHomeManagerDelegate 270 | - (void)homeManagerDidUpdateHomes:(HMHomeManager *)manager; 271 | 272 | #pragma mark - MediaAndAppleMusic 273 | - (void)ba_checkAndRequestPrivacyOfAppleMusicWithBlock:(BAKit_PrivacyResultBlock)block; 274 | 275 | #pragma mark - MotionAndFitness 276 | - (void)ba_checkAndRequestPrivacyOfMotionAndFitness; 277 | 278 | #pragma mark - 通知权限监测 279 | - (void)ba_openMessageNotificationServiceWithBlock:(BAKit_PrivacyOfMessageNotificationResultBlock)block; 280 | 281 | #pragma mark - LocationServices 282 | - (void)ba_checkAndRequestPrivacyOfLocationServicesWithBlock:(BAKit_PrivacyOfLocationResultBlock)block; 283 | 284 | #pragma mark - BluetoothSharing 支持 iOS 10.0 以上 285 | - (void)ba_checkAndRequestPrivacyOfBluetoothSharingWithBlock:(BAKit_PrivacyOfBluetoothResultBlock)block; 286 | 287 | @end 288 | -------------------------------------------------------------------------------- /BAPrivacyManager/BAPrivacyManager/BAPrivacyManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // BAPrivacyManager.m 3 | // BAKit 4 | // 5 | // Created by boai on 2017/9/19. 6 | // Copyright © 2017年 boai. All rights reserved. 7 | // 8 | 9 | #import "BAPrivacyManager.h" 10 | #import "BAKit_ConfigurationDefine.h" 11 | 12 | @interface BAPrivacyManager () 13 | < 14 | CLLocationManagerDelegate, 15 | CBCentralManagerDelegate, 16 | HMHomeManagerDelegate, 17 | UINavigationControllerDelegate 18 | > 19 | 20 | /** 21 | 定位 22 | */ 23 | @property (nonatomic, strong) CLLocationManager *locationManager; 24 | 25 | /** 26 | 蓝牙 27 | */ 28 | @property (nonatomic, strong) CBCentralManager *cMgr; 29 | 30 | /** 31 | 健康 32 | */ 33 | @property (nonatomic, strong) HKHealthStore *healthStore; 34 | 35 | /** 36 | home 37 | */ 38 | @property (nonatomic, strong) HMHomeManager *homeManager; 39 | 40 | /** 41 | 运动 42 | */ 43 | @property (nonatomic, strong) CMMotionActivityManager *cmManager; 44 | 45 | @property (nonatomic, strong) NSOperationQueue *motionActivityQueue; 46 | 47 | @property (nonatomic,copy) void (^BAKit_CLCallBackBlock)(CLAuthorizationStatus state); 48 | @property (nonatomic,copy) void (^BAKit_CBManagerStateCallBackBlock)(CBManagerState state); 49 | @property (nonatomic,copy) void (^BAKit_HomeAccessCallBackBlock)(BOOL isHaveAccess); 50 | 51 | @end 52 | 53 | @implementation BAPrivacyManager 54 | BAKit_SingletonM(BAPrivacyManager) 55 | 56 | #pragma mark - checkAndRequestAccessForType 57 | - (void)ba_authorizationManagerCheckAccessForType:(BAKit_PrivacyType)type 58 | block:(BAKit_PrivacyResultBlock)block 59 | { 60 | switch (type) { 61 | case BAKit_PrivacyType_LocationServices: 62 | { 63 | NSLog(@"此方法暂时不适用 定位监测,请使用 【ba_checkAndRequestPrivacyOfLocationServicesWithBlock】方法监测"); 64 | } 65 | break; 66 | case BAKit_PrivacyType_Contacts: 67 | { 68 | [self ba_checkAndRequestPrivacyOfContactsWithBlock:block]; 69 | } 70 | break; 71 | case BAKit_PrivacyType_Calendars: 72 | { 73 | [self ba_checkAndRequestPrivacyOfCalendarsWithBlock:block]; 74 | } 75 | break; 76 | case BAKit_PrivacyType_Reminders: 77 | { 78 | [self ba_checkAndRequestPrivacyOfRemindersWithBlock:block]; 79 | } 80 | break; 81 | case BAKit_PrivacyType_Photos: 82 | { 83 | [self ba_checkAndRequestPrivacyOfPhotosWithBlock:block]; 84 | } 85 | break; 86 | case BAKit_PrivacyType_BluetoothSharing: 87 | { 88 | NSLog(@"此方法暂时不适用 蓝牙监测,请使用 【ba_checkAndRequestPrivacyOfBluetoothSharingWithBlock】方法监测"); 89 | } 90 | break; 91 | case BAKit_PrivacyType_Microphone: 92 | { 93 | [self ba_checkAndRequestPrivacyOfMicrophoneWithBlock:block]; 94 | } 95 | break; 96 | case BAKit_PrivacyType_SpeechRecognition: 97 | { 98 | [self ba_checkAndRequestPrivacyOfSpeechRecognitionWithBlock:block]; 99 | } 100 | break; 101 | case BAKit_PrivacyType_Camera: 102 | { 103 | [self ba_checkAndRequestPrivacyOfCameraWithBlock:block]; 104 | } 105 | break; 106 | case BAKit_PrivacyType_Health: 107 | { 108 | [self ba_checkAndRequestPrivacyOfHealthWithBlock:block]; 109 | } 110 | break; 111 | case BAKit_PrivacyType_HomeKit: 112 | { 113 | NSLog(@"此方法暂时不适用 健康监测,请使用 【ba_checkAndRequestPrivacyOfHome】方法监测"); 114 | } 115 | break; 116 | case BAKit_PrivacyType_MediaAndAppleMusic: 117 | { 118 | [self ba_checkAndRequestPrivacyOfAppleMusicWithBlock:block]; 119 | } 120 | break; 121 | case BAKit_PrivacyType_MotionAndFitness: 122 | { 123 | [self ba_checkAndRequestPrivacyOfMotionAndFitness]; 124 | } 125 | break; 126 | case BAKit_PrivacyType_None: 127 | { 128 | 129 | } 130 | break; 131 | 132 | default: 133 | break; 134 | } 135 | } 136 | 137 | #pragma mark - Contacts 138 | - (void)ba_checkAndRequestPrivacyOfContactsWithBlock:(BAKit_PrivacyResultBlock)block 139 | { 140 | if (BAKit_isIOS9_Or_Later) 141 | { 142 | CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts]; 143 | 144 | switch (status) { 145 | case CNAuthorizationStatusNotDetermined: 146 | { 147 | CNContactStore *contactStore = [[CNContactStore alloc] init]; 148 | if (contactStore == NULL) 149 | { 150 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_NotSupport privacyType:BAKit_PrivacyType_Contacts]; 151 | } 152 | [contactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) { 153 | 154 | if (error) { 155 | NSLog(@"error:%@",error); 156 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_NotSupport privacyType:BAKit_PrivacyType_Contacts]; 157 | }else{ 158 | if (granted) { 159 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Authorized privacyType:BAKit_PrivacyType_Contacts]; 160 | }else{ 161 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Denied privacyType:BAKit_PrivacyType_Contacts]; 162 | } 163 | } 164 | }]; 165 | } 166 | break; 167 | case CNAuthorizationStatusRestricted: 168 | { 169 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Restricted privacyType:BAKit_PrivacyType_Contacts]; 170 | } 171 | break; 172 | case CNAuthorizationStatusDenied: 173 | { 174 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Denied privacyType:BAKit_PrivacyType_Contacts]; 175 | } 176 | break; 177 | case CNAuthorizationStatusAuthorized: 178 | { 179 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Authorized privacyType:BAKit_PrivacyType_Contacts]; 180 | } 181 | break; 182 | 183 | default: 184 | break; 185 | } 186 | } 187 | else 188 | { 189 | ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus(); 190 | switch (status) { 191 | case kABAuthorizationStatusNotDetermined: 192 | { 193 | __block ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL); 194 | if (addressBookRef == NULL) 195 | { 196 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_NotSupport privacyType:BAKit_PrivacyType_Contacts]; 197 | } 198 | 199 | ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) { 200 | if (granted) 201 | { 202 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Authorized privacyType:BAKit_PrivacyType_Contacts]; 203 | } 204 | else 205 | { 206 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Denied privacyType:BAKit_PrivacyType_Contacts]; 207 | } 208 | if (addressBookRef) 209 | { 210 | CFRelease(addressBookRef); 211 | addressBookRef = NULL; 212 | } 213 | }); 214 | } 215 | break; 216 | case kABAuthorizationStatusRestricted: 217 | { 218 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Restricted privacyType:BAKit_PrivacyType_Contacts]; 219 | } 220 | break; 221 | case kABAuthorizationStatusDenied: 222 | { 223 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Denied privacyType:BAKit_PrivacyType_Contacts]; 224 | } 225 | break; 226 | case kABAuthorizationStatusAuthorized: 227 | { 228 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Authorized privacyType:BAKit_PrivacyType_Contacts]; 229 | } 230 | break; 231 | 232 | default: 233 | break; 234 | } 235 | } 236 | } 237 | 238 | #pragma mark - Calendars 239 | - (void)ba_checkAndRequestPrivacyOfCalendarsWithBlock:(BAKit_PrivacyResultBlock)block 240 | { 241 | EKAuthorizationStatus status = [EKEventStore authorizationStatusForEntityType:EKEntityTypeEvent]; 242 | 243 | switch (status) { 244 | case EKAuthorizationStatusNotDetermined: 245 | { 246 | EKEventStore *store = [[EKEventStore alloc] init]; 247 | if (store == NULL) 248 | { 249 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_NotSupport privacyType:BAKit_PrivacyType_Calendars]; 250 | } 251 | else 252 | { 253 | [store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError * _Nullable error) { 254 | if (error) 255 | { 256 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Denied privacyType:BAKit_PrivacyType_Calendars]; 257 | NSLog(@"erro:%@",error); 258 | } 259 | if (granted) 260 | { 261 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Authorized privacyType:BAKit_PrivacyType_Calendars]; 262 | } 263 | else 264 | { 265 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Denied privacyType:BAKit_PrivacyType_Calendars]; 266 | } 267 | }]; 268 | } 269 | } 270 | break; 271 | case EKAuthorizationStatusRestricted: 272 | { 273 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Restricted privacyType:BAKit_PrivacyType_Calendars]; 274 | } 275 | break; 276 | case EKAuthorizationStatusDenied: 277 | { 278 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Denied privacyType:BAKit_PrivacyType_Calendars]; 279 | } 280 | break; 281 | case EKAuthorizationStatusAuthorized: 282 | { 283 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Authorized privacyType:BAKit_PrivacyType_Calendars]; 284 | } 285 | break; 286 | 287 | default: 288 | break; 289 | } 290 | } 291 | 292 | #pragma mark - Reminders 293 | - (void)ba_checkAndRequestPrivacyOfRemindersWithBlock:(BAKit_PrivacyResultBlock)block 294 | { 295 | EKAuthorizationStatus status = [EKEventStore authorizationStatusForEntityType:EKEntityTypeReminder]; 296 | 297 | if (status == EKAuthorizationStatusNotDetermined) { 298 | EKEventStore *store = [[EKEventStore alloc] init]; 299 | if (store == NULL) { 300 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_NotSupport privacyType:BAKit_PrivacyType_Reminders]; 301 | 302 | }else{ 303 | [store requestAccessToEntityType:EKEntityTypeReminder completion:^(BOOL granted, NSError * _Nullable error) { 304 | if (error) { 305 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Denied privacyType:BAKit_PrivacyType_Reminders]; 306 | 307 | NSLog(@"erro:%@",error); 308 | } 309 | if (granted) { 310 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Authorized privacyType:BAKit_PrivacyType_Reminders]; 311 | 312 | }else{ 313 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Denied privacyType:BAKit_PrivacyType_Reminders]; 314 | } 315 | }]; 316 | } 317 | 318 | } else if (status == EKAuthorizationStatusRestricted) { 319 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Restricted privacyType:BAKit_PrivacyType_Reminders]; 320 | 321 | } else if (status == EKAuthorizationStatusDenied) { 322 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Denied privacyType:BAKit_PrivacyType_Reminders]; 323 | 324 | } else { 325 | // EKAuthorizationStatusAuthorized 326 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Authorized privacyType:BAKit_PrivacyType_Reminders]; 327 | } 328 | } 329 | 330 | #pragma mark - Photos 331 | - (void)ba_checkAndRequestPrivacyOfPhotosWithBlock:(BAKit_PrivacyResultBlock)block 332 | { 333 | if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) 334 | { 335 | if (BAKit_isIOS8_Or_Later) 336 | { 337 | PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus]; 338 | 339 | switch (status) { 340 | case PHAuthorizationStatusNotDetermined: 341 | { 342 | [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) { 343 | if (status == PHAuthorizationStatusNotDetermined) { 344 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_NotDetermined privacyType:BAKit_PrivacyType_Photos]; 345 | 346 | } else if (status == PHAuthorizationStatusRestricted) { 347 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Restricted privacyType:BAKit_PrivacyType_Photos]; 348 | 349 | } else if (status == PHAuthorizationStatusDenied) { 350 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Denied privacyType:BAKit_PrivacyType_Photos]; 351 | 352 | } else { 353 | // PHAuthorizationStatusAuthorized 354 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Authorized privacyType:BAKit_PrivacyType_Photos]; 355 | } 356 | }]; 357 | } 358 | break; 359 | case PHAuthorizationStatusRestricted: 360 | { 361 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Restricted privacyType:BAKit_PrivacyType_Photos]; 362 | } 363 | break; 364 | case PHAuthorizationStatusDenied: 365 | { 366 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Denied privacyType:BAKit_PrivacyType_Photos]; 367 | } 368 | break; 369 | case PHAuthorizationStatusAuthorized: 370 | { 371 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Authorized privacyType:BAKit_PrivacyType_Photos]; 372 | } 373 | break; 374 | 375 | default: 376 | break; 377 | } 378 | } 379 | else 380 | { 381 | // iOS7 - iOS8 382 | ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus]; 383 | 384 | switch (status) { 385 | case ALAuthorizationStatusNotDetermined: 386 | { 387 | // 当某些情况下,ALAuthorizationStatus 为 ALAuthorizationStatusNotDetermined的时候,无法弹出系统首次使用的收取alertView,系统设置中也没有相册的设置,此时将无法使用,所以做以下操作,弹出系统首次使用的授权alertView 388 | __block BOOL isShow = YES; 389 | ALAssetsLibrary *assetLibrary = [[ALAssetsLibrary alloc] init]; 390 | [assetLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) { 391 | if (isShow) { 392 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Authorized privacyType:BAKit_PrivacyType_Photos]; 393 | isShow = NO; 394 | } 395 | } failureBlock:^(NSError *error) { 396 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Denied privacyType:BAKit_PrivacyType_Photos]; 397 | }]; 398 | } 399 | break; 400 | case ALAuthorizationStatusRestricted: 401 | { 402 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Restricted privacyType:BAKit_PrivacyType_Photos]; 403 | } 404 | break; 405 | case ALAuthorizationStatusDenied: 406 | { 407 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Denied privacyType:BAKit_PrivacyType_Photos]; 408 | } 409 | break; 410 | case ALAuthorizationStatusAuthorized: 411 | { 412 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Authorized privacyType:BAKit_PrivacyType_Photos]; 413 | } 414 | break; 415 | 416 | default: 417 | break; 418 | } 419 | } 420 | } 421 | else 422 | { 423 | NSLog(@"相册不可用!"); 424 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_NotSupport privacyType:BAKit_PrivacyType_Photos]; 425 | } 426 | } 427 | 428 | #pragma mark - BluetoothSharing 429 | - (void)ba_checkAndRequestPrivacyOfBluetoothSharingWithBlock:(BAKit_PrivacyOfBluetoothResultBlock)block 430 | { 431 | self.cMgr = [[CBCentralManager alloc] initWithDelegate:self queue:nil]; 432 | BAKit_WeakSelf 433 | 434 | 435 | if (@available(iOS 10.0, *)) { 436 | [self setBAKit_CBManagerStateCallBackBlock:^(CBManagerState status){ 437 | BAKit_StrongSelf 438 | 439 | switch (status) { 440 | case CBManagerStateResetting: 441 | { 442 | [self ba_executeBluetoothSharingWithBlock:block CBManagerStatus:BAKit_CBManagerStatus_Resetting privacyType:BAKit_PrivacyType_BluetoothSharing]; 443 | } 444 | break; 445 | case CBManagerStateUnsupported: 446 | { 447 | [self ba_executeBluetoothSharingWithBlock:block CBManagerStatus:BAKit_CBManagerStatus_Unsupported privacyType:BAKit_PrivacyType_BluetoothSharing]; 448 | } 449 | break; 450 | case CBManagerStateUnauthorized: 451 | { 452 | [self ba_executeBluetoothSharingWithBlock:block CBManagerStatus:BAKit_CBManagerStatus_Unauthorized privacyType:BAKit_PrivacyType_BluetoothSharing]; 453 | } 454 | break; 455 | case CBManagerStatePoweredOff: 456 | { 457 | [self ba_executeBluetoothSharingWithBlock:block CBManagerStatus:BAKit_CBManagerStatus_PoweredOff privacyType:BAKit_PrivacyType_BluetoothSharing]; 458 | } 459 | break; 460 | case CBManagerStatePoweredOn: 461 | { 462 | [self ba_executeBluetoothSharingWithBlock:block CBManagerStatus:BAKit_CBManagerStatus_PoweredOn privacyType:BAKit_PrivacyType_BluetoothSharing]; 463 | } 464 | break; 465 | case CBManagerStateUnknown: 466 | { 467 | [self ba_executeBluetoothSharingWithBlock:block CBManagerStatus:BAKit_CBManagerStatus_Unknown privacyType:BAKit_PrivacyType_BluetoothSharing]; 468 | } 469 | break; 470 | 471 | default: 472 | break; 473 | } 474 | 475 | }]; 476 | } else { 477 | // Fallback on earlier versions 478 | } 479 | } 480 | 481 | #pragma mark CBCentralManagerDelegate 482 | - (void)centralManagerDidUpdateState:(CBCentralManager *)central 483 | { 484 | if (self.BAKit_CBManagerStateCallBackBlock) 485 | { 486 | self.BAKit_CBManagerStateCallBackBlock(central.state); 487 | } 488 | } 489 | 490 | #pragma mark - Microphone 491 | - (void)ba_checkAndRequestPrivacyOfMicrophoneWithBlock:(BAKit_PrivacyResultBlock)block 492 | { 493 | AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio]; 494 | 495 | BAKit_WeakSelf 496 | switch (status) { 497 | case AVAuthorizationStatusNotDetermined: 498 | { 499 | [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) { 500 | BAKit_StrongSelf 501 | if (granted) 502 | { 503 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Authorized privacyType:BAKit_PrivacyType_Microphone]; 504 | } 505 | else 506 | { 507 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Denied privacyType:BAKit_PrivacyType_Microphone]; 508 | } 509 | }]; 510 | } 511 | break; 512 | case AVAuthorizationStatusRestricted: 513 | { 514 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Restricted privacyType:BAKit_PrivacyType_Microphone]; 515 | } 516 | break; 517 | case AVAuthorizationStatusDenied: 518 | { 519 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Denied privacyType:BAKit_PrivacyType_Microphone]; 520 | } 521 | break; 522 | case AVAuthorizationStatusAuthorized: 523 | { 524 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Authorized privacyType:BAKit_PrivacyType_Microphone]; 525 | } 526 | break; 527 | 528 | default: 529 | break; 530 | } 531 | } 532 | 533 | #pragma mark - SpeechRecognition 534 | - (void)ba_checkAndRequestPrivacyOfSpeechRecognitionWithBlock:(BAKit_PrivacyResultBlock)block 535 | { 536 | if (BAKit_isIOS10_Or_Later) 537 | { 538 | if (@available(iOS 10.0, *)) { 539 | SFSpeechRecognizerAuthorizationStatus status = [SFSpeechRecognizer authorizationStatus]; 540 | 541 | switch (status) { 542 | case SFSpeechRecognizerAuthorizationStatusNotDetermined: 543 | { 544 | [SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status) { 545 | 546 | if (status == SFSpeechRecognizerAuthorizationStatusNotDetermined) { 547 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_NotDetermined privacyType:BAKit_PrivacyType_SpeechRecognition]; 548 | 549 | } else if (status == SFSpeechRecognizerAuthorizationStatusDenied) { 550 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Denied privacyType:BAKit_PrivacyType_SpeechRecognition]; 551 | 552 | } else if (status == SFSpeechRecognizerAuthorizationStatusRestricted) { 553 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Restricted privacyType:BAKit_PrivacyType_SpeechRecognition]; 554 | 555 | } else { 556 | // SFSpeechRecognizerAuthorizationStatusAuthorized 557 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Authorized privacyType:BAKit_PrivacyType_SpeechRecognition]; 558 | } 559 | }]; 560 | } 561 | break; 562 | case SFSpeechRecognizerAuthorizationStatusDenied: 563 | { 564 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Denied privacyType:BAKit_PrivacyType_SpeechRecognition]; 565 | } 566 | break; 567 | case SFSpeechRecognizerAuthorizationStatusRestricted: 568 | { 569 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Restricted privacyType:BAKit_PrivacyType_SpeechRecognition]; 570 | } 571 | break; 572 | case SFSpeechRecognizerAuthorizationStatusAuthorized: 573 | { 574 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Authorized privacyType:BAKit_PrivacyType_SpeechRecognition]; 575 | } 576 | break; 577 | 578 | default: 579 | break; 580 | } 581 | } else { 582 | // Fallback on earlier versions 583 | } 584 | } 585 | else 586 | { 587 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_NotSupport privacyType:BAKit_PrivacyType_SpeechRecognition]; 588 | } 589 | } 590 | 591 | #pragma mark - Camera 592 | - (void)ba_checkAndRequestPrivacyOfCameraWithBlock:(BAKit_PrivacyResultBlock)block 593 | { 594 | if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { 595 | 596 | AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]; 597 | 598 | switch (status) { 599 | case AVAuthorizationStatusNotDetermined: 600 | { 601 | [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) { 602 | if (granted) 603 | { 604 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Authorized privacyType:BAKit_PrivacyType_Camera]; 605 | } 606 | else 607 | { 608 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Denied privacyType:BAKit_PrivacyType_Camera]; 609 | } 610 | }]; 611 | } 612 | break; 613 | case AVAuthorizationStatusRestricted: 614 | { 615 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Restricted privacyType:BAKit_PrivacyType_Camera]; 616 | } 617 | break; 618 | case AVAuthorizationStatusDenied: 619 | { 620 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Denied privacyType:BAKit_PrivacyType_Camera]; 621 | } 622 | break; 623 | case AVAuthorizationStatusAuthorized: 624 | { 625 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Authorized privacyType:BAKit_PrivacyType_Camera]; 626 | } 627 | break; 628 | 629 | default: 630 | break; 631 | } 632 | } 633 | else 634 | { 635 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_NotSupport privacyType:BAKit_PrivacyType_Camera]; 636 | } 637 | } 638 | 639 | #pragma mark - Health 640 | - (void)ba_checkAndRequestPrivacyOfHealthWithBlock:(BAKit_PrivacyResultBlock)block 641 | { 642 | if (BAKit_isIOS8_Or_Later) 643 | { 644 | if ([HKHealthStore isHealthDataAvailable]) 645 | { 646 | if (!self.healthStore) 647 | { 648 | self.healthStore = [[HKHealthStore alloc] init]; 649 | } 650 | 651 | // 以心率 HKQuantityTypeIdentifierHeartRate 为例子 652 | HKQuantityType *heartRateType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate]; 653 | HKAuthorizationStatus status = [self.healthStore authorizationStatusForType:heartRateType]; 654 | 655 | switch (status) { 656 | case HKAuthorizationStatusNotDetermined: 657 | { 658 | NSSet *typeSet = [NSSet setWithObject:heartRateType]; 659 | 660 | [self.healthStore requestAuthorizationToShareTypes:typeSet readTypes:typeSet completion:^(BOOL success, NSError * _Nullable error) { 661 | 662 | // tips:这个block不止在用户点击允许或者不允许的时候响应,在弹出访问健康数据允许窗口后,只要界面发生变化(以及程序进入后台),都会响应该block。 663 | // sucess 为YES代表用户响应了该界面,允许或者拒绝 664 | if (success) 665 | { 666 | // 由于用户已经响该界面(不管是允许或者拒绝) 667 | // 并且这时候应该只会有两种状态:HKAuthorizationStatusSharingAuthorized 或者 HKAuthorizationStatusSharingDenied 668 | HKAuthorizationStatus status = [self.healthStore authorizationStatusForType:heartRateType]; 669 | if (status == HKAuthorizationStatusNotDetermined) 670 | { 671 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_NotDetermined privacyType:BAKit_PrivacyType_Health]; 672 | } 673 | else if (status == HKAuthorizationStatusSharingAuthorized) 674 | { 675 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Authorized privacyType:BAKit_PrivacyType_Health]; 676 | } 677 | else 678 | { 679 | // HKAuthorizationStatusSharingDenied 680 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Denied privacyType:BAKit_PrivacyType_Health]; 681 | } 682 | } 683 | else 684 | { 685 | if (error) 686 | { 687 | NSLog(@"requestHealthAuthorization: error:%@",error); 688 | } 689 | } 690 | }]; 691 | } 692 | break; 693 | case HKAuthorizationStatusSharingDenied: 694 | { 695 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Denied privacyType:BAKit_PrivacyType_Health]; 696 | } 697 | break; 698 | case HKAuthorizationStatusSharingAuthorized: 699 | { 700 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Authorized privacyType:BAKit_PrivacyType_Health]; 701 | } 702 | break; 703 | 704 | default: 705 | break; 706 | } 707 | 708 | } 709 | else 710 | { 711 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_NotSupport privacyType:BAKit_PrivacyType_Health]; 712 | NSLog(@"unavailable"); 713 | // Health data is not avaliable on all device. 714 | } 715 | } 716 | else 717 | { 718 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_NotSupport privacyType:BAKit_PrivacyType_Health]; 719 | NSLog(@"iOS8以下不支持"); 720 | } 721 | } 722 | 723 | #pragma mark - HomeKit 724 | - (void)ba_checkAndRequestPrivacyOfHomeWithBlock:(BAKit_PrivacyOfHomeResultBlock)block 725 | { 726 | if (BAKit_isIOS8_Or_Later) 727 | { 728 | if (!self.homeManager) 729 | { 730 | self.homeManager = [[HMHomeManager alloc] init]; 731 | self.homeManager.delegate = self; 732 | } 733 | [self setBAKit_HomeAccessCallBackBlock:^(BOOL isHaveAccess){ 734 | if (block) 735 | { 736 | block(isHaveAccess); 737 | } 738 | }]; 739 | } 740 | else 741 | { 742 | NSLog(@"The home is available on ios8 or later"); 743 | } 744 | } 745 | 746 | #pragma mark - HMHomeManagerDelegate 747 | - (void)homeManagerDidUpdateHomes:(HMHomeManager *)manager 748 | { 749 | if (manager.homes.count > 0) 750 | { 751 | NSLog(@"A home exists, so we have access."); 752 | if (self.BAKit_HomeAccessCallBackBlock) 753 | { 754 | self.BAKit_HomeAccessCallBackBlock(YES); 755 | } 756 | } 757 | else 758 | { 759 | __weak HMHomeManager *weakHomeManager = manager; 760 | [manager addHomeWithName:@"Test Home" completionHandler:^(HMHome * _Nullable home, NSError * _Nullable error) { 761 | 762 | if (!error) 763 | { 764 | NSLog(@"We have access for home."); 765 | if (self.BAKit_HomeAccessCallBackBlock) 766 | { 767 | self.BAKit_HomeAccessCallBackBlock(YES); 768 | } 769 | } 770 | else 771 | 772 | { 773 | // tips:出现错误,错误类型参考 HMError.h 774 | if (error.code == HMErrorCodeHomeAccessNotAuthorized) 775 | { 776 | // User denied permission. 777 | NSLog(@"用户拒绝!!"); 778 | } 779 | else 780 | { 781 | NSLog(@"HOME_ERROR:%ld,%@",error.code, error.localizedDescription); 782 | } 783 | if (self.BAKit_HomeAccessCallBackBlock) 784 | { 785 | self.BAKit_HomeAccessCallBackBlock(YES); 786 | } 787 | } 788 | 789 | if (home) 790 | { 791 | [weakHomeManager removeHome:home completionHandler:^(NSError * _Nullable error) { 792 | // ... do something with the result of removing the home ... 793 | }]; 794 | } 795 | }]; 796 | } 797 | } 798 | 799 | #pragma mark - MediaAndAppleMusic 800 | - (void)ba_checkAndRequestPrivacyOfAppleMusicWithBlock:(BAKit_PrivacyResultBlock)block 801 | { 802 | if (@available(iOS 9.3, *)) 803 | { 804 | SKCloudServiceAuthorizationStatus status = [SKCloudServiceController authorizationStatus]; 805 | 806 | if (@available(iOS 9.3, *)) 807 | { 808 | if (status == SKCloudServiceAuthorizationStatusNotDetermined) 809 | { 810 | if (@available(iOS 9.3, *)) 811 | { 812 | [SKCloudServiceController requestAuthorization:^(SKCloudServiceAuthorizationStatus status) { 813 | switch (status) { 814 | case SKCloudServiceAuthorizationStatusNotDetermined: 815 | { 816 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_NotDetermined privacyType:BAKit_PrivacyType_MediaAndAppleMusic]; 817 | } 818 | break; 819 | case SKCloudServiceAuthorizationStatusRestricted: 820 | { 821 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Restricted privacyType:BAKit_PrivacyType_MediaAndAppleMusic]; 822 | } 823 | break; 824 | case SKCloudServiceAuthorizationStatusDenied: 825 | { 826 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Denied privacyType:BAKit_PrivacyType_MediaAndAppleMusic]; 827 | } 828 | break; 829 | case SKCloudServiceAuthorizationStatusAuthorized: 830 | { 831 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Authorized privacyType:BAKit_PrivacyType_MediaAndAppleMusic]; 832 | } 833 | break; 834 | default: 835 | break; 836 | } 837 | }]; 838 | } 839 | else 840 | { 841 | // Fallback on earlier versions 842 | } 843 | } 844 | else if (status == SKCloudServiceAuthorizationStatusRestricted) 845 | { 846 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Restricted privacyType:BAKit_PrivacyType_MediaAndAppleMusic]; 847 | } 848 | else if (status == SKCloudServiceAuthorizationStatusDenied) 849 | { 850 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Denied privacyType:BAKit_PrivacyType_MediaAndAppleMusic]; 851 | } 852 | 853 | } 854 | 855 | else 856 | { 857 | // SKCloudServiceAuthorizationStatusAuthorized 858 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_Authorized privacyType:BAKit_PrivacyType_MediaAndAppleMusic]; 859 | } 860 | } 861 | else 862 | { 863 | [self ba_executePrivacyBlock:block privacyStatus:BAKit_PrivacyStatus_NotSupport privacyType:BAKit_PrivacyType_MediaAndAppleMusic]; 864 | NSLog(@"AppleMusic只支持iOS9.3+"); 865 | } 866 | } 867 | 868 | #pragma mark - MotionAndFitness 869 | - (void)ba_checkAndRequestPrivacyOfMotionAndFitness 870 | { 871 | self.cmManager = [[CMMotionActivityManager alloc] init]; 872 | self.motionActivityQueue = [[NSOperationQueue alloc] init]; 873 | [self.cmManager startActivityUpdatesToQueue:self.motionActivityQueue withHandler:^(CMMotionActivity *activity) { 874 | 875 | [self.cmManager stopActivityUpdates]; 876 | 877 | NSLog(@"We have access for MotionAndFitness."); 878 | }]; 879 | 880 | NSLog(@"We don't have permission to MotionAndFitness."); 881 | } 882 | 883 | - (void)ba_openMessageNotificationServiceWithBlock:(BAKit_PrivacyOfMessageNotificationResultBlock)block 884 | { 885 | BOOL isOpen = NO; 886 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0 887 | UIUserNotificationSettings *setting = [[UIApplication sharedApplication] currentUserNotificationSettings]; 888 | 889 | UIUserNotificationType type = setting.types; 890 | if (setting.types != UIUserNotificationTypeNone) 891 | { 892 | isOpen = YES; 893 | } 894 | if (block) 895 | { 896 | block(isOpen, type); 897 | } 898 | #else 899 | 900 | #endif 901 | 902 | } 903 | 904 | #pragma mark - LocationServices 905 | - (void)ba_checkAndRequestPrivacyOfLocationServicesWithBlock:(BAKit_PrivacyOfLocationResultBlock)block 906 | { 907 | BOOL isLocationServicesEnabled = [CLLocationManager locationServicesEnabled]; 908 | if (!isLocationServicesEnabled) 909 | { 910 | NSLog(@"定位服务不可用,例如定位没有打开..."); 911 | [self ba_executeLocationServicesWithBlock:block locationAuthorizationStatus:BAKit_LocationAuthorizationStatus_NotSupport privacyType:BAKit_PrivacyType_LocationServices]; 912 | } 913 | else 914 | { 915 | CLAuthorizationStatus status = [CLLocationManager authorizationStatus]; 916 | 917 | switch (status) { 918 | case kCLAuthorizationStatusNotDetermined: 919 | { 920 | self.locationManager = [[CLLocationManager alloc] init]; 921 | self.locationManager.delegate = self; 922 | 923 | // 两种定位模式 924 | [self.locationManager requestWhenInUseAuthorization]; 925 | BAKit_WeakSelf 926 | [self setBAKit_CLCallBackBlock:^(CLAuthorizationStatus state) { 927 | BAKit_StrongSelf 928 | if (status == kCLAuthorizationStatusNotDetermined) 929 | { 930 | [self ba_executeLocationServicesWithBlock:block locationAuthorizationStatus:BAKit_LocationAuthorizationStatus_NotDetermined privacyType:BAKit_PrivacyType_LocationServices]; 931 | } 932 | else if (status == kCLAuthorizationStatusRestricted) 933 | { 934 | [self ba_executeLocationServicesWithBlock:block locationAuthorizationStatus:BAKit_LocationAuthorizationStatus_Restricted privacyType:BAKit_PrivacyType_LocationServices]; 935 | } 936 | else if (status == kCLAuthorizationStatusDenied) 937 | { 938 | [self ba_executeLocationServicesWithBlock:block locationAuthorizationStatus:BAKit_LocationAuthorizationStatus_Restricted privacyType:BAKit_PrivacyType_LocationServices]; 939 | } 940 | else if (status == kCLAuthorizationStatusAuthorizedAlways) 941 | { 942 | [self ba_executeLocationServicesWithBlock:block locationAuthorizationStatus:BAKit_LocationAuthorizationStatus_AuthorizedAlways privacyType:BAKit_PrivacyType_LocationServices]; 943 | } 944 | else if (status == kCLAuthorizationStatusAuthorizedWhenInUse) 945 | { 946 | [self ba_executeLocationServicesWithBlock:block locationAuthorizationStatus:BAKit_LocationAuthorizationStatus_AuthorizedWhenInUse privacyType:BAKit_PrivacyType_LocationServices]; 947 | } 948 | else 949 | { 950 | // kCLAuthorizationStatusAuthorized < ios8 951 | [self ba_executeLocationServicesWithBlock:block locationAuthorizationStatus:BAKit_LocationAuthorizationStatus_Authorized privacyType:BAKit_PrivacyType_LocationServices]; 952 | } 953 | }]; 954 | } 955 | break; 956 | 957 | case kCLAuthorizationStatusRestricted: 958 | { 959 | [self ba_executeLocationServicesWithBlock:block locationAuthorizationStatus:BAKit_LocationAuthorizationStatus_Restricted privacyType:BAKit_PrivacyType_LocationServices]; 960 | } 961 | break; 962 | 963 | case kCLAuthorizationStatusDenied: 964 | { 965 | [self ba_executeLocationServicesWithBlock:block locationAuthorizationStatus:BAKit_LocationAuthorizationStatus_Restricted privacyType:BAKit_PrivacyType_LocationServices]; 966 | } 967 | break; 968 | 969 | case kCLAuthorizationStatusAuthorizedAlways: 970 | { 971 | [self ba_executeLocationServicesWithBlock:block locationAuthorizationStatus:BAKit_LocationAuthorizationStatus_AuthorizedAlways privacyType:BAKit_PrivacyType_LocationServices]; 972 | } 973 | break; 974 | 975 | case kCLAuthorizationStatusAuthorizedWhenInUse: 976 | { 977 | [self ba_executeLocationServicesWithBlock:block locationAuthorizationStatus:BAKit_LocationAuthorizationStatus_AuthorizedWhenInUse privacyType:BAKit_PrivacyType_LocationServices]; 978 | } 979 | break; 980 | 981 | default: 982 | break; 983 | } 984 | } 985 | } 986 | 987 | #pragma mark - CLLocationManagerDelegate 988 | - (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status 989 | { 990 | if (self.BAKit_CLCallBackBlock) 991 | { 992 | self.BAKit_CLCallBackBlock(status); 993 | } 994 | } 995 | 996 | #pragma mark - PrivacyStatus 权限回调 block 997 | - (void)ba_executePrivacyBlock:(BAKit_PrivacyResultBlock)block 998 | privacyStatus:(BAKit_PrivacyStatus)privacyStatus 999 | privacyType:(BAKit_PrivacyType)privacyType 1000 | { 1001 | dispatch_async(dispatch_get_main_queue(), ^{ 1002 | if (block) 1003 | { 1004 | block(privacyStatus, privacyType); 1005 | } 1006 | }); 1007 | } 1008 | 1009 | #pragma mark - Location Services CallBack 1010 | - (void)ba_executeLocationServicesWithBlock:(BAKit_PrivacyOfLocationResultBlock)block locationAuthorizationStatus:(BAKit_LocationAuthorizationStatus)locationAuthorizationStatus privacyType:(BAKit_PrivacyType)privacyType 1011 | { 1012 | dispatch_async(dispatch_get_main_queue(), ^{ 1013 | if (block) 1014 | { 1015 | block(locationAuthorizationStatus); 1016 | } 1017 | }); 1018 | } 1019 | 1020 | #pragma mark - Bluetooth Sharing CallBack 1021 | - (void)ba_executeBluetoothSharingWithBlock:(BAKit_PrivacyOfBluetoothResultBlock)block CBManagerStatus:(BAKit_CBManagerStatus)CBManagerStatus privacyType:(BAKit_PrivacyType)privacyType 1022 | { 1023 | dispatch_async(dispatch_get_main_queue(), ^{ 1024 | if (block) 1025 | { 1026 | block(CBManagerStatus); 1027 | } 1028 | }); 1029 | } 1030 | 1031 | @end 1032 | -------------------------------------------------------------------------------- /BAPrivacyManager/BAPrivacyManager/BAPrivacyManager_Version.h: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | * @header BAKit.h 4 | * 5 | * @brief BAKit 6 | * 7 | * @author 博爱 8 | * @copyright Copyright © 2016年 博爱. All rights reserved. 9 | * @version V1.0 10 | */ 11 | 12 | // _ooOoo_ 13 | // o8888888o 14 | // 88" . "88 15 | // (| -_- |) 16 | // O\ = /O 17 | // ____/`---'\____ 18 | // . ' \\| |// `. 19 | // / \\||| : |||// \ 20 | // / _||||| -:- |||||- \ 21 | // | | \\\ - /// | | 22 | // | \_| ''\---/'' | | 23 | // \ .-\__ `-` ___/-. / 24 | // ___`. .' /--.--\ `. . __ 25 | // ."" '< `.___\_<|>_/___.' >'"". 26 | // | | : `- \`.;`\ _ /`;.`/ - ` : | | 27 | // \ \ `-. \_ __\ /__ _/ .-` / / 28 | // ======`-.____`-.___\_____/___.-`____.-'====== 29 | // `=---=' 30 | // 31 | // ............................................. 32 | // 佛祖镇楼 BUG辟易 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 | * 在使用 BAKit 的过程中如果出现 bug 请及时以以下任意一种方式联系我,我会及时修复 bug 63 | * 64 | * QQ : 可以添加ios开发技术群 479663605 在这里找到我(博爱1616【137361770】) 65 | * 微博 : 博爱1616 66 | * Email : 137361770@qq.com 67 | * GitHub : https://github.com/boai 68 | * BAHome : https://github.com/BAHome 69 | * 博客 : http://boaihome.com 70 | 71 | ********************************************************************************* 72 | 73 | */ 74 | 75 | #ifndef BAPrivacyManager_Version_h 76 | #define BAPrivacyManager_Version_h 77 | 78 | /*! 79 | ********************************************************************************* 80 | ************************************ 更新说明 ************************************ 81 | ********************************************************************************* 82 | 83 | 欢迎使用 BAHome 系列开源代码 ! 84 | 如有更多需求,请前往:https://github.com/BAHome 85 | 86 | 项目源码地址: 87 | OC 版 :https://github.com/BAHome/BAPrivacyManager 88 | 89 | 最新更新时间:2017-10-08【倒叙】
90 | 最新 Version:【Version:1.0.1】
91 | 更新内容:
92 | 1.0.1.1、优化注释
93 | 94 | 最新更新时间:2017-10-07【倒叙】
95 | 最新 Version:【Version:1.0.0】
96 | 更新内容:
97 | 1.0.0.1、iOS 所有隐私权限封装,定位、蓝牙、通知、运动、日历、相册、相机等 14 种权限封装!详见 demo!
98 | 99 | */ 100 | 101 | #endif /* BAPrivacyManager_Version_h */ 102 | -------------------------------------------------------------------------------- /BAPrivacyManager/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 | -------------------------------------------------------------------------------- /BAPrivacyManager/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | NSBluetoothPeripheralUsageDescription 47 | 需要获取蓝牙权限 48 | NSCalendarsUsageDescription 49 | 日历 50 | NSCameraUsageDescription 51 | 需要获取您的摄像头信息 52 | NSContactsUsageDescription 53 | 需要获取您的通讯录权限 54 | NSHealthShareUsageDescription 55 | 健康分享权限 56 | NSHealthUpdateUsageDescription 57 | 健康数据更新权限 58 | NSHomeKitUsageDescription 59 | HomeKit权限 60 | NSLocationAlwaysUsageDescription 61 | 一直定位权限 62 | NSLocationUsageDescription 63 | 定位权限 64 | NSLocationWhenInUseUsageDescription 65 | 使用app期间定位权限 66 | NSMicrophoneUsageDescription 67 | 需要获取您的麦克风权限 68 | NSPhotoLibraryUsageDescription 69 | 需要获取您的相册信息 70 | NSRemindersUsageDescription 71 | 提醒事项 72 | NSSiriUsageDescription 73 | 需要获取您的Siri权限 74 | NSSpeechRecognitionUsageDescription 75 | 语音识别权限 76 | NSVideoSubscriberAccountUsageDescription 77 | AppleTV权限 78 | NSAppleMusicUsageDescription 79 | Add tracks to your music library. 80 | NSMotionUsageDescription 81 | 运动与健身权限 82 | 83 | 84 | -------------------------------------------------------------------------------- /BAPrivacyManager/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 28 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /BAPrivacyManager/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // BAPrivacyManager 4 | // 5 | // Created by boai on 2017/9/28. 6 | // Copyright © 2017年 boai. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /BAPrivacyManager/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // BAPrivacyManager 4 | // 5 | // Created by boai on 2017/9/28. 6 | // Copyright © 2017年 boai. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | #import "BAKit_PrivacyManager.h" 12 | 13 | static NSString * const kCellID = @"BAFoundationViewControllerCell"; 14 | 15 | @interface ViewController () 16 | 17 | @property(nonatomic, strong) UITableView *tableView; 18 | @property(nonatomic, strong) NSArray *dataArray; 19 | 20 | @end 21 | 22 | @implementation ViewController 23 | 24 | - (void)viewDidLoad { 25 | [super viewDidLoad]; 26 | // Do any additional setup after loading the view. 27 | 28 | [self setupUI]; 29 | } 30 | 31 | - (void)setupUI 32 | { 33 | self.view.backgroundColor = BAKit_Color_White_pod; 34 | self.title = @"BAPrivacyManager"; 35 | } 36 | 37 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 38 | { 39 | return self.dataArray.count; 40 | } 41 | 42 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 43 | { 44 | 45 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellID]; 46 | 47 | if (!cell) 48 | { 49 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:kCellID]; 50 | } 51 | NSString *msg = [@(indexPath.row + 1).stringValue stringByAppendingString:@"、"]; 52 | cell.textLabel.text = [msg stringByAppendingString:self.dataArray[indexPath.row]]; 53 | cell.textLabel.font = [UIFont systemFontOfSize:15]; 54 | cell.textLabel.numberOfLines = 0; 55 | 56 | return cell; 57 | } 58 | 59 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 60 | { 61 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 62 | 63 | switch (indexPath.row) { 64 | case 0: 65 | { 66 | [BAPrivacyManagerShared ba_checkAndRequestPrivacyOfLocationServicesWithBlock:^(BAKit_LocationAuthorizationStatus status) { 67 | if (status == BAKit_LocationAuthorizationStatus_Authorized) 68 | { 69 | BAKit_ShowAlertWithMsg_ios8(@"已经授权过,无需授权"); 70 | } 71 | else if (status == BAKit_LocationAuthorizationStatus_NotDetermined) 72 | { 73 | BAKit_ShowAlertWithMsg_ios8(@"第一次授权!"); 74 | } 75 | else 76 | { 77 | NSString *msg = [NSString stringWithFormat:@"授权类型:%@,授权状态:%ld", self.dataArray[indexPath.row], status]; 78 | NSLog(@"%@", msg); 79 | BAKit_ShowAlertWithMsg_ios8(msg); 80 | } 81 | 82 | }]; 83 | } 84 | break; 85 | case 1: 86 | { 87 | [BAPrivacyManagerShared ba_checkAndRequestPrivacyOfContactsWithBlock:^(BAKit_PrivacyStatus status, BAKit_PrivacyType type) { 88 | NSString *msg = [NSString stringWithFormat:@"授权类型:%@,授权状态:%ld", self.dataArray[indexPath.row], status]; 89 | NSLog(@"%@", msg); 90 | BAKit_ShowAlertWithMsg_ios8(msg); 91 | }]; 92 | } 93 | break; 94 | case 2: 95 | { 96 | [BAPrivacyManagerShared ba_checkAndRequestPrivacyOfCalendarsWithBlock:^(BAKit_PrivacyStatus status, BAKit_PrivacyType type) { 97 | NSString *msg = [NSString stringWithFormat:@"授权类型:%@,授权状态:%ld", self.dataArray[indexPath.row], status]; 98 | NSLog(@"%@", msg); 99 | BAKit_ShowAlertWithMsg_ios8(msg); 100 | }]; 101 | } 102 | break; 103 | case 3: 104 | { 105 | [BAPrivacyManagerShared ba_checkAndRequestPrivacyOfRemindersWithBlock:^(BAKit_PrivacyStatus status, BAKit_PrivacyType type) { 106 | NSString *msg = [NSString stringWithFormat:@"授权类型:%@,授权状态:%ld", self.dataArray[indexPath.row], status]; 107 | NSLog(@"%@", msg); 108 | BAKit_ShowAlertWithMsg_ios8(msg); 109 | }]; 110 | } 111 | break; 112 | case 4: 113 | { 114 | [BAPrivacyManagerShared ba_checkAndRequestPrivacyOfPhotosWithBlock:^(BAKit_PrivacyStatus status, BAKit_PrivacyType type) { 115 | NSString *msg = [NSString stringWithFormat:@"授权类型:%@,授权状态:%ld", self.dataArray[indexPath.row], status]; 116 | NSLog(@"%@", msg); 117 | BAKit_ShowAlertWithMsg_ios8(msg); 118 | }]; 119 | } 120 | break; 121 | case 5: 122 | { 123 | [BAPrivacyManagerShared ba_checkAndRequestPrivacyOfCameraWithBlock:^(BAKit_PrivacyStatus status, BAKit_PrivacyType type) { 124 | NSString *msg = [NSString stringWithFormat:@"授权类型:%@,授权状态:%ld", self.dataArray[indexPath.row], status]; 125 | NSLog(@"%@", msg); 126 | BAKit_ShowAlertWithMsg_ios8(msg); 127 | }]; 128 | } 129 | break; 130 | case 6: 131 | { 132 | [BAPrivacyManagerShared ba_checkAndRequestPrivacyOfBluetoothSharingWithBlock:^(BAKit_CBManagerStatus status) { 133 | NSString *msg = [NSString stringWithFormat:@"授权类型:%@,授权状态:%ld", self.dataArray[indexPath.row], status]; 134 | NSLog(@"%@", msg); 135 | BAKit_ShowAlertWithMsg_ios8(msg); 136 | }]; 137 | } 138 | break; 139 | case 7: 140 | { 141 | [BAPrivacyManagerShared ba_checkAndRequestPrivacyOfMicrophoneWithBlock:^(BAKit_PrivacyStatus status, BAKit_PrivacyType type) { 142 | NSString *msg = [NSString stringWithFormat:@"授权类型:%@,授权状态:%ld", self.dataArray[indexPath.row], status]; 143 | NSLog(@"%@", msg); 144 | BAKit_ShowAlertWithMsg_ios8(msg); 145 | }]; 146 | } 147 | break; 148 | case 8: 149 | { 150 | [BAPrivacyManagerShared ba_checkAndRequestPrivacyOfSpeechRecognitionWithBlock:^(BAKit_PrivacyStatus status, BAKit_PrivacyType type) { 151 | NSString *msg = [NSString stringWithFormat:@"授权类型:%@,授权状态:%ld", self.dataArray[indexPath.row], status]; 152 | NSLog(@"%@", msg); 153 | BAKit_ShowAlertWithMsg_ios8(msg); 154 | }]; 155 | } 156 | break; 157 | case 9: 158 | { 159 | [BAPrivacyManagerShared ba_checkAndRequestPrivacyOfHealthWithBlock:^(BAKit_PrivacyStatus status, BAKit_PrivacyType type) { 160 | NSString *msg = [NSString stringWithFormat:@"授权类型:%@,授权状态:%ld", self.dataArray[indexPath.row], status]; 161 | NSLog(@"%@", msg); 162 | BAKit_ShowAlertWithMsg_ios8(msg); 163 | }]; 164 | } 165 | break; 166 | case 10: 167 | { 168 | [BAPrivacyManagerShared ba_checkAndRequestPrivacyOfHomeWithBlock:^(BOOL isHaveHomeAccess) { 169 | NSString *msg = [NSString stringWithFormat:@"授权类型:%@,授权状态:%d", self.dataArray[indexPath.row], isHaveHomeAccess]; 170 | NSLog(@"%@", msg); 171 | BAKit_ShowAlertWithMsg_ios8(msg); 172 | }]; 173 | } 174 | break; 175 | case 11: 176 | { 177 | [BAPrivacyManagerShared ba_checkAndRequestPrivacyOfAppleMusicWithBlock:^(BAKit_PrivacyStatus status, BAKit_PrivacyType type) { 178 | NSString *msg = [NSString stringWithFormat:@"授权类型:%@,授权状态:%ld", self.dataArray[indexPath.row], status]; 179 | NSLog(@"%@", msg); 180 | BAKit_ShowAlertWithMsg_ios8(msg); 181 | }]; 182 | } 183 | break; 184 | case 12: 185 | { 186 | [BAPrivacyManagerShared ba_checkAndRequestPrivacyOfMotionAndFitness]; 187 | } 188 | break; 189 | case 13: 190 | { 191 | [BAPrivacyManagerShared ba_openMessageNotificationServiceWithBlock:^(BOOL isOpenMessageNotification, UIUserNotificationType type) { 192 | NSString *msg = [NSString stringWithFormat:@"授权类型:%@,授权状态:%d,%ld", self.dataArray[indexPath.row], isOpenMessageNotification, type]; 193 | NSLog(@"%@", msg); 194 | BAKit_ShowAlertWithMsg_ios8(msg); 195 | }]; 196 | } 197 | break; 198 | 199 | default: 200 | break; 201 | } 202 | } 203 | 204 | - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section 205 | { 206 | return 15; 207 | } 208 | 209 | - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section 210 | { 211 | return FLT_MIN; 212 | } 213 | 214 | - (void)viewWillLayoutSubviews 215 | { 216 | [super viewWillLayoutSubviews]; 217 | 218 | self.tableView.frame = self.view.bounds; 219 | 220 | } 221 | 222 | #pragma mark - setter / getter 223 | - (UITableView *)tableView 224 | { 225 | if (!_tableView) 226 | { 227 | _tableView = [[UITableView alloc] init]; 228 | self.tableView.backgroundColor = BAKit_Color_Gray_11_pod; 229 | self.tableView.delegate = self; 230 | self.tableView.dataSource = self; 231 | 232 | self.tableView.estimatedRowHeight = 44; 233 | self.tableView.rowHeight = UITableViewAutomaticDimension; 234 | 235 | self.tableView.tableFooterView = [UIView new]; 236 | [self.view addSubview:self.tableView]; 237 | } 238 | return _tableView; 239 | } 240 | 241 | - (NSArray *)dataArray 242 | { 243 | if (!_dataArray) 244 | { 245 | _dataArray = @[@"定位", @"通讯录", 246 | @"日历", @"提醒事项", 247 | @"照片", @"相机", 248 | @"蓝牙共享", @"麦克风", 249 | @"语音识别 >= iOS 10.0", 250 | @"健康 >= iOS 8.0", 251 | @"家庭 >= iOS 8.0", 252 | @"媒体与 Apple Music >= iOS 9.3", 253 | @"运动与健身", @"通知权限监测" 254 | ]; 255 | } 256 | return _dataArray; 257 | } 258 | 259 | @end 260 | -------------------------------------------------------------------------------- /BAPrivacyManager/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // BAPrivacyManager 4 | // 5 | // Created by boai on 2017/9/28. 6 | // Copyright © 2017年 boai. 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 | -------------------------------------------------------------------------------- /Images/BAPrivacyManager.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BAHome/BAPrivacyManager/fafa3fa6afb900923c9806e456c01b7f07e34fb0/Images/BAPrivacyManager.png -------------------------------------------------------------------------------- /Images/BAPrivacyManager1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BAHome/BAPrivacyManager/fafa3fa6afb900923c9806e456c01b7f07e34fb0/Images/BAPrivacyManager1.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 boai 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BAPrivacyManager 2 | [![BAHome Team Name](https://img.shields.io/badge/Team-BAHome-brightgreen.svg?style=flat)](https://github.com/BAHome "BAHome Team") 3 | ![](https://img.shields.io/badge/platform-iOS-red.svg) ![](https://img.shields.io/badge/language-Objective--C-orange.svg) 4 | ![](https://img.shields.io/badge/license-MIT%20License-brightgreen.svg) 5 | ![](https://img.shields.io/cocoapods/v/BAPrivacyManager.svg?style=flat) ![](https://img.shields.io/cocoapods/dt/BAPrivacyManager.svg 6 | ) [![](https://img.shields.io/badge/微博-博爱1616-red.svg)](http://weibo.com/538298123) 7 | 8 | ## 1、功能及简介 9 | * 1、iOS 所有隐私权限封装,定位、蓝牙、通知、运动、日历、相册、相机等 14 种权限封装!详见 demo!
10 | 11 | ## 2、图片示例 12 | ![BAPrivacyManager1](https://github.com/BAHome/BAPrivacyManager/blob/master/Images/BAPrivacyManager1.png) 13 | 14 | ## 3、安装、导入示例和源码地址 15 | * 1、pod 导入【最新版本:![](https://img.shields.io/cocoapods/v/BAPrivacyManager.svg?style=flat)】:
16 | `pod 'BAPrivacyManager'`
17 | 如果发现 `pod search BAPrivacyManager` 搜索出来的不是最新版本,需要在终端执行 cd 转换文件路径命令退回到 desktop,然后执行 `pod setup` 命令更新本地spec缓存(可能需要几分钟),然后再搜索就可以了。
18 | 具体步骤: 19 | - pod setup : 初始化 20 | - pod repo update : 更新仓库 21 | - pod search BAPrivacyManager 22 | * 2、文件夹拖入:下载demo,把 BAPrivacyManager 文件夹拖入项目即可,
23 | * 3、导入头文件:
24 | ` #import "BAKit_PrivacyManager.h" `
25 | * 4、项目源码地址:
26 | OC 版 :[https://github.com/BAHome/BAPrivacyManager](https://github.com/BAHome/BAPrivacyManager)
27 | 28 | ## 4、BAPrivacyManager 的类结构及 demo 示例 29 | ![BAPrivacyManager](https://github.com/BAHome/BAPrivacyManager/blob/master/Images/BAPrivacyManager.png) 30 | 31 | ### BAPrivacyManager.h 32 | ``` 33 | #import 34 | #import "BAKit_Singleton.h" 35 | 36 | // Import required frameworks 37 | #import 38 | #import 39 | #import 40 | #import 41 | #import 42 | #import 43 | #import 44 | #import 45 | #import 46 | #import 47 | #import 48 | #import 49 | // 相册 50 | #import 51 | // 通知 52 | #import 53 | 54 | 55 | /** 56 | 隐私类型 57 | 58 | - BAKit_PrivacyType_None: 无 59 | - BAKit_PrivacyType_LocationServices: 定位 60 | - BAKit_PrivacyType_Contacts: 通讯录 61 | - BAKit_PrivacyType_Calendars: 日历 62 | - BAKit_PrivacyType_Reminders: 提醒事项 63 | - BAKit_PrivacyType_Photos: 照片 64 | - BAKit_PrivacyType_Camera: 相机 65 | - BAKit_PrivacyType_BluetoothSharing: 蓝牙共享 66 | - BAKit_PrivacyType_Microphone: 麦克风 67 | - BAKit_PrivacyType_SpeechRecognition: 语音识别 >= iOS 10.0 68 | - BAKit_PrivacyType_Health: 健康 >= iOS 8.0 69 | - BAKit_PrivacyType_HomeKit: 家庭 >= iOS 8.0 70 | - BAKit_PrivacyType_MediaAndAppleMusic: 媒体与 Apple Music >= iOS 9.3 71 | - BAKit_PrivacyType_MotionAndFitness: 运动与健身 72 | - BAKit_PrivacyType_MessageNotification: 消息通知 73 | */ 74 | typedef NS_ENUM(NSUInteger, BAKit_PrivacyType){ 75 | BAKit_PrivacyType_None = 0, 76 | BAKit_PrivacyType_LocationServices, 77 | BAKit_PrivacyType_Contacts, 78 | BAKit_PrivacyType_Calendars, 79 | BAKit_PrivacyType_Reminders, 80 | BAKit_PrivacyType_Photos, 81 | BAKit_PrivacyType_Camera, 82 | BAKit_PrivacyType_BluetoothSharing, 83 | BAKit_PrivacyType_Microphone, 84 | BAKit_PrivacyType_SpeechRecognition, 85 | BAKit_PrivacyType_Health, 86 | BAKit_PrivacyType_HomeKit, 87 | BAKit_PrivacyType_MediaAndAppleMusic, 88 | BAKit_PrivacyType_MotionAndFitness, 89 | BAKit_PrivacyType_MessageNotification, 90 | }; 91 | 92 | /** 93 | 权限状态,参考:PHAuthorizationStatus 等,可以根据返回的不同状态做相应的处理 94 | 95 | - BAKit_PrivacyStatus_NotDetermined: 用户从未进行过授权等处理,首次访问相应内容会提示用户进行授权 96 | - BAKit_PrivacyStatus_Authorized: 已授权 97 | - BAKit_PrivacyStatus_Denied: 拒绝 98 | - BAKit_PrivacyStatus_Restricted: 应用没有相关权限,且当前用户无法改变这个权限,比如:家长控制 99 | - BAKit_PrivacyStatus_NotSupport: 硬件等不支持 100 | */ 101 | typedef NS_ENUM(NSUInteger, BAKit_PrivacyStatus){ 102 | BAKit_PrivacyStatus_NotDetermined = 0, 103 | BAKit_PrivacyStatus_Authorized = 1, 104 | BAKit_PrivacyStatus_Denied = 2, 105 | BAKit_PrivacyStatus_Restricted = 3, 106 | BAKit_PrivacyStatus_NotSupport = 4, 107 | }; 108 | 109 | /** 110 | 定位权限状态,参考:CLAuthorizationStatus 111 | 112 | - BAKit_LocationAuthorizationStatus_NotDetermined: 用户从未进行过授权等处理,首次访问相应内容会提示用户进行授权 113 | - BAKit_LocationAuthorizationStatus_Authorized: 一直允许获取定位 ps:< iOS8用 114 | - BAKit_LocationAuthorizationStatus_Denied: 拒绝 115 | - BAKit_LocationAuthorizationStatus_Restricted: 应用没有相关权限,且当前用户无法改变这个权限,比如:家长控制 116 | - BAKit_LocationAuthorizationStatus_NotSupport: 硬件等不支持 117 | - BAKit_LocationAuthorizationStatus_AuthorizedAlways: 一直允许获取定位 118 | - BAKit_LocationAuthorizationStatus_AuthorizedWhenInUse: 在使用时允许获取定位 119 | */ 120 | typedef NS_ENUM(NSUInteger, BAKit_LocationAuthorizationStatus){ 121 | BAKit_LocationAuthorizationStatus_NotDetermined = 0, 122 | BAKit_LocationAuthorizationStatus_Authorized = 1, 123 | BAKit_LocationAuthorizationStatus_Denied = 2, 124 | BAKit_LocationAuthorizationStatus_Restricted = 3, 125 | BAKit_LocationAuthorizationStatus_NotSupport = 4, 126 | BAKit_LocationAuthorizationStatus_AuthorizedAlways = 5, 127 | BAKit_LocationAuthorizationStatus_AuthorizedWhenInUse = 6, 128 | }; 129 | 130 | /** 131 | 蓝牙连接状态,参考:CBManagerState 132 | 133 | - BAKit_CBManagerStatus_Unknown: 未知状态 134 | - BAKit_CBManagerStatus_Resetting: 正在重置,与系统服务暂时丢失 135 | - BAKit_CBManagerStatus_Unsupported: 不支持蓝牙 136 | - BAKit_CBManagerStatus_Unauthorized: 未授权 137 | - BAKit_CBManagerStatus_PoweredOff: 关闭 138 | - BAKit_CBManagerStatus_PoweredOn: 开启并可用 139 | */ 140 | typedef NS_ENUM(NSUInteger, BAKit_CBManagerStatus){ 141 | BAKit_CBManagerStatus_Unknown = 0, 142 | BAKit_CBManagerStatus_Resetting = 1, 143 | BAKit_CBManagerStatus_Unsupported = 2, 144 | BAKit_CBManagerStatus_Unauthorized = 3, 145 | BAKit_CBManagerStatus_PoweredOff = 4, 146 | BAKit_CBManagerStatus_PoweredOn = 5, 147 | }; 148 | 149 | /* 150 | 定义权限状态回调 block 151 | */ 152 | typedef void(^BAKit_PrivacyResultBlock)(BAKit_PrivacyStatus status, BAKit_PrivacyType type); 153 | 154 | /** 155 | 定位权限 block 156 | 157 | @param status 定位权限状态 158 | */ 159 | typedef void(^BAKit_PrivacyOfLocationResultBlock)(BAKit_LocationAuthorizationStatus status); 160 | 161 | /** 162 | 蓝牙连接状态 block 163 | 164 | @param status 蓝牙连接状态 165 | */ 166 | typedef void(^BAKit_PrivacyOfBluetoothResultBlock)(BAKit_CBManagerStatus status); 167 | 168 | /** 169 | 家庭状态 block 170 | 171 | @param isHaveHomeAccess HomeKit 状态 172 | */ 173 | typedef void(^BAKit_PrivacyOfHomeResultBlock)(BOOL isHaveHomeAccess); 174 | 175 | /** 176 | 运动与健身状态 block 177 | 178 | @param isHaveMotionAccess 运动与健身状态 179 | */ 180 | typedef void(^BAKit_PrivacyOfMotionResultBlock)(BOOL isHaveMotionAccess); 181 | 182 | /** 183 | 是否开启通知 184 | 185 | @param isOpenMessageNotification 开启通知状态 186 | @param type 通知类型 187 | */ 188 | typedef void(^BAKit_PrivacyOfMessageNotificationResultBlock)(BOOL isOpenMessageNotification, UIUserNotificationType type); 189 | 190 | #define BAPrivacyManagerShared [BAPrivacyManager sharedBAPrivacyManager] 191 | 192 | @interface BAPrivacyManager : NSObject 193 | BAKit_SingletonH(BAPrivacyManager) 194 | 195 | 196 | #pragma mark - checkAndRequestAccessForType 197 | - (void)ba_authorizationManagerCheckAccessForType:(BAKit_PrivacyType)type 198 | block:(BAKit_PrivacyResultBlock)block; 199 | 200 | #pragma mark - Contacts 201 | - (void)ba_checkAndRequestPrivacyOfContactsWithBlock:(BAKit_PrivacyResultBlock)block; 202 | 203 | #pragma mark - Calendars 204 | - (void)ba_checkAndRequestPrivacyOfCalendarsWithBlock:(BAKit_PrivacyResultBlock)block; 205 | 206 | #pragma mark - Reminders 207 | - (void)ba_checkAndRequestPrivacyOfRemindersWithBlock:(BAKit_PrivacyResultBlock)block; 208 | 209 | #pragma mark - Photos 210 | - (void)ba_checkAndRequestPrivacyOfPhotosWithBlock:(BAKit_PrivacyResultBlock)block; 211 | 212 | #pragma mark - Microphone 213 | - (void)ba_checkAndRequestPrivacyOfMicrophoneWithBlock:(BAKit_PrivacyResultBlock)block; 214 | 215 | #pragma mark - SpeechRecognition 216 | - (void)ba_checkAndRequestPrivacyOfSpeechRecognitionWithBlock:(BAKit_PrivacyResultBlock)block; 217 | 218 | #pragma mark - Camera 219 | - (void)ba_checkAndRequestPrivacyOfCameraWithBlock:(BAKit_PrivacyResultBlock)block; 220 | 221 | #pragma mark - Health,注意:需要证书支持 healthkit 222 | - (void)ba_checkAndRequestPrivacyOfHealthWithBlock:(BAKit_PrivacyResultBlock)block; 223 | 224 | #pragma mark - HomeKit,注意:需要证书支持 HomeKit 225 | - (void)ba_checkAndRequestPrivacyOfHomeWithBlock:(BAKit_PrivacyOfHomeResultBlock)block; 226 | 227 | #pragma mark - HMHomeManagerDelegate 228 | - (void)homeManagerDidUpdateHomes:(HMHomeManager *)manager; 229 | 230 | #pragma mark - MediaAndAppleMusic 231 | - (void)ba_checkAndRequestPrivacyOfAppleMusicWithBlock:(BAKit_PrivacyResultBlock)block; 232 | 233 | #pragma mark - MotionAndFitness 234 | - (void)ba_checkAndRequestPrivacyOfMotionAndFitness; 235 | 236 | #pragma mark - 通知权限监测 237 | - (void)ba_openMessageNotificationServiceWithBlock:(BAKit_PrivacyOfMessageNotificationResultBlock)block; 238 | 239 | #pragma mark - LocationServices 240 | - (void)ba_checkAndRequestPrivacyOfLocationServicesWithBlock:(BAKit_PrivacyOfLocationResultBlock)block; 241 | 242 | #pragma mark - BluetoothSharing 支持 iOS 10.0 以上 243 | - (void)ba_checkAndRequestPrivacyOfBluetoothSharingWithBlock:(BAKit_PrivacyOfBluetoothResultBlock)block; 244 | 245 | @end 246 | ``` 247 | 248 | ### demo 示例 249 | ``` 250 | // 示例1:定位权限 251 | [BAPrivacyManagerShared ba_checkAndRequestPrivacyOfLocationServicesWithBlock:^(BAKit_LocationAuthorizationStatus status) { 252 | if (status == BAKit_LocationAuthorizationStatus_Authorized) 253 | { 254 | BAKit_ShowAlertWithMsg_ios8(@"已经授权过,无需授权"); 255 | } 256 | else if (status == BAKit_LocationAuthorizationStatus_NotDetermined) 257 | { 258 | BAKit_ShowAlertWithMsg_ios8(@"第一次授权!"); 259 | } 260 | else 261 | { 262 | NSString *msg = [NSString stringWithFormat:@"授权类型:%@,授权状态:%ld", self.dataArray[indexPath.row], status]; 263 | NSLog(@"%@", msg); 264 | BAKit_ShowAlertWithMsg_ios8(msg); 265 | } 266 | 267 | }]; 268 | 269 | 270 | // 示例2:通知权限 271 | [BAPrivacyManagerShared ba_openMessageNotificationServiceWithBlock:^(BOOL isOpenMessageNotification, UIUserNotificationType type) { 272 | NSString *msg = [NSString stringWithFormat:@"授权类型:%@,授权状态:%d,%ld", self.dataArray[indexPath.row], isOpenMessageNotification, type]; 273 | NSLog(@"%@", msg); 274 | BAKit_ShowAlertWithMsg_ios8(msg); 275 | }]; 276 | 277 | // 示例3:蓝牙权限 278 | [BAPrivacyManagerShared ba_checkAndRequestPrivacyOfBluetoothSharingWithBlock:^(BAKit_CBManagerStatus status) { 279 | NSString *msg = [NSString stringWithFormat:@"授权类型:%@,授权状态:%ld", self.dataArray[indexPath.row], status]; 280 | NSLog(@"%@", msg); 281 | BAKit_ShowAlertWithMsg_ios8(msg); 282 | }]; 283 | 284 | 其他示例可下载demo查看源码! 285 | ``` 286 | 287 | ## 5、更新记录:【倒叙】 288 | 欢迎使用 [【BAHome】](https://github.com/BAHome) 系列开源代码 ! 289 | 如有更多需求,请前往:[【https://github.com/BAHome】](https://github.com/BAHome) 290 | 291 | 最新更新时间:2017-10-07【倒叙】
292 | 最新 Version:【Version:1.0.0】
293 | 更新内容:
294 | 1.0.0.1、iOS 所有隐私权限封装,定位、蓝牙、通知、运动、日历、相册、相机等 14 种权限封装!详见 demo!
295 | 296 | 297 | ## 6、bug 反馈 298 | > 1、开发中遇到 bug,希望小伙伴儿们能够及时反馈与我们 [【BAHome】](https://github.com/BAHome) 团队,我们必定会认真对待每一个问题!
299 | 300 | > 2、以后提需求和 bug 的同学,记得把 git 或者博客链接给我们,我直接超链到你们那里!希望大家积极参与测试!
301 | 302 | ## 7、BAHome 团队成员 303 | > 1、QQ 群 304 | 479663605
305 | 【注意:此群为 2 元 付费群,介意的小伙伴儿勿扰!】
306 | 307 | > 孙博岩
308 | QQ:137361770
309 | git:[https://github.com/boai](https://github.com/boai)
310 | 简书:[http://www.jianshu.com/u/95c9800fdf47](http://www.jianshu.com/u/95c9800fdf47)
311 | 微博:[![](https://img.shields.io/badge/微博-博爱1616-red.svg)](http://weibo.com/538298123)
312 | 313 | > 马景丽
314 | QQ:1253540493
315 | git:[https://github.com/MaJingli](https://github.com/MaJingli)
316 | 317 | > 陆晓峰
318 | QQ:442171865
319 | git:[https://github.com/zeR0Lu](https://github.com/zeR0Lu)
320 | 321 | > 陈集
322 | QQ:3161182978
323 | git:[https://github.com/chenjipdc](https://github.com/chenjipdc)
324 | 简书:[http://www.jianshu.com/u/90ae559fc21d](http://www.jianshu.com/u/90ae559fc21d) 325 | 326 | > 任子丰
327 | QQ:459643690
328 | git:[https://github.com/renzifeng](https://github.com/renzifeng)
329 | 330 | > 吴丰收
331 | QQ:498121294
332 | 333 | > 石少庸
334 | QQ:363605775
335 | git:[https://github.com/CrazyCoderShi](https://github.com/CrazyCoderShi)
336 | 简书:[http://www.jianshu.com/u/0726f4d689a3](http://www.jianshu.com/u/0726f4d689a3) 337 | 338 | ## 8、开发环境 和 支持版本 339 | > 开发使用 最新版本 Xcode,理论上支持 iOS 8 及以上版本,如有版本适配问题,请及时反馈!多谢合作! 340 | 341 | ## 9、感谢 342 | > 感谢 [【BAHome】](https://github.com/BAHome) 团队成员倾力合作,后期会推出一系列 常用 UI 控件的封装,大家有需求得也可以在 issue 提出,如果合理,我们会尽快推出新版本!
343 | 344 | > [【BAHome】](https://github.com/BAHome) 的发展离不开小伙伴儿的信任与推广,再次感谢各位小伙伴儿的支持! 345 | 346 | --------------------------------------------------------------------------------