carplay

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

CarPlay Skill

CarPlay 开发技能

When to Use This Skill

何时使用该技能

Use this skill when:
  • Developing CarPlay apps for iOS
  • Building audio, podcast, or music apps for CarPlay
  • Creating navigation apps with turn-by-turn guidance
  • Implementing communication apps (messaging, VoIP)
  • Building parking, EV charging, or food ordering apps
  • Working with CPTemplate, CPInterfaceController, or any CarPlay APIs
在以下场景使用本技能:
  • 开发iOS平台的CarPlay应用
  • 构建CarPlay音频、播客或音乐应用
  • 创建带逐向导航的导航应用
  • 实现通讯应用(消息、VoIP)
  • 开发停车、电动汽车充电或外卖点餐应用
  • 使用CPTemplate、CPInterfaceController或任何CarPlay API

Description

内容简介

Complete CarPlay framework documentation covering audio, communication, navigation, parking, EV charging, and food ordering integrations. Includes all templates (CPListTemplate, CPMapTemplate, CPGridTemplate, etc.), UI elements, and navigation APIs.
完整的CarPlay框架文档,涵盖音频、通讯、导航、停车、电动汽车充电和外卖点餐的集成内容。包含所有模板(CPListTemplate、CPMapTemplate、CPGridTemplate等)、UI元素和导航API。

Quick Reference

快速参考

Core Components

核心组件

Api Reference

API参考

  • CPInterfaceController
  • CPWindow
  • CarPlay
  • CPInterfaceController
  • CPWindow
  • CarPlay

Communication

通讯模块

  • CPContact
  • CPMessageListItem
  • CPContact
  • CPMessageListItem

Getting Started

入门指南

  • CPSessionConfiguration
  • CPTemplateApplicationScene
  • CPTemplateApplicationSceneDelegate
  • CPSessionConfiguration
  • CPTemplateApplicationScene
  • CPTemplateApplicationSceneDelegate

Navigation

导航模块

  • CPManeuver
  • CPNavigationSession
  • CPRouteChoice
  • CPTrip
  • CPManeuver
  • CPNavigationSession
  • CPRouteChoice
  • CPTrip

Poi

兴趣点(POI)

  • CPPointOfInterest
  • CPPointOfInterest

Templates

模板

  • CPActionSheetTemplate
  • CPAlertTemplate
  • CPContactTemplate
  • CPGridTemplate
  • CPInformationTemplate
  • CPListTemplate
  • CPMapTemplate
  • CPNowPlayingTemplate
  • CPPointOfInterestTemplate
  • CPSearchTemplate
  • CPTabBarTemplate
  • CPTemplate
  • CPVoiceControlTemplate
  • CPActionSheetTemplate
  • CPAlertTemplate
  • CPContactTemplate
  • CPGridTemplate
  • CPInformationTemplate
  • CPListTemplate
  • CPMapTemplate
  • CPNowPlayingTemplate
  • CPPointOfInterestTemplate
  • CPSearchTemplate
  • CPTabBarTemplate
  • CPTemplate
  • CPVoiceControlTemplate

Ui Elements

UI元素

  • CPAlertAction
  • CPBarButton
  • CPButton
  • CPGridButton
  • CPInformationItem
  • CPListImageRowItem
  • CPListItem
  • CPListSection
  • CPTextButton
  • CPAlertAction
  • CPBarButton
  • CPButton
  • CPGridButton
  • CPInformationItem
  • CPListImageRowItem
  • CPListItem
  • CPListSection
  • CPTextButton

Dashboard (iOS 13.4+)

仪表盘(iOS 13.4+)

  • CPDashboardButton
  • CPDashboardController
  • CPTemplateApplicationDashboardScene
  • CPTemplateApplicationDashboardSceneDelegate
  • CPDashboardButton
  • CPDashboardController
  • CPTemplateApplicationDashboardScene
  • CPTemplateApplicationDashboardSceneDelegate

Instrument Cluster (iOS 15.4+)

仪表集群(iOS 15.4+)

  • CPInstrumentClusterController
  • CPTemplateApplicationInstrumentClusterScene
  • CPTemplateApplicationInstrumentClusterSceneDelegate
  • CPInstrumentClusterController
  • CPTemplateApplicationInstrumentClusterScene
  • CPTemplateApplicationInstrumentClusterSceneDelegate

Key Concepts

核心概念

Platform Support

平台支持

  • iOS 12.0+ (Core CarPlay)
  • iOS 13.4+ (Dashboard scenes)
  • iOS 14.0+ (Tab Bar, POI, Now Playing)
  • iOS 15.4+ (Instrument Cluster)
  • iOS 17.4+ (CPRouteInformation)
  • iPadOS 12.0+
  • Mac Catalyst 13.1+
  • iOS 12.0+(核心CarPlay功能)
  • iOS 13.4+(仪表盘场景)
  • iOS 14.0+(标签栏、POI、Now Playing)
  • iOS 15.4+(仪表集群)
  • iOS 17.4+(CPRouteInformation)
  • iPadOS 12.0+
  • Mac Catalyst 13.1+

CarPlay App Categories

CarPlay应用分类

⚠️ Important: CarPlay apps require entitlements from Apple. You must request and receive approval for your specific app category before your app can connect to CarPlay.
CarPlay supports apps in the following categories (each requires a separate entitlement):
  • Audio & Podcasts: Music, podcasts, audiobooks, and radio apps
    • Entitlement:
      com.apple.developer.carplay-audio
    • Requirements: Audio playback, Now Playing integration
  • Communication: Messaging and VoIP calling apps
    • Entitlement:
      com.apple.developer.carplay-communication
    • Requirements: CallKit integration, Siri integration
  • Navigation: Turn-by-turn navigation and maps
    • Entitlement:
      com.apple.developer.carplay-maps
    • Requirements: Real-time navigation, route guidance
  • Parking: Finding and paying for parking
    • Entitlement:
      com.apple.developer.carplay-parking
    • Requirements: Location services, parking availability
  • EV Charging: Locating and managing electric vehicle charging
    • Entitlement:
      com.apple.developer.carplay-charging
    • Requirements: Charging station data, availability status
  • Food Ordering: Quick service food ordering
    • Entitlement:
      com.apple.developer.carplay-quick-food
    • Requirements: Menu browsing, order placement
How to request entitlements:
  1. Visit https://developer.apple.com/contact/carplay/
  2. Describe your app's functionality and category
  3. Wait for Apple's review and approval (typically 1-2 weeks)
  4. Add the approved entitlement to your Xcode project
⚠️ 重要提示: CarPlay应用需要苹果的权限授权。在应用连接CarPlay前,你必须针对特定应用类别申请并获得苹果的批准。
CarPlay支持以下类别的应用(每个类别需要单独的权限):
  • 音频与播客:音乐、播客、有声书和广播应用
    • 权限:
      com.apple.developer.carplay-audio
    • 要求:音频播放、Now Playing集成
  • 通讯:消息和VoIP通话应用
    • 权限:
      com.apple.developer.carplay-communication
    • 要求:CallKit集成、Siri集成
  • 导航:逐向导航和地图应用
    • 权限:
      com.apple.developer.carplay-maps
    • 要求:实时导航、路线指引
  • 停车服务:查找和支付停车费的应用
    • 权限:
      com.apple.developer.carplay-parking
    • 要求:定位服务、停车位状态查询
  • 电动汽车充电:查找和管理电动汽车充电的应用
    • 权限:
      com.apple.developer.carplay-charging
    • 要求:充电站数据、可用状态查询
  • 外卖点餐:快餐点餐应用
    • 权限:
      com.apple.developer.carplay-quick-food
    • 要求:菜单浏览、下单功能
如何申请权限:
  1. 访问 https://developer.apple.com/contact/carplay/
  2. 描述你的应用功能和所属类别
  3. 等待苹果的审核和批准(通常1-2周)
  4. 在Xcode项目中添加已获批的权限

Template-Based UI

基于模板的UI系统

CarPlay uses a template-based system where Apple provides the UI components and you provide the content. This ensures:
  • Driver-safe interfaces optimized for in-car use
  • Consistent user experience across all CarPlay apps
  • Automatic adaptation to different vehicle displays
CarPlay采用基于模板的系统,由苹果提供UI组件,开发者提供内容。这确保了:
  • 为车载使用优化的驾驶员安全界面
  • 所有CarPlay应用的一致用户体验
  • 自动适配不同车辆的显示屏

Usage Guidelines

使用指南

  1. Use appropriate templates for your app category
  2. Keep content simple - limit items and text for driver safety
  3. Provide large, clear images for better visibility
  4. Handle connection/disconnection gracefully
  5. Test in CarPlay Simulator before testing in vehicle
  6. Follow distraction guidelines - no video, animations, or ads while driving
  1. 为应用类别选择合适的模板
  2. 保持内容简洁 - 为了驾驶员安全,限制项目数量和文本内容
  3. 提供大尺寸、清晰的图片以提升可见性
  4. 优雅处理连接/断开连接的情况
  5. 在车载测试前先在CarPlay模拟器中测试
  6. 遵循防干扰指南 - 驾驶时不显示视频、动画或广告

Testing with CarPlay Simulator

使用CarPlay模拟器测试

The CarPlay Simulator in Xcode allows you to test your app without a physical vehicle:
Setup:
  1. Open your CarPlay app project in Xcode
  2. Select an iOS Simulator as your run destination
  3. In the Simulator menu: I/O > External Displays > CarPlay
  4. A CarPlay display window will appear alongside the iOS simulator
Simulator Features:
  • Test all CarPlay templates and UI elements
  • Simulate day/night modes (automatic based on system dark mode)
  • Test different screen sizes and aspect ratios
  • Simulate Siri interactions and voice commands
  • Test connection/disconnection scenarios
  • Debug layout issues before vehicle testing
Limitations:
  • Cannot test actual vehicle integration
  • Limited testing of physical controls (knobs, touchscreens)
  • Some vehicle-specific features unavailable
  • Audio routing may differ from actual vehicles
Best Practice: Always test in the simulator first, then verify in a physical vehicle or CarPlay-compatible head unit before release.
Xcode中的CarPlay模拟器允许你无需实体车辆即可测试应用:
设置步骤:
  1. 在Xcode中打开你的CarPlay应用项目
  2. 选择iOS模拟器作为运行目标
  3. 在模拟器菜单中:I/O > 外部显示器 > CarPlay
  4. CarPlay显示窗口将与iOS模拟器一同出现
模拟器功能:
  • 测试所有CarPlay模板和UI元素
  • 模拟日/夜模式(根据系统深色模式自动切换)
  • 测试不同屏幕尺寸和宽高比
  • 模拟Siri交互和语音命令
  • 测试连接/断开连接场景
  • 在车载测试前调试布局问题
局限性:
  • 无法测试实际车辆集成
  • 物理控制(旋钮、触摸屏)的测试有限
  • 部分车辆专属功能不可用
  • 音频路由可能与实际车辆不同
最佳实践: 发布前始终先在模拟器中测试,然后在实体车辆或CarPlay兼容的车机中验证。

Navigation

导航模块

See the
references/
directory for detailed API documentation organized by category:
  • references/api_reference.md
    - Api Reference
  • references/communication.md
    - Communication
  • references/dashboard.md
    - Dashboard and Instrument Cluster
  • references/getting_started.md
    - Getting Started
  • references/navigation.md
    - Navigation
  • references/poi.md
    - Poi
  • references/templates.md
    - Templates
  • references/ui_elements.md
    - Ui Elements
按类别组织的详细API文档请查看
references/
目录:
  • references/api_reference.md
    - API参考
  • references/communication.md
    - 通讯模块
  • references/dashboard.md
    - 仪表盘与仪表集群
  • references/getting_started.md
    - 入门指南
  • references/navigation.md
    - 导航模块
  • references/poi.md
    - 兴趣点(POI)
  • references/templates.md
    - 模板
  • references/ui_elements.md
    - UI元素

Best Practices

最佳实践

  • Scene Management: Implement
    CPTemplateApplicationSceneDelegate
    to handle CarPlay connection
  • Template Limits: Respect maximum item counts (CPListTemplate: 12 sections, CPGridTemplate: 8 buttons)
  • Image Sizes: Follow recommended image sizes for templates and UI elements
  • Dynamic Updates: Use update methods (
    updateSections
    ,
    updateButtons
    ) to refresh content
  • Navigation Hierarchy: Use push/pop for navigation, present for modals
  • Error Handling: Gracefully handle failures and provide user feedback
  • 场景管理:实现
    CPTemplateApplicationSceneDelegate
    以处理CarPlay连接
  • 模板限制:遵守最大项目数量限制(CPListTemplate:12个分区,CPGridTemplate:8个按钮)
  • 图片尺寸:遵循模板和UI元素推荐的图片尺寸
  • 动态更新:使用更新方法(
    updateSections
    updateButtons
    )刷新内容
  • 导航层级:使用push/pop进行导航,present展示模态窗口
  • 错误处理:优雅处理失败情况并提供用户反馈

Common Patterns

常见实现模式

Basic List Template

基础列表模板

swift
// Create list items
let item1 = CPListItem(text: "Song Title", detailText: "Artist Name")
item1.handler = { item, completion in
    // Handle selection
    completion()
}

// Create section and template
let section = CPListSection(items: [item1, item2])
let listTemplate = CPListTemplate(title: "My Playlist", sections: [section])

// Set as root
interfaceController.setRootTemplate(listTemplate, animated: true)
swift
// Create list items
let item1 = CPListItem(text: "Song Title", detailText: "Artist Name")
item1.handler = { item, completion in
    // Handle selection
    completion()
}

// Create section and template
let section = CPListSection(items: [item1, item2])
let listTemplate = CPListTemplate(title: "My Playlist", sections: [section])

// Set as root
interfaceController.setRootTemplate(listTemplate, animated: true)

Navigation with Map Template

带地图模板的导航

swift
// Create map template
let mapTemplate = CPMapTemplate()
mapTemplate.mapDelegate = self

// Show trip preview
let trip = CPTrip(/* route data */)
mapTemplate.showTripPreviews([trip], textConfiguration: nil)

// Start navigation
let navigationSession = mapTemplate.startNavigationSession(for: trip)
navigationSession.upcomingManeuvers = [maneuver1, maneuver2]
swift
// Create map template
let mapTemplate = CPMapTemplate()
mapTemplate.mapDelegate = self

// Show trip preview
let trip = CPTrip(/* route data */)
mapTemplate.showTripPreviews([trip], textConfiguration: nil)

// Start navigation
let navigationSession = mapTemplate.startNavigationSession(for: trip)
navigationSession.upcomingManeuvers = [maneuver1, maneuver2]

Tab Bar Template

标签栏模板

swift
// Create root templates for each tab
let musicTab = CPListTemplate(title: "Music", sections: [musicSection])
musicTab.tabTitle = "Music"
musicTab.tabImage = UIImage(systemName: "music.note")

let podcastsTab = CPListTemplate(title: "Podcasts", sections: [podcastSection])
podcastsTab.tabTitle = "Podcasts"
podcastsTab.tabImage = UIImage(systemName: "mic")

// Create tab bar
let tabBarTemplate = CPTabBarTemplate(templates: [musicTab, podcastsTab])
interfaceController.setRootTemplate(tabBarTemplate, animated: false)
swift
// Create root templates for each tab
let musicTab = CPListTemplate(title: "Music", sections: [musicSection])
musicTab.tabTitle = "Music"
musicTab.tabImage = UIImage(systemName: "music.note")

let podcastsTab = CPListTemplate(title: "Podcasts", sections: [podcastSection])
podcastsTab.tabTitle = "Podcasts"
podcastsTab.tabImage = UIImage(systemName: "mic")

// Create tab bar
let tabBarTemplate = CPTabBarTemplate(templates: [musicTab, podcastsTab])
interfaceController.setRootTemplate(tabBarTemplate, animated: false)

Now Playing Template

Now Playing模板

swift
// Configure Now Playing buttons
let playButton = CPNowPlayingPlaybackRateButton()
let skipButton = CPNowPlayingSkipButton(handler: { _ in
    // Skip to next track
})

CPNowPlayingTemplate.shared.updateNowPlayingButtons([playButton, skipButton])
CPNowPlayingTemplate.shared.isUpNextButtonEnabled = true
swift
// Configure Now Playing buttons
let playButton = CPNowPlayingPlaybackRateButton()
let skipButton = CPNowPlayingSkipButton(handler: { _ in
    // Skip to next track
})

CPNowPlayingTemplate.shared.updateNowPlayingButtons([playButton, skipButton])
CPNowPlayingTemplate.shared.isUpNextButtonEnabled = true

Sports Mode for Live Events (iOS 18.4+)

赛事模式(iOS 18.4+)

swift
// Create team logos
let homeTeamLogo = CPNowPlayingSportsTeamLogo(teamLogo: UIImage(named: "home_logo")!)
let awayTeamLogo = CPNowPlayingSportsTeamLogo(teamInitials: "VIS")

// Create teams with scores and possession
let homeTeam = CPNowPlayingSportsTeam(
    name: "Home Team",
    logo: homeTeamLogo,
    teamStandings: "1st Place",
    eventScore: "21",
    possessionIndicator: .solid,  // Home team has possession
    favorite: true
)

let awayTeam = CPNowPlayingSportsTeam(
    name: "Away Team",
    logo: awayTeamLogo,
    teamStandings: "2nd Place",
    eventScore: "17",
    possessionIndicator: nil,  // No possession
    favorite: false
)

// Create game clock (counting down from 15:00)
let gameClock = CPNowPlayingSportsClock(
    timeRemaining: 15 * 60,  // 15 minutes in seconds
    paused: false
)

// Create event status with status text and clock
let eventStatus = CPNowPlayingSportsEventStatus(
    eventStatusText: ["3rd Quarter", "4th Down", "Goal Line"],
    eventStatusImage: UIImage(named: "field_position"),
    eventClock: gameClock
)

// Create sports mode
let sportsMode = CPNowPlayingModeSports(
    leftTeam: homeTeam,
    rightTeam: awayTeam,
    eventStatus: eventStatus,
    backgroundArtwork: UIImage(named: "stadium_background")
)

// Set as active now playing mode
CPNowPlayingTemplate.shared.nowPlayingMode = sportsMode

// Update clock during game (e.g., every second)
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
    // Update time remaining
    let newClock = CPNowPlayingSportsClock(
        timeRemaining: getCurrentGameTime(),
        paused: isGamePaused()
    )

    // Update event status with new clock
    let updatedStatus = CPNowPlayingSportsEventStatus(
        eventStatusText: eventStatus.eventStatusText,
        eventStatusImage: eventStatus.eventStatusImage,
        eventClock: newClock
    )

    // Refresh sports mode
    let updatedMode = CPNowPlayingModeSports(
        leftTeam: homeTeam,
        rightTeam: awayTeam,
        eventStatus: updatedStatus,
        backgroundArtwork: sportsMode.backgroundArtwork
    )

    CPNowPlayingTemplate.shared.nowPlayingMode = updatedMode
}
swift
// Create team logos
let homeTeamLogo = CPNowPlayingSportsTeamLogo(teamLogo: UIImage(named: "home_logo")!)
let awayTeamLogo = CPNowPlayingSportsTeamLogo(teamInitials: "VIS")

// Create teams with scores and possession
let homeTeam = CPNowPlayingSportsTeam(
    name: "Home Team",
    logo: homeTeamLogo,
    teamStandings: "1st Place",
    eventScore: "21",
    possessionIndicator: .solid,  // Home team has possession
    favorite: true
)

let awayTeam = CPNowPlayingSportsTeam(
    name: "Away Team",
    logo: awayTeamLogo,
    teamStandings: "2nd Place",
    eventScore: "17",
    possessionIndicator: nil,  // No possession
    favorite: false
)

// Create game clock (counting down from 15:00)
let gameClock = CPNowPlayingSportsClock(
    timeRemaining: 15 * 60,  // 15 minutes in seconds
    paused: false
)

// Create event status with status text and clock
let eventStatus = CPNowPlayingSportsEventStatus(
    eventStatusText: ["3rd Quarter", "4th Down", "Goal Line"],
    eventStatusImage: UIImage(named: "field_position"),
    eventClock: gameClock
)

// Create sports mode
let sportsMode = CPNowPlayingModeSports(
    leftTeam: homeTeam,
    rightTeam: awayTeam,
    eventStatus: eventStatus,
    backgroundArtwork: UIImage(named: "stadium_background")
)

// Set as active now playing mode
CPNowPlayingTemplate.shared.nowPlayingMode = sportsMode

// Update clock during game (e.g., every second)
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
    // Update time remaining
    let newClock = CPNowPlayingSportsClock(
        timeRemaining: getCurrentGameTime(),
        paused: isGamePaused()
    )

    // Update event status with new clock
    let updatedStatus = CPNowPlayingSportsEventStatus(
        eventStatusText: eventStatus.eventStatusText,
        eventStatusImage: eventStatus.eventStatusImage,
        eventClock: newClock
    )

    // Refresh sports mode
    let updatedMode = CPNowPlayingModeSports(
        leftTeam: homeTeam,
        rightTeam: awayTeam,
        eventStatus: updatedStatus,
        backgroundArtwork: sportsMode.backgroundArtwork
    )

    CPNowPlayingTemplate.shared.nowPlayingMode = updatedMode
}

Navigation with Maneuvers

带转向指引的导航

swift
// Create maneuvers for turn-by-turn guidance
let maneuver = CPManeuver()
maneuver.instructionVariants = ["Turn right onto Main Street"]
maneuver.symbolImage = UIImage(named: "turn-right")
maneuver.initialTravelEstimates = CPTravelEstimates(
    distanceRemaining: Measurement(value: 500, unit: UnitLength.meters),
    timeRemaining: 60
)

// Add lane guidance
let lane1 = CPLane(angles: [.left, .straight])
lane1.status = .recommended
let lane2 = CPLane(angles: [.straight, .right])
lane2.status = .preferred
maneuver.linkedLaneGuidance = CPLaneGuidance(lanes: [lane1, lane2], instructionVariants: ["Use right lane"])

// Add maneuver to navigation session
navigationSession.upcomingManeuvers = [maneuver]
swift
// Create maneuvers for turn-by-turn guidance
let maneuver = CPManeuver()
maneuver.instructionVariants = ["Turn right onto Main Street"]
maneuver.symbolImage = UIImage(named: "turn-right")
maneuver.initialTravelEstimates = CPTravelEstimates(
    distanceRemaining: Measurement(value: 500, unit: UnitLength.meters),
    timeRemaining: 60
)

// Add lane guidance
let lane1 = CPLane(angles: [.left, .straight])
lane1.status = .recommended
let lane2 = CPLane(angles: [.straight, .right])
lane2.status = .preferred
maneuver.linkedLaneGuidance = CPLaneGuidance(lanes: [lane1, lane2], instructionVariants: ["Use right lane"])

// Add maneuver to navigation session
navigationSession.upcomingManeuvers = [maneuver]

Attributed Instructions with Images

带图片的富文本指引

swift
// Create attributed instruction with embedded image
let instruction = NSMutableAttributedString(string: "Turn right on Apple Park Way")

// Attach an image icon
let image = UIImage(systemName: "arrow.turn.up.right")!
let attachment = NSTextAttachment(image: image)
let imageString = NSAttributedString(attachment: attachment)
instruction.append(NSAttributedString(string: " "))
instruction.append(imageString)

// Create maneuver with attributed instruction
let maneuver = CPManeuver()
maneuver.attributedInstructionVariants = [instruction]

// Also set dashboard-specific attributed instructions
let dashboardInstruction = NSMutableAttributedString(string: "Turn Right ")
let dashboardImage = UIImage(systemName: "arrow.turn.up.right.circle.fill")!
let dashboardAttachment = NSTextAttachment(image: dashboardImage)
dashboardInstruction.append(NSAttributedString(attachment: dashboardAttachment))
dashboardInstruction.append(NSAttributedString(string: " Apple Park Way"))

maneuver.dashboardAttributedInstructionVariants = [dashboardInstruction]

// Set symbol image for main display
maneuver.symbolImage = UIImage(named: "turn-right")

// Add to navigation session
navigationSession.upcomingManeuvers = [maneuver]
swift
// Create attributed instruction with embedded image
let instruction = NSMutableAttributedString(string: "Turn right on Apple Park Way")

// Attach an image icon
let image = UIImage(systemName: "arrow.turn.up.right")!
let attachment = NSTextAttachment(image: image)
let imageString = NSAttributedString(attachment: attachment)
instruction.append(NSAttributedString(string: " "))
instruction.append(imageString)

// Create maneuver with attributed instruction
let maneuver = CPManeuver()
maneuver.attributedInstructionVariants = [instruction]

// Also set dashboard-specific attributed instructions
let dashboardInstruction = NSMutableAttributedString(string: "Turn Right ")
let dashboardImage = UIImage(systemName: "arrow.turn.up.right.circle.fill")!
let dashboardAttachment = NSTextAttachment(image: dashboardImage)
dashboardInstruction.append(NSAttributedString(attachment: dashboardAttachment))
dashboardInstruction.append(NSAttributedString(string: " Apple Park Way"))

maneuver.dashboardAttributedInstructionVariants = [dashboardInstruction]

// Set symbol image for main display
maneuver.symbolImage = UIImage(named: "turn-right")

// Add to navigation session
navigationSession.upcomingManeuvers = [maneuver]

Route Selection

路线选择

swift
// Create route choices for trip preview
let fastRoute = CPRouteChoice(
    summaryVariants: ["Via Highway - 25 min"],
    additionalInformationVariants: ["Fastest route"],
    selectionSummaryVariants: ["Take the highway"]
)

let scenicRoute = CPRouteChoice(
    summaryVariants: ["Via Scenic Road - 35 min"],
    additionalInformationVariants: ["No tolls"],
    selectionSummaryVariants: ["Take the scenic route"]
)

let trip = CPTrip(
    origin: originMapItem,
    destination: destinationMapItem,
    routeChoices: [fastRoute, scenicRoute]
)

mapTemplate.showTripPreviews([trip], textConfiguration: nil)
swift
// Create route choices for trip preview
let fastRoute = CPRouteChoice(
    summaryVariants: ["Via Highway - 25 min"],
    additionalInformationVariants: ["Fastest route"],
    selectionSummaryVariants: ["Take the highway"]
)

let scenicRoute = CPRouteChoice(
    summaryVariants: ["Via Scenic Road - 35 min"],
    additionalInformationVariants: ["No tolls"],
    selectionSummaryVariants: ["Take the scenic route"]
)

let trip = CPTrip(
    origin: originMapItem,
    destination: destinationMapItem,
    routeChoices: [fastRoute, scenicRoute]
)

mapTemplate.showTripPreviews([trip], textConfiguration: nil)

Dashboard Integration (iOS 13.4+)

仪表盘集成(iOS 13.4+)

swift
// Configure dashboard scene delegate
func templateApplicationDashboardScene(
    _ dashboardScene: CPTemplateApplicationDashboardScene,
    didConnect dashboardController: CPDashboardController,
    to window: UIWindow
) {
    // Create dashboard shortcut buttons
    let homeButton = CPDashboardButton(
        titleVariants: ["Home"],
        subtitleVariants: ["123 Main St"],
        image: UIImage(systemName: "house.fill")!
    ) { button in
        // Navigate to home
    }

    let workButton = CPDashboardButton(
        titleVariants: ["Work"],
        subtitleVariants: ["456 Office Blvd"],
        image: UIImage(systemName: "building.2.fill")!
    ) { button in
        // Navigate to work
    }

    // Set dashboard shortcut buttons
    dashboardController.shortcutButtons = [homeButton, workButton]
}
swift
// Configure dashboard scene delegate
func templateApplicationDashboardScene(
    _ dashboardScene: CPTemplateApplicationDashboardScene,
    didConnect dashboardController: CPDashboardController,
    to window: UIWindow
) {
    // Create dashboard shortcut buttons
    let homeButton = CPDashboardButton(
        titleVariants: ["Home"],
        subtitleVariants: ["123 Main St"],
        image: UIImage(systemName: "house.fill")!
    ) { button in
        // Navigate to home
    }

    let workButton = CPDashboardButton(
        titleVariants: ["Work"],
        subtitleVariants: ["456 Office Blvd"],
        image: UIImage(systemName: "building.2.fill")!
    ) { button in
        // Navigate to work
    }

    // Set dashboard shortcut buttons
    dashboardController.shortcutButtons = [homeButton, workButton]
}

Instrument Cluster Integration (iOS 15.4+)

仪表集群集成(iOS 15.4+)

swift
// Configure instrument cluster scene delegate
func templateApplicationInstrumentClusterScene(
    _ instrumentClusterScene: CPTemplateApplicationInstrumentClusterScene,
    didConnect instrumentClusterController: CPInstrumentClusterController
) {
    // Configure instrument cluster display
    instrumentClusterController.inactiveDescriptionVariants = [
        "No active navigation"
    ]

    // Set compass display
    instrumentClusterController.compassSetting = .automatic

    // Update with route information (iOS 17.4+)
    let routeInfo = CPRouteInformation(
        maneuvers: upcomingManeuvers,
        laneGuidances: lanGuidances,
        currentManeuvers: [currentManeuver],
        currentLaneGuidance: currentLaneGuidance,
        trip: currentTrip,
        maneuverTravelEstimates: travelEstimates
    )

    // Display on instrument cluster
    instrumentClusterController.compassSetting = .showAlways
}
swift
// Configure instrument cluster scene delegate
func templateApplicationInstrumentClusterScene(
    _ instrumentClusterScene: CPTemplateApplicationInstrumentClusterScene,
    didConnect instrumentClusterController: CPInstrumentClusterController
) {
    // Configure instrument cluster display
    instrumentClusterController.inactiveDescriptionVariants = [
        "No active navigation"
    ]

    // Set compass display
    instrumentClusterController.compassSetting = .automatic

    // Update with route information (iOS 17.4+)
    let routeInfo = CPRouteInformation(
        maneuvers: upcomingManeuvers,
        laneGuidances: lanGuidances,
        currentManeuvers: [currentManeuver],
        currentLaneGuidance: currentLaneGuidance,
        trip: currentTrip,
        maneuverTravelEstimates: travelEstimates
    )

    // Display on instrument cluster
    instrumentClusterController.compassSetting = .showAlways
}

Grid Template

网格模板

swift
// Create grid buttons with icons
let homeButton = CPGridButton(
    titleVariants: ["Home"],
    image: UIImage(systemName: "house.fill")!
) { button in
    // Navigate to home
}

let workButton = CPGridButton(
    titleVariants: ["Work"],
    image: UIImage(systemName: "building.2.fill")!
) { button in
    // Navigate to work
}

let favoritesButton = CPGridButton(
    titleVariants: ["Favorites"],
    image: UIImage(systemName: "star.fill")!
) { button in
    // Show favorites
}

// Create grid template with up to 8 buttons
let gridTemplate = CPGridTemplate(
    title: "Quick Actions",
    gridButtons: [homeButton, workButton, favoritesButton]
)

interfaceController.setRootTemplate(gridTemplate, animated: true)

// Update buttons dynamically
let newButtons = [homeButton, workButton, favoritesButton, newButton]
gridTemplate.updateGridButtons(newButtons)
swift
// Create grid buttons with icons
let homeButton = CPGridButton(
    titleVariants: ["Home"],
    image: UIImage(systemName: "house.fill")!
) { button in
    // Navigate to home
}

let workButton = CPGridButton(
    titleVariants: ["Work"],
    image: UIImage(systemName: "building.2.fill")!
) { button in
    // Navigate to work
}

let favoritesButton = CPGridButton(
    titleVariants: ["Favorites"],
    image: UIImage(systemName: "star.fill")!
) { button in
    // Show favorites
}

// Create grid template with up to 8 buttons
let gridTemplate = CPGridTemplate(
    title: "Quick Actions",
    gridButtons: [homeButton, workButton, favoritesButton]
)

interfaceController.setRootTemplate(gridTemplate, animated: true)

// Update buttons dynamically
let newButtons = [homeButton, workButton, favoritesButton, newButton]
gridTemplate.updateGridButtons(newButtons)

Search Template

搜索模板

swift
// Create search template
let searchTemplate = CPSearchTemplate()
searchTemplate.delegate = self

// Set as root
interfaceController.setRootTemplate(searchTemplate, animated: true)

// Implement CPSearchTemplateDelegate
func searchTemplate(
    _ searchTemplate: CPSearchTemplate,
    updatedSearchText searchText: String,
    completionHandler: @escaping ([CPListItem]) -> Void
) {
    // Perform search
    let results = performSearch(query: searchText)

    // Convert to list items
    let listItems = results.map { result in
        let item = CPListItem(text: result.name, detailText: result.address)
        item.handler = { item, completion in
            // Handle selection
            self.showResultDetails(result)
            completion()
        }
        return item
    }

    // Return results
    completionHandler(listItems)
}

func searchTemplateSearchButtonPressed(_ searchTemplate: CPSearchTemplate) {
    // User tapped search button
    print("Search initiated")
}
swift
// Create search template
let searchTemplate = CPSearchTemplate()
searchTemplate.delegate = self

// Set as root
interfaceController.setRootTemplate(searchTemplate, animated: true)

// Implement CPSearchTemplateDelegate
func searchTemplate(
    _ searchTemplate: CPSearchTemplate,
    updatedSearchText searchText: String,
    completionHandler: @escaping ([CPListItem]) -> Void
) {
    // Perform search
    let results = performSearch(query: searchText)

    // Convert to list items
    let listItems = results.map { result in
        let item = CPListItem(text: result.name, detailText: result.address)
        item.handler = { item, completion in
            // Handle selection
            self.showResultDetails(result)
            completion()
        }
        return item
    }

    // Return results
    completionHandler(listItems)
}

func searchTemplateSearchButtonPressed(_ searchTemplate: CPSearchTemplate) {
    // User tapped search button
    print("Search initiated")
}

Point of Interest Template

兴趣点模板

swift
// Create points of interest
let poi1 = CPPointOfInterest(
    location: MKMapItem(placemark: MKPlacemark(coordinate: coordinate1)),
    title: "Apple Park",
    subtitle: "1 Apple Park Way",
    summary: "Apple headquarters",
    detailTitle: "Visitor Center",
    detailSubtitle: "Open 9 AM - 5 PM",
    detailSummary: "Tours available",
    pinImage: UIImage(systemName: "applelogo")
)

let poi2 = CPPointOfInterest(
    location: MKMapItem(placemark: MKPlacemark(coordinate: coordinate2)),
    title: "Golden Gate Bridge",
    subtitle: "San Francisco",
    summary: "Iconic landmark",
    detailTitle: "Vista Point",
    detailSubtitle: "Always Open",
    detailSummary: "Great views",
    pinImage: UIImage(systemName: "bridge")
)

// Create POI template
let poiTemplate = CPPointOfInterestTemplate(
    title: "Nearby Attractions",
    pointsOfInterest: [poi1, poi2],
    selectedIndex: 0
)

poiTemplate.pointOfInterestDelegate = self

// Implement delegate
func pointOfInterestTemplate(
    _ template: CPPointOfInterestTemplate,
    didSelectPointOfInterest poi: CPPointOfInterest
) {
    // User selected a POI
    print("Selected: \(poi.title)")

    // Show navigation options
    showNavigationOptions(for: poi)
}

func pointOfInterestTemplate(
    _ template: CPPointOfInterestTemplate,
    didChangeMapRegion region: MKCoordinateRegion
) {
    // Map region changed (user panned/zoomed)
    fetchNearbyPOIs(in: region)
}
swift
// Create points of interest
let poi1 = CPPointOfInterest(
    location: MKMapItem(placemark: MKPlacemark(coordinate: coordinate1)),
    title: "Apple Park",
    subtitle: "1 Apple Park Way",
    summary: "Apple headquarters",
    detailTitle: "Visitor Center",
    detailSubtitle: "Open 9 AM - 5 PM",
    detailSummary: "Tours available",
    pinImage: UIImage(systemName: "applelogo")
)

let poi2 = CPPointOfInterest(
    location: MKMapItem(placemark: MKPlacemark(coordinate: coordinate2)),
    title: "Golden Gate Bridge",
    subtitle: "San Francisco",
    summary: "Iconic landmark",
    detailTitle: "Vista Point",
    detailSubtitle: "Always Open",
    detailSummary: "Great views",
    pinImage: UIImage(systemName: "bridge")
)

// Create POI template
let poiTemplate = CPPointOfInterestTemplate(
    title: "Nearby Attractions",
    pointsOfInterest: [poi1, poi2],
    selectedIndex: 0
)

poiTemplate.pointOfInterestDelegate = self

// Implement delegate
func pointOfInterestTemplate(
    _ template: CPPointOfInterestTemplate,
    didSelectPointOfInterest poi: CPPointOfInterest
) {
    // User selected a POI
    print("Selected: \(poi.title)")

    // Show navigation options
    showNavigationOptions(for: poi)
}

func pointOfInterestTemplate(
    _ template: CPPointOfInterestTemplate,
    didChangeMapRegion region: MKCoordinateRegion
) {
    // Map region changed (user panned/zoomed)
    fetchNearbyPOIs(in: region)
}

Information Template

信息模板

swift
// Create information items
let addressItem = CPInformationItem(
    title: "Address",
    detail: "1 Apple Park Way, Cupertino, CA"
)

let hoursItem = CPInformationItem(
    title: "Hours",
    detail: "9:00 AM - 9:00 PM"
)

let phoneItem = CPInformationItem(
    title: "Phone",
    detail: "(408) 996-1010"
)

// Create action buttons
let callButton = CPTextButton(text: "Call", textStyle: .normal) { button in
    // Make phone call
    makePhoneCall()
}

let directionsButton = CPTextButton(text: "Directions", textStyle: .confirm) { button in
    // Start navigation
    startNavigation()
}

// Create information template
let infoTemplate = CPInformationTemplate(
    title: "Apple Store",
    layout: .leading,  // or .twoColumn
    items: [addressItem, hoursItem, phoneItem],
    actions: [callButton, directionsButton]
)

interfaceController.pushTemplate(infoTemplate, animated: true)
swift
// Create information items
let addressItem = CPInformationItem(
    title: "Address",
    detail: "1 Apple Park Way, Cupertino, CA"
)

let hoursItem = CPInformationItem(
    title: "Hours",
    detail: "9:00 AM - 9:00 PM"
)

let phoneItem = CPInformationItem(
    title: "Phone",
    detail: "(408) 996-1010"
)

// Create action buttons
let callButton = CPTextButton(text: "Call", textStyle: .normal) { button in
    // Make phone call
    makePhoneCall()
}

let directionsButton = CPTextButton(text: "Directions", textStyle: .confirm) { button in
    // Start navigation
    startNavigation()
}

// Create information template
let infoTemplate = CPInformationTemplate(
    title: "Apple Store",
    layout: .leading,  // or .twoColumn
    items: [addressItem, hoursItem, phoneItem],
    actions: [callButton, directionsButton]
)

interfaceController.pushTemplate(infoTemplate, animated: true)

Action Sheet Template

动作表模板

swift
// Create actions for action sheet
let confirmAction = CPAlertAction(title: "Confirm", style: .default) { action in
    // User confirmed
    self.performAction()
}

let cancelAction = CPAlertAction(title: "Cancel", style: .cancel) { action in
    // User cancelled
    print("Action cancelled")
}

let destructiveAction = CPAlertAction(title: "Delete", style: .destructive) { action in
    // User chose destructive action
    self.deleteItem()
}

// Create action sheet
let actionSheet = CPActionSheetTemplate(
    title: "Choose Action",
    message: "What would you like to do?",
    actions: [confirmAction, destructiveAction, cancelAction]
)

// Present modally
interfaceController.presentTemplate(actionSheet, animated: true, completion: nil)
swift
// Create actions for action sheet
let confirmAction = CPAlertAction(title: "Confirm", style: .default) { action in
    // User confirmed
    self.performAction()
}

let cancelAction = CPAlertAction(title: "Cancel", style: .cancel) { action in
    // User cancelled
    print("Action cancelled")
}

let destructiveAction = CPAlertAction(title: "Delete", style: .destructive) { action in
    // User chose destructive action
    self.deleteItem()
}

// Create action sheet
let actionSheet = CPActionSheetTemplate(
    title: "Choose Action",
    message: "What would you like to do?",
    actions: [confirmAction, destructiveAction, cancelAction]
)

// Present modally
interfaceController.presentTemplate(actionSheet, animated: true, completion: nil)

Alert Template

警告模板

swift
// Create alert actions
let okAction = CPAlertAction(title: "OK", style: .default) { action in
    // User tapped OK
    print("User acknowledged")
}

let retryAction = CPAlertAction(title: "Retry", style: .default) { action in
    // User wants to retry
    self.retryOperation()
}

let cancelAction = CPAlertAction(title: "Cancel", style: .cancel) { action in
    // User cancelled
}

// Create alert with multiple title variants for different screen sizes
let alert = CPAlertTemplate(
    titleVariants: [
        "Connection Lost",
        "Lost Connection",
        "No Network"
    ],
    actions: [retryAction, cancelAction]
)

// Present alert
interfaceController.presentTemplate(alert, animated: true, completion: nil)

// Auto-dismiss after 5 seconds
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
    interfaceController.dismissTemplate(animated: true, completion: nil)
}
swift
// Create alert actions
let okAction = CPAlertAction(title: "OK", style: .default) { action in
    // User tapped OK
    print("User acknowledged")
}

let retryAction = CPAlertAction(title: "Retry", style: .default) { action in
    // User wants to retry
    self.retryOperation()
}

let cancelAction = CPAlertAction(title: "Cancel", style: .cancel) { action in
    // User cancelled
}

// Create alert with multiple title variants for different screen sizes
let alert = CPAlertTemplate(
    titleVariants: [
        "Connection Lost",
        "Lost Connection",
        "No Network"
    ],
    actions: [retryAction, cancelAction]
)

// Present alert
interfaceController.presentTemplate(alert, animated: true, completion: nil)

// Auto-dismiss after 5 seconds
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
    interfaceController.dismissTemplate(animated: true, completion: nil)
}

Voice Control Template

语音控制模板

swift
// Create voice control states
let listeningState = CPVoiceControlState(
    identifier: "listening",
    titleVariants: ["Listening...", "Say a command"],
    image: UIImage(systemName: "waveform")!,
    repeats: true
)

let processingState = CPVoiceControlState(
    identifier: "processing",
    titleVariants: ["Processing...", "Working on it"],
    image: UIImage(systemName: "gear")!,
    repeats: false
)

let successState = CPVoiceControlState(
    identifier: "success",
    titleVariants: ["Done!", "Complete"],
    image: UIImage(systemName: "checkmark.circle.fill")!,
    repeats: false
)

// Create voice control template
let voiceTemplate = CPVoiceControlTemplate(
    voiceControlStates: [listeningState, processingState, successState]
)

// Present voice control
interfaceController.presentTemplate(voiceTemplate, animated: true) {
    // Start listening
    self.startVoiceRecognition()
}

// Update state based on recognition progress
voiceTemplate.activateVoiceControlState(withIdentifier: "processing")

// Show success when done
voiceTemplate.activateVoiceControlState(withIdentifier: "success")

// Dismiss after completion
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
    interfaceController.dismissTemplate(animated: true, completion: nil)
}
swift
// Create voice control states
let listeningState = CPVoiceControlState(
    identifier: "listening",
    titleVariants: ["Listening...", "Say a command"],
    image: UIImage(systemName: "waveform")!,
    repeats: true
)

let processingState = CPVoiceControlState(
    identifier: "processing",
    titleVariants: ["Processing...", "Working on it"],
    image: UIImage(systemName: "gear")!,
    repeats: false
)

let successState = CPVoiceControlState(
    identifier: "success",
    titleVariants: ["Done!", "Complete"],
    image: UIImage(systemName: "checkmark.circle.fill")!,
    repeats: false
)

// Create voice control template
let voiceTemplate = CPVoiceControlTemplate(
    voiceControlStates: [listeningState, processingState, successState]
)

// Present voice control
interfaceController.presentTemplate(voiceTemplate, animated: true) {
    // Start listening
    self.startVoiceRecognition()
}

// Update state based on recognition progress
voiceTemplate.activateVoiceControlState(withIdentifier: "processing")

// Show success when done
voiceTemplate.activateVoiceControlState(withIdentifier: "success")

// Dismiss after completion
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
    interfaceController.dismissTemplate(animated: true, completion: nil)
}

Contact Template (Communication)

联系人模板(通讯类)

swift
// Create contact
let contact = CPContact(
    name: "John Appleseed",
    image: UIImage(named: "contact_photo")
)
contact.subtitle = "Friend"
contact.informativeText = "Last contact: Today"

// Create contact action buttons
let callButton = CPContactCallButton(handler: { button in
    // Initiate phone call
    self.makePhoneCall(to: contact)
})

let messageButton = CPContactMessageButton(phoneOrEmail: "john@example.com")

let directionsButton = CPContactDirectionsButton(handler: { button in
    // Navigate to contact's location
    self.navigateToContact(contact)
})

contact.actions = [callButton, messageButton, directionsButton]

// Create contact template
let contactTemplate = CPContactTemplate(contact: contact)

// Present contact card
interfaceController.pushTemplate(contactTemplate, animated: true)
swift
// Create contact
let contact = CPContact(
    name: "John Appleseed",
    image: UIImage(named: "contact_photo")
)
contact.subtitle = "Friend"
contact.informativeText = "Last contact: Today"

// Create contact action buttons
let callButton = CPContactCallButton(handler: { button in
    // Initiate phone call
    self.makePhoneCall(to: contact)
})

let messageButton = CPContactMessageButton(phoneOrEmail: "john@example.com")

let directionsButton = CPContactDirectionsButton(handler: { button in
    // Navigate to contact's location
    self.navigateToContact(contact)
})

contact.actions = [callButton, messageButton, directionsButton]

// Create contact template
let contactTemplate = CPContactTemplate(contact: contact)

// Present contact card
interfaceController.pushTemplate(contactTemplate, animated: true)

Message List Template (Communication)

消息列表模板(通讯类)

swift
// Create leading configurations (profile images)
let profileImage = UIImage(named: "profile")!
let leadingConfig = CPMessageListItemLeadingConfiguration(
    leadingItem: .image(profileImage),
    leadingImage: profileImage,
    unreadIndicator: true
)

// Create trailing configurations (timestamps/badges)
let trailingConfig = CPMessageListItemTrailingConfiguration(
    trailingItem: .image(UIImage(systemName: "chevron.right")!),
    trailingImage: UIImage(systemName: "paperclip")
)

// Create message list items
let message1 = CPMessageListItem(
    conversationIdentifier: "conv_1",
    text: "John Appleseed",
    leadingConfiguration: leadingConfig,
    trailingConfiguration: trailingConfig,
    detailText: "Hey, are you free for lunch?",
    trailingText: "12:30 PM"
)
message1.handler = { item, completion in
    // Open conversation
    self.openConversation(id: "conv_1")
    completion()
}

let message2 = CPMessageListItem(
    fullName: "Jane Smith",
    phoneOrEmailAddress: "jane@example.com",
    leadingConfiguration: CPMessageListItemLeadingConfiguration(
        leadingItem: .image(UIImage(named: "jane_photo")!),
        leadingImage: UIImage(named: "jane_photo")!,
        unreadIndicator: false
    ),
    trailingConfiguration: trailingConfig,
    detailText: "Thanks for the update!",
    trailingText: "Yesterday"
)

// Create list template with messages
let section = CPListSection(items: [message1, message2])
let listTemplate = CPListTemplate(title: "Messages", sections: [section])

interfaceController.setRootTemplate(listTemplate, animated: true)
swift
// Create leading configurations (profile images)
let profileImage = UIImage(named: "profile")!
let leadingConfig = CPMessageListItemLeadingConfiguration(
    leadingItem: .image(profileImage),
    leadingImage: profileImage,
    unreadIndicator: true
)

// Create trailing configurations (timestamps/badges)
let trailingConfig = CPMessageListItemTrailingConfiguration(
    trailingItem: .image(UIImage(systemName: "chevron.right")!),
    trailingImage: UIImage(systemName: "paperclip")
)

// Create message list items
let message1 = CPMessageListItem(
    conversationIdentifier: "conv_1",
    text: "John Appleseed",
    leadingConfiguration: leadingConfig,
    trailingConfiguration: trailingConfig,
    detailText: "Hey, are you free for lunch?",
    trailingText: "12:30 PM"
)
message1.handler = { item, completion in
    // Open conversation
    self.openConversation(id: "conv_1")
    completion()
}

let message2 = CPMessageListItem(
    fullName: "Jane Smith",
    phoneOrEmailAddress: "jane@example.com",
    leadingConfiguration: CPMessageListItemLeadingConfiguration(
        leadingItem: .image(UIImage(named: "jane_photo")!),
        leadingImage: UIImage(named: "jane_photo")!,
        unreadIndicator: false
    ),
    trailingConfiguration: trailingConfig,
    detailText: "Thanks for the update!",
    trailingText: "Yesterday"
)

// Create list template with messages
let section = CPListSection(items: [message1, message2])
let listTemplate = CPListTemplate(title: "Messages", sections: [section])

interfaceController.setRootTemplate(listTemplate, animated: true)

List Image Row Item

列表图片行项目

swift
// Create images for grid display
let image1 = UIImage(named: "album_cover_1")!
let image2 = UIImage(named: "album_cover_2")!
let image3 = UIImage(named: "album_cover_3")!
let image4 = UIImage(named: "album_cover_4")!

// Create list image row item with titles
let imageRowItem = CPListImageRowItem(
    text: "Recently Played",
    images: [image1, image2, image3, image4],
    imageTitles: ["Rock Hits", "Chill Vibes", "Workout Mix", "Road Trip"]
)

// Handle image selection
imageRowItem.listImageRowHandler = { item, index, completion in
    // User selected image at index
    print("Selected image \(index)")
    self.playAlbum(at: index)
    completion()
}

// Handle row selection
imageRowItem.handler = { item, completion in
    // User tapped the entire row (not a specific image)
    self.showRecentlyPlayed()
    completion()
}

// Create list with image row
let section = CPListSection(items: [imageRowItem])
let listTemplate = CPListTemplate(title: "Music", sections: [section])

// Update images dynamically
let newImages = [image1, image2, image3, image4, image5]
imageRowItem.update(newImages)
swift
// Create images for grid display
let image1 = UIImage(named: "album_cover_1")!
let image2 = UIImage(named: "album_cover_2")!
let image3 = UIImage(named: "album_cover_3")!
let image4 = UIImage(named: "album_cover_4")!

// Create list image row item with titles
let imageRowItem = CPListImageRowItem(
    text: "Recently Played",
    images: [image1, image2, image3, image4],
    imageTitles: ["Rock Hits", "Chill Vibes", "Workout Mix", "Road Trip"]
)

// Handle image selection
imageRowItem.listImageRowHandler = { item, index, completion in
    // User selected image at index
    print("Selected image \(index)")
    self.playAlbum(at: index)
    completion()
}

// Handle row selection
imageRowItem.handler = { item, completion in
    // User tapped the entire row (not a specific image)
    self.showRecentlyPlayed()
    completion()
}

// Create list with image row
let section = CPListSection(items: [imageRowItem])
let listTemplate = CPListTemplate(title: "Music", sections: [section])

// Update images dynamically
let newImages = [image1, image2, image3, image4, image5]
imageRowItem.update(newImages)

Reference Documentation

参考文档

For complete API details, see the categorized documentation in the
references/
directory.
完整的API详情请查看
references/
目录下按类别组织的文档。