[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-6861":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":16,"stars30d":16,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":17,"rankGlobal":10,"rankLanguage":10,"license":18,"archived":19,"fork":20,"defaultBranch":21,"hasWiki":19,"hasPages":20,"topics":22,"createdAt":10,"pushedAt":10,"updatedAt":23,"readmeContent":24,"aiSummary":25,"trendingCount":16,"starSnapshotCount":16,"syncStatus":26,"lastSyncTime":27,"discoverSource":28},6861,"PermissionScope","nickoneill\u002FPermissionScope","nickoneill","Intelligent iOS permissions UI and unified API","",null,"Swift",4797,496,1,30,0,30.09,"MIT License",true,false,"master",[],"2026-06-12 02:01:31","## PermissionScope is no longer supported. Please use an alternative if you need updates for newer iOS 10 and 11 APIs!\n\n\u003Cp align=\"center\">\n    \u003Cimg src=\"http:\u002F\u002Fraquo.net\u002Fimages\u002Fbanner.png\" alt=\"PermissionScope\" \u002F>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n    \u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fplatform-iOS%208%2B-blue.svg?style=flat\" alt=\"Platform: iOS 8+\" \u002F>\n    \u003Ca href=\"https:\u002F\u002Fdeveloper.apple.com\u002Fswift\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Flanguage-swift3-f48041.svg?style=flat\" alt=\"Language: Swift 3\" \u002F>\u003C\u002Fa>\n    \u003Ca href=\"https:\u002F\u002Fgithub.com\u002FCarthage\u002FCarthage\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FCarthage-compatible-4BC51D.svg?style=flat\" alt=\"Carthage compatible\" \u002F>\u003C\u002Fa>\n    \u003Ca href=\"https:\u002F\u002Fcocoapods.org\u002Fpods\u002FPermissionScope\">\u003Cimg src=\"https:\u002F\u002Fcocoapod-badges.herokuapp.com\u002Fv\u002FPermissionScope\u002Fbadge.png\" alt=\"Cocoapods compatible\" \u002F>\u003C\u002Fa>\n    \u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Flicense-MIT-lightgrey.svg?style=flat\" alt=\"License: MIT\" \u002F>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n    \u003Ca href=\"#installation\">Installation\u003C\u002Fa>\n  • \u003Ca href=\"#dialog-usage\">Usage\u003C\u002Fa>\n  • \u003Ca href=\"#customization\">Customization\u003C\u002Fa>\n  • \u003Ca href=\"#known-bugs\">Known bugs\u003C\u002Fa>\n  • \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fnickoneill\u002FPermissionScope\u002Fissues\">Issues\u003C\u002Fa>\n  • \u003Ca href=\"#license\">License\u003C\u002Fa>\n\u003C\u002Fp>\n\nInspired by (but unrelated to) [Periscope](https:\u002F\u002Fwww.periscope.tv)'s permission control, PermissionScope is a Swift framework for intelligently requesting permissions from users. **It contains not only a simple UI to request permissions but also a unified permissions API** that can tell you the status of any given system permission or easily request them.\n\nSome examples of multiple permissions requests, a single permission and the denied alert.\n\n\u003Cp align=\"center\">\n    \u003Cimg src=\"http:\u002F\u002Fraquo.net\u002Fimages\u002Fpermissionscope.gif\" alt=\"permissionscope gif\" \u002F>\n\u003C\u002Fp>\n\nPermissionScope **gives you space to explain your reasons for requesting permissions** and **allows users to tackle the system dialogs at their own pace**. It presents a straightforward permissions design and is flexible enough to fit in to most UIKit-based apps.\n\nBest of all, PermissionScope detects when your app's permissions have been denied by a user and gives them an easy prompt to go into the system settings page to modify these permissions.\n\nSupported permissions:\n* Notifications\n* Location (WhileInUse, Always)\n* Contacts\n* Events\n* Microphone\n* Camera\n* Photos\n* Reminders\n* Bluetooth\n* Motion\n\n## compatibility\n\nPermissionScope requires iOS 8+, compatible with both **Swift 3** and **Objective-C** based projects.\n\nFor Swift 2.x support, please use the swift2 branch or the 1.0.2 release version. This branch was up-to-date on 9\u002F6\u002F16 but is not being maintained. All future efforts will go towards Swift 3 development.\n\n## installation\n\nInstallation for [Carthage](https:\u002F\u002Fgithub.com\u002FCarthage\u002FCarthage) is simple enough:\n\n`github \"nickoneill\u002FPermissionScope\" ~> 1.0`\n\nAs for [Cocoapods](https:\u002F\u002Fcocoapods.org), use this to get the latest release:\n\n```ruby\nuse_frameworks!\n\npod 'PermissionScope'\n```\n\nAnd `import PermissionScope` in the files you'd like to use it.\n\n## dialog usage\n\nThe simplest implementation displays a list of permissions and is removed when all of them have satisfactory access.\n\n```swift\nclass ViewController: UIViewController {\n    let pscope = PermissionScope()\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        \n        \u002F\u002F Set up permissions\n        pscope.addPermission(ContactsPermission(),\n            message: \"We use this to steal\\r\\nyour friends\")\n        pscope.addPermission(NotificationsPermission(notificationCategories: nil),\n            message: \"We use this to send you\\r\\nspam and love notes\")\n        pscope.addPermission(LocationWhileInUsePermission(),\n            message: \"We use this to track\\r\\nwhere you live\")\n\t\n\t\u002F\u002F Show dialog with callbacks\n        pscope.show({ finished, results in\n            print(\"got results \\(results)\")\n        }, cancelled: { (results) -> Void in\n            print(\"thing was cancelled\")\n        })   \n    }\n}\n```\n\nThe permissions view will automatically show if there are permissions to approve and will take no action if permissions are already granted. It will automatically hide when all permissions have been approved.\n\nIf you're attempting to block access to a screen in your app without permissions (like, say, the broadcast screen in Periscope), you should watch for the cancel closure and take an appropriate action for your app.\n\n### customization\n\nYou can easily change the colors, label and buttons fonts with PermissionScope by modifying any of these properties:\n\nField | Type | Comment\n----- | ---- | -------\nheaderLabel | UILabel | Header UILabel with the message \"Hey, listen!\" by default.\nbodyLabel | UILabel | Header UILabel with the message \"We need a couple things\\r\\nbefore you get started.\" by default.\ncloseButtonTextColor | UIColor | Color for the close button's text color.\npermissionButtonTextColor  | UIColor | Color for the permission buttons' text color.\npermissionButtonBorderColor | UIColor | Color for the permission buttons' border color.\nbuttonFont | UIFont | Font used for all the UIButtons\nlabelFont | UIFont | Font used for all the UILabels\ncloseButton | UIButton | Close button. By default in the top right corner.\ncloseOffset | CGSize | Offset used to position the Close button.\nauthorizedButtonColor | UIColor | Color used for permission buttons with authorized status\nunauthorizedButtonColor | UIColor? | Color used for permission buttons with unauthorized status. By default, inverse of `authorizedButtonColor`.\npermissionButtonΒorderWidth | CGFloat | Border width for the permission buttons.\npermissionButtonCornerRadius | CGFloat | Corner radius for the permission buttons.\npermissionLabelColor | UIColor | Color for the permission labels' text color.\ncontentView | UIView | Dialog's content view\n\nIn addition, the default behavior for tapping the background behind the dialog is to cancel the dialog (which calls the cancel closure you can provide on `show`). You can change this behavior with `backgroundTapCancels` during init.\n\nIf you'd like more control over the button text for a particular permission, you can [use a `.strings` file](https:\u002F\u002Fgithub.com\u002Fnickoneill\u002FPermissionScope\u002Fpull\u002F12#issuecomment-96428580) for your intended language and override them that way. Please get in touch if you'd like to contribute a localization file for another language!\n\n## unified permissions API\n\nPermissionScope also has an abstracted API for getting the state for a given permission and requesting permissions if you need to do so outside of the normal dialog UI. Think of it as a unified iOS permissions API that can provide some features that even Apple does not (such as detecting denied notification permissions).\n\n```swift\nswitch PermissionScope().statusContacts() {\ncase .Unknown:\n    \u002F\u002F ask\n    PermissionScope().requestContacts()\ncase .Unauthorized, .Disabled:\n    \u002F\u002F bummer\n    return\ncase .Authorized:\n    \u002F\u002F thanks!\n    return\n}\n```\n\n### calling `request*` methods directly\n\nNormally PermissionScope is used to walk users through necessary permissions before they're allowed to do something in your app. Sometimes you may wish to instead call into the various `request*` permissions-seeking methods of PermissionScope directly, from your own UI.\n\nTo call these methods directly, you must first set the `viewControllerForAlerts` method to your current UIViewController, in case PermissionScope needs to present some alerts to the user for denied or disabled permissions:\n\n```swift\nlet pscope = PermissionScope()\npscope.viewControllerForAlerts = self\n```\n\nYou will probably also want to set the `onAuthChange`, `onCancel`, and `onDisabledOrDenied` closures, which are called at the appropriate times when the `request*` methods are finished, otherwise you won't know when the work has been completed.\n\n```swift\npscope.onAuthChange = { (finished, results) in\n\tprintln(\"Request was finished with results \\(results)\")\n\tif results[0].status == .Authorized {\n\t\tprintln(\"They've authorized the use of notifications\")\n\t\tUIApplication.sharedApplication().registerForRemoteNotifications()\n\t}\n}\npscope.onCancel = { results in\n\tprintln(\"Request was cancelled with results \\(results)\")\n}\npscope.onDisabledOrDenied = { results in\n\tprintln(\"Request was denied or disabled with results \\(results)\")\n}\n```\n\nAnd then you might call it when the user toggles a switch:\n\n```swift\n@IBAction func notificationsChanged(sender: UISwitch) {\n\tif sender.on {\n\t\t\u002F\u002F turn on notifications\n\t\tif PermissionScope().statusNotifications() == .Authorized {\n\t\t\tUIApplication.sharedApplication().registerForRemoteNotifications()\n\t\t} else {\n\t\t\tpscope.requestNotifications()\n\t\t}\n\t} else {\n\t    \u002F\u002F turn off notifications\n\t}\n```\nIf you're also using PermissionScope in the traditional manner, don't forget to set viewControllerForAlerts back to it's default, the instance of PermissionScope. The easiest way to do this is to set it explicitly before you call a `request*` method, and then reset it in your closures.\n\n```swift\npscope.viewControllerForAlerts = pscope as UIViewController\n```\n\n### PermissionScope registers user notification settings, not remote notifications\nUsers will get the prompt to enable notifications when using PermissionScope but it's up to you to watch for results in your app delegate's `didRegisterUserNotificationSettings` and then register for remote notifications independently. This won't alert the user again. You're still responsible for handling the shipment of user notification settings off to your push server.\n\n## extra requirements for permissions\n\n### location \n**You must set these Info.plist keys for location to work**\n\nTrickiest part of implementing location permissions? You must implement the proper key in your Info.plist file with a short description of how your app uses location info (shown in the system permissions dialog). Without this, trying to get location  permissions will just silently fail. *Software*!\n\nUse `NSLocationAlwaysUsageDescription` or `NSLocationWhenInUseUsageDescription` where appropriate for your app usage. You can specify which of these location permissions you wish to request with `.LocationAlways` or `.LocationInUse` while configuring PermissionScope.\n\n### bluetooth\n\nThe *NSBluetoothPeripheralUsageDescription* key in the Info.plist specifying a short description of why your app needs to act as a bluetooth peripheral in the background is **optional**.\n\nHowever, enabling `background-modes` in the capabilities section and checking the `acts as a bluetooth LE accessory` checkbox is **required**.\n\n## known bugs\n\n* ITC app rejection with the following reason: \"*This app attempts to access privacy-sensitive data without a usage description*\". ([#194](https:\u002F\u002Fgithub.com\u002Fnickoneill\u002FPermissionScope\u002Fissues\u002F194))\n\nSolution: TBD\n\n* When the user is taken to the Settings.app, if any of the app's permissions are changed (whilst the app was in the background), the app will crash. ([#160](https:\u002F\u002Fgithub.com\u002Fnickoneill\u002FPermissionScope\u002Fissues\u002F160))\n\nSolution: None. Works as intended by the OS.\n\n* Link \"**Show me**\" does not work on denied a permission ([#61](https:\u002F\u002Fgithub.com\u002Fnickoneill\u002FPermissionScope\u002Fissues\u002F61))\n\nSolution: Run your app without the debugger.\n\n* When using **Carthage**, the following error occurs: *Module file was created by an older version of the compiler*.\n\nSolution: Use the `--no-use-binaries` flag (e.g:  `carthage update --no-use-binaries`).\n\n## license\n\nPermissionScope uses the MIT license. Please file an issue if you have any questions or if you'd like to share how you're using this tool.\n","PermissionScope 是一个用于智能请求iOS用户权限的Swift框架。它不仅提供了一个简洁的用户界面来请求权限，还统一了权限请求API，可以查询任何系统权限的状态或轻松请求这些权限。该框架支持包括通知、位置、联系人、事件、麦克风、相机等在内的多种权限，并且能够在用户的权限被拒绝时，引导用户前往系统设置页面进行修改。尽管官方已不再维护此项目，但其设计理念和功能仍适用于需要在iOS 8及以上版本中优雅地处理权限请求的应用场景，特别是那些基于UIKit构建的应用程序。",2,"2026-06-11 03:09:17","top_language"]