dpearson2699/swift-ios-skills3 files

Permissionkit

Create child communication safety experiences using PermissionKit to request parental permission for children. Use when building apps that involve child-to-contact communication, need to check communication limits, request parent/guardian approval, or handle permission responses for minors.

Specification
Skill ID
dpearson2699/swift-ios-skills/permissionkit
Publisher
dpearson2699
Repository
swift-ios-skills
Installs
0
Files
3
Synced
Sep 23, 2026
How to use it

Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.

dpearson2699/swift-ios-skills/permissionkitInstalls these files
  • SKILL.md
  • evals/evals.json
  • references/permissionkit-patterns.md

What this skill tells the agent

PermissionKit

Request permission from a parent or guardian to modify a child's communication rules. PermissionKit creates communication safety experiences that let children ask for exceptions to communication limits set by their parents.

PermissionKit communication experiences are available only through iMessage. Use it for parent/guardian approval flows, not as a general in-app contact permission, moderation, or chat-safety framework.

Contents

  • Availability and Setup
  • Core Concepts
  • Checking Communication Limits
  • Creating Permission Questions
  • Requesting Permission with AskCenter
  • SwiftUI Integration with PermissionButton
  • Handling Responses
  • Significant App Update Topic
  • Common Mistakes
  • Review Checklist
  • References

Availability and Setup

Import PermissionKit. Do not invent PermissionKit entitlement keys; verify current Apple documentation and Xcode capabilities before adding signing requirements.

import PermissionKit

Use this centralized version matrix and verify it against the current SDK:

TierAPIsiOS/iPadOS/Mac Catalyst/macOS/visionOS
CoreTopics, handles, questions, responses, choices, CommunicationLimits26.0+
ErrorsAskError26.1+
PresentationAskCenter, ask/response sequences, PermissionButton, significant-update topics26.2+

Core Concepts

PermissionKit manages a flow where:

  1. A child encounters a communication limit in your app
  2. Your app creates a PermissionQuestion describing the request
  3. The system presents the question to the child for them to send to their parent
  4. The parent reviews and approves or denies the request
  5. Your app receives a PermissionResponse with the parent's decision

Key Types

TypeRole
AskCenterSingleton that manages permission requests and responses
PermissionQuestionDescribes the permission being requested
PermissionResponseThe parent's decision (approval or denial)
PermissionChoiceThe specific answer (approve/decline)
PermissionButtonSwiftUI button that triggers the permission flow
CommunicationTopicTopic for communication-related permission requests
CommunicationHandleA phone number, email, or custom identifier
CommunicationLimitsChecks which communication handles are known to the system
SignificantAppUpdateTopicTopic for significant app update permission requests

Checking Communication Limits

Use CommunicationLimits.current to check whether the system already knows a communication handle for your app. This is not an "are communication limits enabled?" probe. If limits are not enabled, AskCenter.shared.ask(_:in:) throws AskError.communicationLimitsNotEnabled; handle that path when asking.

knownHandles(in:) also requires the calling app to have a non-nil, nonempty bundle identifier. Corrected code should guard Bundle.main.bundleIdentifier before calling it.

import PermissionKit

func needsPermissionPrompt(for handle: CommunicationHandle) async -> Bool {
    let limits = CommunicationLimits.current
    let isKnown = await limits.isKnownHandle(handle)
    return !isKnown
}

// Check multiple handles at once.
func filterKnownHandles(_ handles: Set<CommunicationHandle>) async -> Set<CommunicationHandle> {
    guard Bundle.main.bundleIdentifier?.isEmpty == false else { return [] }

    let limits = CommunicationLimits.current
    return await limits.knownHandles(in: handles)
}

Creating Communication Handles

let phoneHandle = CommunicationHandle(
    value: "+1234567890",
    kind: .phoneNumber
)

let emailHandle = CommunicationHandle(
    value: "friend@example.com",
    kind: .emailAddress
)

let customHandle = CommunicationHandle(
    value: "user123",
    kind: .custom
)

Creating Permission Questions

Build a PermissionQuestion with the contact information and communication action type.

// Question for a single contact
let handle = CommunicationHandle(value: "+1234567890", kind: .phoneNumber)
let question = PermissionQuestion<CommunicationTopic>(handle: handle)

// Question for multiple contacts
let handles = [
    CommunicationHandle(value: "+1234567890", kind: .phoneNumber),
    CommunicationHandle(value: "friend@example.com", kind: .emailAddress)
]
let multiQuestion = PermissionQuestion<CommunicationTopic>(handles: handles)

Using CommunicationTopic with Person Information

Provide display names and avatars for a richer permission prompt.

let personInfo = CommunicationTopic.PersonInformation(
    handle: CommunicationHandle(value: "+1234567890", kind: .phoneNumber),
    nameComponents: {
        var name = PersonNameComponents()
        name.givenName = "Alex"
        name.familyName = "Smith"
        return name
    }(),
    avatarImage: nil
)

let topic = CommunicationTopic(
    personInformation: [personInfo],
    actions: [.message, .audioCall]
)

let question = PermissionQuestion<CommunicationTopic>(communicationTopic: topic)

Communication Actions

ActionDescription
.messageText messaging
.audioCallVoice call
.videoCallVideo call
.callGeneric call
.chatChat communication
.followFollow a user
.beFollowedAllow being followed
.friendFriend request
.connectConnection request
.communicateGeneric communication

Requesting Permission with AskCenter

Use AskCenter.shared to request that the child send the permission question to their parent or guardian. The async ask call starts the send flow; parent decisions arrive later through responses(for:). If the child cancels the send flow, the system does not deliver a PermissionResponse for that question.

import PermissionKit

func requestPermission(
    for question: PermissionQuestion<CommunicationTopic>,
    in viewController: UIViewController
) async {
    do {
        try await AskCenter.shared.ask(question, in: viewController)
        // Question send flow was started; wait for responses(for:) separately.
    } catch let error as AskError {
        switch error {
        case .communicationLimitsNotEnabled:
            // Communication limits not active -- continue with normal app flow.
            break
        case .contactSyncNotSetup:
            // Contact sync not configured
            break
        case .invalidQuestion:
            // Question is malformed
            break
        case .notAvailable:
            // PermissionKit not available on this device
            break
        case .systemError(let underlying):
            print("System error: \(underlying)")
        case .unknown:
            break
        @unknown default:
            break
        }
    }
}

SwiftUI Integration with PermissionButton

PermissionButton is a SwiftUI view that triggers the permission flow when tapped. It uses the same response model as AskCenter: observe responses and model a pending/canceled state instead of assuming every tap produces a parent decision.

import SwiftUI
import PermissionKit

struct ContactPermissionView: View {
    let handle = CommunicationHandle(value: "+1234567890", kind: .phoneNumber)

    var body: some View {
        let question = PermissionQuestion<CommunicationTopic>(handle: handle)

        PermissionButton(question: question) {
            Label("Ask to Message", systemImage: "message")
        }
    }
}

For richer SwiftUI flows, custom topics, and long-lived managers, read references/permissionkit-patterns.md.

Handling Responses

Use this skill in a project

Open any RiverX project, search the Skills panel for dpearson2699/swift-ios-skills/permissionkit, and install it in one click.

Use this skill