本文へ移動
cccskills
無料GitHub で公開

carplay

Build CarPlay-enabled apps using the CarPlay framework. Use when creating navigation, audio, communication, EV charging, parking, or food ordering apps for the car display, working with CPTemplateApplicationScene, CPListTemplate, CPMapTemplate, CPNowPlayingTemplate, configuring CarPlay entitlements, or integrating with CarPlay Simulator for testing.

インストール方法を見る

含まれるファイル(2)

  • SKILL.md16.8 KB
  • references/carplay-patterns.md17.6 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

CarPlay

Build apps that display on the vehicle's CarPlay screen using the CarPlay framework's template-based UI system. Covers scene lifecycle, template types, navigation guidance, audio playback, communication, point-of-interest categories, entitlement setup, and simulator testing. Targets Swift 6.3 / iOS 26+.

See references/carplay-patterns.md for extended patterns including full navigation sessions, dashboard scenes, and advanced template composition.

Contents

Entitlements and Setup

CarPlay requires a category-specific entitlement granted by Apple. Request it at developer.apple.com/contact/carplay and agree to the CarPlay Entitlement Addendum.

Entitlement Keys by Category

EntitlementCategory
com.apple.developer.carplay-audioAudio
com.apple.developer.carplay-communicationCommunication
com.apple.developer.carplay-mapsNavigation
com.apple.developer.carplay-chargingEV Charging
com.apple.developer.carplay-parkingParking
com.apple.developer.carplay-quick-orderingQuick Food Ordering

Project Configuration

  1. Update the App ID in the developer portal under Additional Capabilities.
  2. Generate a new provisioning profile for the updated App ID.
  3. In Xcode, disable automatic signing and import the CarPlay provisioning profile.
  4. Add an Entitlements.plist with the entitlement key set to true.
  5. Set Code Signing Entitlements build setting to the Entitlements.plist path.

Key Types

TypeRole
CPTemplateApplicationSceneUIScene subclass for the CarPlay display
CPTemplateApplicationSceneDelegateScene connect/disconnect lifecycle
CPInterfaceControllerManages the template navigation hierarchy
CPTemplateAbstract base for all CarPlay templates
CPSessionConfigurationVehicle display limits and content style

Scene Configuration

Declare the CarPlay scene in Info.plist and implement CPTemplateApplicationSceneDelegate to respond when CarPlay connects.

Info.plist Scene Manifest

<key>UIApplicationSceneManifest</key>
<dict>
    <key>UIApplicationSupportsMultipleScenes</key>
    <true/>
    <key>UISceneConfigurations</key>
    <dict>
        <key>CPTemplateApplicationSceneSessionRoleApplication</key>
        <array>
            <dict>
                <key>UISceneClassName</key>
                <string>CPTemplateApplicationScene</string>
                <key>UISceneConfigurationName</key>
                <string>CarPlaySceneConfiguration</string>
                <key>UISceneDelegateClassName</key>
                <string>$(PRODUCT_MODULE_NAME).CarPlaySceneDelegate</string>
            </dict>
        </array>
    </dict>
</dict>

Scene Delegate (Non-Navigation)

Non-navigation apps receive an interface controller only. No window.

import CarPlay

final class CarPlaySceneDelegate: UIResponder,
    CPTemplateApplicationSceneDelegate {

    var interfaceController: CPInterfaceController?

    func templateApplicationScene(
        _ templateApplicationScene: CPTemplateApplicationScene,
        didConnect interfaceController: CPInterfaceController
    ) {
        self.interfaceController = interfaceController
        interfaceController.setRootTemplate(buildRootTemplate(),
                                            animated: true, completion: nil)
    }

    func templateApplicationScene(
        _ templateApplicationScene: CPTemplateApplicationScene,
        didDisconnectInterfaceController interfaceController: CPInterfaceController
    ) {
        self.interfaceController = nil
    }
}

Scene Delegate (Navigation)

Navigation apps receive both an interface controller and a CPWindow. Set the window's root view controller to draw map content.

func templateApplicationScene(
    _ templateApplicationScene: CPTemplateApplicationScene,
    didConnect interfaceController: CPInterfaceController,
    to window: CPWindow
) {
    self.interfaceController = interfaceController
    self.carWindow = window
    window.rootViewController = MapViewController()

    let mapTemplate = CPMapTemplate()
    mapTemplate.mapDelegate = self
    interfaceController.setRootTemplate(mapTemplate, animated: true,
                                        completion: nil)
}

Templates Overview

CarPlay provides a fixed set of template types. The app supplies content; the system renders it on the vehicle display.

General Purpose Templates

TemplatePurpose
CPTabBarTemplateContainer with tabbed child templates
CPListTemplateScrollable sectioned list
CPGridTemplateGrid of tappable icon buttons (max 8)
CPInformationTemplateKey-value info with up to 3 actions
CPAlertTemplateModal alert with up to 2 actions
CPActionSheetTemplateModal action sheet

Category-Specific Templates

TemplateCategory
CPMapTemplateNavigation -- map overlay with nav bar
CPSearchTemplateNavigation -- destination search
CPNowPlayingTemplateAudio -- shared Now Playing screen
CPPointOfInterestTemplateEV Charging / Parking / Food -- POI map
CPContactTemplateCommunication -- contact card

Navigation Hierarchy

Use pushTemplate(_:animated:completion:) to add templates to the stack. Use presentTemplate(_:animated:completion:) for modal display. Use popTemplate(animated:completion:) to go back. CPTabBarTemplate must be set as root -- it cannot be pushed or presented.

CPTabBarTemplate

let browseTab = CPListTemplate(title: "Browse",
                               sections: [CPListSection(items: listItems)])
browseTab.tabImage = UIImage(systemName: "list.bullet")

let tabBar = CPTabBarTemplate(templates: [browseTab, settingsTab])
tabBar.delegate = self
interfaceController.setRootTemplate(tabBar, animated: true, completion: nil)

CPListTemplate

let item = CPListItem(text: "Favorites", detailText: "12 items")
item.handler = { selectedItem, completion in
    self.interfaceController?.pushTemplate(detailTemplate, animated: true,
                                           completion: nil)
    completion()
}

let section = CPListSection(items: [item], header: "Library",
                            sectionIndexTitle: nil)
let listTemplate = CPListTemplate(title: "My App", sections: [section])

Navigation Apps

Navigation apps use com.apple.developer.carplay-maps. They are the only category that receives a CPWindow for drawing map content. The root template must be a CPMapTemplate.

Trip Preview and Route Selection

let routeChoice = CPRouteChoice(
    summaryVariants: ["Fastest Route", "Fast"],
    additionalInformationVariants: ["Via Highway 101"],
    selectionSummaryVariants: ["25 min"]
)
let trip = CPTrip(origin: origin, destination: destination,
                  routeChoices: [routeChoice])
mapTemplate.showTripPreviews([trip], textConfiguration: nil)

Starting a Navigation Session

extension CarPlaySceneDelegate: CPMapTemplateDelegate {
    func mapTemplate(_ mapTemplate: CPMapTemplate,
                     startedTrip trip: CPTrip,
                     using routeChoice: CPRouteChoice) {
        let session = mapTemplate.startNavigationSession(for: trip)
        session.pauseTrip(for: .loading, description: "Calculating route...")

        let maneuver = CPManeuver()
        maneuver.instructionVariants = ["Turn right onto Main St"]
        maneuver.symbolImage = UIImage(systemName: "arrow.turn.up.right")
        session.upcomingManeuvers = [maneuver]

        let estimates = CPTravelEstimates(
            distanceRemaining: Measurement(value: 5.2, unit: .miles),
            timeRemaining: 900)
        session.updateEstimates(estimates, for: maneuver)
    }
}

Map Buttons

let zoomIn = CPMapButton { _ in self.mapViewController.zoomIn() }
zoomIn.image = UIImage(systemName: "plus.magnifyingglass")
mapTemplate.mapButtons = [zoomIn, zoomOut]

CPSearchTemplate

extension CarPlaySceneDelegate: CPSearchTemplateDelegate {
    func searchTemplate(_ searchTemplate: CPSearchTemplate,
                        updatedSearchText searchText: String,
                        completionHandler: @escaping ([CPListItem]) -> Void) {
        performSearch(query: searchText) { results in
            completionHandler(results.map {
                CPListItem(text: $0.name, detailText: $0.address)
            })
        }
    }

    func searchTemplate(_ searchTemplate: CPSearchTemplate,
                        selectedResult item: CPListItem,
                        completionHandler: @escaping () -> Void) {
        // Navigate to selected destination
        completionHandler()
    }
}

Audio Apps

Audio apps use com.apple.developer.carplay-audio. They display browsable content in lists and use CPNowPlayingTemplate for playback controls.

Now Playing Template

CPNowPlayingTemplate is a shared singleton. It reads metadata from MPNowPlayingInfoCenter. Do not instantiate a new one.

let nowPlaying = CPNowPlayingTemplate.shared
nowPlaying.isUpNextButtonEnabled = true
nowPlaying.isAlbumArtistButtonEnabled = true
nowPlaying.updateNowPlayingButtons([
    CPNowPlayingShuffleButton { _ in self.toggleShuffle() },
    CPNowPlayingRepeatButton { _ in self.toggleRepeat() }
])
nowPlaying.add(self) // Register as CPNowPlayingTemplateObserver

Siri Assistant Cell

Audio apps supporting INPlayMediaIntent can show an assistant cell. Communication apps use INStartCallIntent with .startCall.

let config = CPAssistantCellConfiguration(
    position: .top, visibility: .always, assistantAction: .playMedia)
let listTemplate = CPListTemplate(
    title: "Playlists",
    sections: [CPListSection(items: items)],
    assistantCellConfiguration: config)

Communication Apps

Communication apps use com.apple.developer.carplay-communication. They display message lists and contacts, and support INStartCallIntent for Siri-initiated calls.

let message = CPMessageListItem(
    conversationIdentifier: "conv-123",
    text: "Meeting at 3pm",
    leadingConfiguration: CPMessageListItem.LeadingConfiguration(
        leadingItem: .init(text: "Jane", textStyle: .abbreviated),
        unread: true),
    trailingConfiguration: CPMessageListItem.TrailingConfiguration(
        trailingItem: .init(text: "2:45 PM")),
    trailingText: nil, trailingImage: nil)

let messageList = CPListTemplate(title: "Messages",
                                 sections: [CPListSection(items: [message])])

Point of Interest Apps

EV charging, parking, and food ordering apps use CPPointOfInterestTemplate and CPInformationTemplate to display locations and details.

CPPointOfInterestTemplate

let poi = CPPointOfInterest(
    location: MKMapItem(placemark: MKPlacemark(
        coordinate: CLLocationCoordinate2D(latitude: 37.7749,
                                           longitude: -122.4194))),
    title: "SuperCharger Station", subtitle: "4 available",
    summary: "150 kW DC fast charging",
    detailTitle: "SuperCharger Station", detailSubtitle: "$0.28/kWh",
    detailSummary: "Open 24 hours",
    pinImage: UIImage(systemName: "bolt.fill"))

poi.primaryButton = CPTextButton(title: "Navigate",
                                 textStyle: .confirm) { _ in }

let poiTemplate = CPPointOfInterestTemplate(
    title: "Nearby Chargers", pointsOfInterest: [poi], selectedIndex: 0)
poiTemplate.pointOfInterestDelegate = self

CPInformationTemplate

let infoTemplate = CPInformationTemplate(
    title: "Order Summary", layout: .leading,
    items: [
        CPInformationItem(title: "Item", detail: "Burrito Bowl"),
        CPInformationItem(title: "Total", detail: "$12.50")],
    actions: [
        CPTextButton(title: "Place Order", textStyle: .confirm) { _ in
            self.placeOrder() },
        CPTextButton(title: "Cancel", textStyle: .cancel) { _ in
            self.interfaceController?.popTemplate(animated: true,
                                                  completion: nil) }])

Testing with CarPlay Simulator

  1. Build and run in Xcode with the iOS simulator.
  2. Choose I/O > External Displays > CarPlay.

Default window: 800x480 at @2x. Enable extra options for navigation apps:

defaults write com.apple.iphonesimulator CarPlayExtraOptions -bool YES

Recommended Test Configurations

ConfigurationPixelsScale
Minimum748 x 456@2x
Portrait768 x 1024@2x
Standard800 x 480@2x
High-resolution1920 x 720@3x

Simulator cannot test locked-iPhone behavior, Siri, audio coexistence with car radio, or physical input hardware (knobs, touch pads). Test on a real CarPlay-capable vehicle or aftermarket head unit when possible.

Common Mistakes

DON'T: Use the wrong scene delegate method

Navigation apps must implement templateApplicationScene(_:didConnect:to:) (with CPWindow). Non-navigation apps use templateApplicationScene(_:didConnect:) (no window). Using the wrong variant produces no CarPlay UI.

DON'T: Draw custom UI in the navigation window

CPWindow is exclusively for map content. All overlays, alerts, and controls must use CarPlay templates.

DON'T: Push or present CPTabBarTemplate

CPTabBarTemplate can only be set as root. Pushing or presenting it fails. Use setRootTemplate(_:animated:completion:).

DON'T: Instantiate CPNowPlayingTemplate

Use CPNowPlayingTemplate.shared. Creating a new instance causes issues.

DON'T: Ignore vehicle display limits

Check CPSessionConfiguration.limitedUserInterfaces and respect maximumItemCount / maximumSectionCount on list templates.

DON'T: Forget to call the completion handler

CPListItem.handler must call its completion handler in every code path. Failure leaves the list in a loading state.

Review Checklist

  • Correct CarPlay entitlement key in Entitlements.plist
  • UIApplicationSupportsMultipleScenes set to true
  • CPTemplateApplicationSceneSessionRoleApplication scene in Info.plist
  • Scene delegate class name matches UISceneDelegateClassName
  • Correct delegate method used (with/without CPWindow)
  • Root template set in didConnect before returning
  • Interface controller and window references cleared on disconnect
  • CPTabBarTemplate only used as root, never pushed
  • CPNowPlayingTemplate.shared used, not a new instance
  • maximumItemCount/maximumSectionCount checked before populating lists
  • CPListItem.handler calls completion in every path
  • Map-only content in CPWindow root view controller (navigation apps)
  • App functions while iPhone is locked
  • Tested at minimum, standard, and high-resolution simulator sizes
  • Audio session deactivated when not actively playing

References

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

When the user wants to A/B test App Store product page elements to improve conversion rate. Also use when the user mentions "A/B test", "product page optimization", "test my screenshots", "test my icon", "conversion rate optimization", "CPP", or "custom product pages". For screenshot design, see screenshot-optimization. For metadata optimization, see metadata-optimization.

日本語の概要は準備中です。原文の説明を表示しています。

JordanCoin/ios-skills-collection62026年9月10日 更新

Discover and configure Bluetooth and Wi-Fi accessories using AccessorySetupKit. Use when presenting a privacy-preserving accessory picker, defining discovery descriptors for BLE or Wi-Fi devices, handling accessory session events, migrating from CoreBluetooth permission-based scanning, or setting up accessories without requiring broad Bluetooth permissions.

日本語の概要は準備中です。原文の説明を表示しています。

JordanCoin/ios-skills-collection62026年9月10日 更新

Implement, review, or improve Live Activities and Dynamic Island experiences in iOS apps using ActivityKit. Use when building real-time updating widgets for the Lock Screen and Dynamic Island — delivery tracking, sports scores, ride-sharing status, workout timers, media playback, or any time-sensitive information that updates in real time. Also use when working with ActivityKit, ActivityAttributes, Activity lifecycle (request/update/end), Dynamic Island layouts (compact/minimal/expanded), push-to-update Live Activities, or Lock Screen live widgets.

日本語の概要は準備中です。原文の説明を表示しています。

JordanCoin/ios-skills-collection62026年9月10日 更新

Measure ad effectiveness with privacy-preserving attribution using AdAttributionKit. Use when registering ad impressions, handling attribution postbacks, updating conversion values, implementing re-engagement attribution, configuring publisher or advertiser apps, or replacing SKAdNetwork with AdAttributionKit for ad measurement.

日本語の概要は準備中です。原文の説明を表示しています。

JordanCoin/ios-skills-collection62026年9月10日 更新

alarmkit

無料

Implement AlarmKit alarms and countdown timers for iOS and iPadOS with Lock Screen, Dynamic Island, and Apple Watch system UI. Covers AlarmManager scheduling, AlarmAttributes and AlarmPresentation, AlarmButton stop and snooze actions, authorization, state observation, and Live Activity integration. Use when building wake-up alarms, countdown timers, or alarm-style alerts that need Apple's system alarm experience.

日本語の概要は準備中です。原文の説明を表示しています。

JordanCoin/ios-skills-collection62026年9月10日 更新

When the user wants to optimize their Google Play Store listing — title, short description, full description, keywords, ratings, or Play Store-specific features. Use when the user mentions "Google Play", "Android", "Play Store", "Play Console", "short description", "full description indexed", "Google Play ASO", or wants Google Play-specific keyword, creative, or ratings strategy. For iOS App Store optimization, see aso-audit and metadata-optimization.

日本語の概要は準備中です。原文の説明を表示しています。

JordanCoin/ios-skills-collection62026年9月10日 更新

JordanCoin のスキルをすべて見る

このスキルの問題を報告する