expo-modules — android expo-modules, apple-health, community, android, ide skills, apple-health-analytics, apple-health-xml, capacitor-android, data-sync, health, Claude Code

v1.0.0

关于此技能

非常适合需要在iOS上与Apple HealthKit实现无缝集成的移动健康代理 Building great Expo native modules for iOS and Android. Views, APIs, Marshalling, Shared Objects, Expo Documentation, Verifying Expo modules.

# 核心主题

manavkushwaha10 manavkushwaha10
[0]
[0]
更新于: 3/23/2026

Killer-Skills Review

Decision support comes first. Repository text comes second.

Reference-Only Page Review Score: 5/11

This page remains useful for operators, but Killer-Skills treats it as reference material instead of a primary organic landing page.

Concrete use-case guidance Explicit limitations and caution
Review Score
5/11
Quality Score
42
Canonical Locale
en
Detected Body Locale
en

非常适合需要在iOS上与Apple HealthKit实现无缝集成的移动健康代理 Building great Expo native modules for iOS and Android. Views, APIs, Marshalling, Shared Objects, Expo Documentation, Verifying Expo modules.

核心价值

赋予代理读取、写入和订阅健康数据的能力,使用本地API,通过如`std:kv-storage`的标准支持多样化的健康指标和锻炼,并直接暴露本地功能

适用 Agent 类型

非常适合需要在iOS上与Apple HealthKit实现无缝集成的移动健康代理

赋予的主要能力 · expo-modules

与Apple HealthKit交互以进行健身追踪
订阅健康数据更新以获得个性化推荐
使用直接访问iOS健康指标的方式开发本地健康和健身应用

! 使用限制与门槛

  • 仅限iOS
  • 需要本地API兼容性
  • 依赖于Apple HealthKit的可用性和用户权限

Why this page is reference-only

  • - Current locale does not satisfy the locale-governance contract.
  • - The page lacks a strong recommendation layer.
  • - The underlying skill quality score is below the review floor.

Source Boundary

The section below is supporting source material from the upstream repository. Use the Killer-Skills review above as the primary decision layer.

实验室 Demo

Browser Sandbox Environment

⚡️ Ready to unleash?

Experience this Agent in a zero-setup browser environment powered by WebContainers. No installation required.

Boot Container Sandbox

常见问题与安装步骤

以下问题与步骤与页面结构化数据保持一致,便于搜索引擎理解页面内容。

? FAQ

expo-modules 是什么?

非常适合需要在iOS上与Apple HealthKit实现无缝集成的移动健康代理 Building great Expo native modules for iOS and Android. Views, APIs, Marshalling, Shared Objects, Expo Documentation, Verifying Expo modules.

如何安装 expo-modules?

运行命令:npx killer-skills add manavkushwaha10/apple-health/expo-modules。支持 Cursor、Windsurf、VS Code、Claude Code 等 19+ IDE/Agent。

expo-modules 适用于哪些场景?

典型场景包括:与Apple HealthKit交互以进行健身追踪、订阅健康数据更新以获得个性化推荐、使用直接访问iOS健康指标的方式开发本地健康和健身应用。

expo-modules 支持哪些 IDE 或 Agent?

该技能兼容 Cursor, Windsurf, VS Code, Trae, Claude Code, OpenClaw, Aider, Codex, OpenCode, Goose, Cline, Roo Code, Kiro, Augment Code, Continue, GitHub Copilot, Sourcegraph Cody, and Amazon Q Developer。可使用 Killer-Skills CLI 一条命令通用安装。

expo-modules 有哪些限制?

仅限iOS;需要本地API兼容性;依赖于Apple HealthKit的可用性和用户权限。

安装步骤

  1. 1. 打开终端

    在你的项目目录中打开终端或命令行。

  2. 2. 执行安装命令

    运行:npx killer-skills add manavkushwaha10/apple-health/expo-modules。CLI 会自动识别 IDE 或 AI Agent 并完成配置。

  3. 3. 开始使用技能

    expo-modules 已启用,可立即在当前项目中调用。

! 参考页模式

此页面仍可作为安装与查阅参考,但 Killer-Skills 不再把它视为主要可索引落地页。请优先阅读上方评审结论,再决定是否继续查看上游仓库说明。

Imported Repository Instructions

The section below is supporting source material from the upstream repository. Use the Killer-Skills review above as the primary decision layer.

Supporting Evidence

expo-modules

Building great Expo native modules for iOS and Android. Views, APIs, Marshalling, Shared Objects, Expo Documentation, Verifying Expo modules.

SKILL.md
Readonly
Imported Repository Instructions
The section below is supporting source material from the upstream repository. Use the Killer-Skills review above as the primary decision layer.
Supporting Evidence

Great module standards

  • Design native APIs as if you contributing W3C specs for the browser, take inspiration from modern web modules. eg std:kv-storage, clipboard.
  • Aim for 100% backwards compatibility like the web.
  • Create escape hatches for single-platform functionality.
  • Avoid extraneous abstractions. Directly expose native functionality.
  • Avoid unnecessary async methods. Use sync methods when possible.
  • Prefer string union types for API options instead of boolean flags, enums, or multiple parameters. eg instead of capture(options: { isHighQuality: boolean }), use capture(options: { quality: 'high' | 'medium' | 'low' }).
  • Marshalling is awesome for platform-specific APIs.
  • New Architecture only. NEVER support legacy React Native architecture.
  • ALWAYS use only Expo modules API.
  • Prefer Swift and Kotlin.
  • Use optionality for availability checks as opposed to extraneous isAvailable functions or constants. eg snapshot.capture?.() instead of snapshot.isAvailable && snapshot.capture().
  • ALWAYS support the latest and greatest API features.

Example of a GREAT Expo module:

ts
1import { NativeModule } from "expo"; 2 3declare class AppClipModule extends NativeModule<{}> { 4 prompt(): void; 5 isAppClip?: boolean; 6} 7 8// This call loads the native module object from the JSI. 9const AppClipNative = 10 typeof expo !== "undefined" 11 ? (expo.modules.AppClip as AppClipModule) ?? {} 12 : {}; 13 14if (AppClipNative?.isAppClip) { 15 navigator.appClip = { 16 prompt: AppClipNative.prompt, 17 }; 18} 19 20// Add types for the global `navigator.appClip` object. 21declare global { 22 interface Navigator { 23 /** 24 * Only available in an App Clip context. 25 * @expo 26 */ 27 appClip?: { 28 /** Open the SKOverlay */ 29 prompt: () => void; 30 }; 31 } 32} 33 34export {};
  • Simple web-style interface.
  • Global type augmentation for easy access.
  • Docs in the type definitions.
  • Optional availability checks instead of extraneous isAvailable methods.

Example of a POOR Expo module:

ts
1import { NativeModulesProxy } from "expo-modules-core"; 2const { ExpoAppClip } = NativeModulesProxy; 3export default { 4 promptAppClip() { 5 return ExpoAppClip.promptAppClip(); 6 }, 7 isAppClipAvailable() { 8 return ExpoAppClip.isAppClipAvailable(); 9 }, 10};

Great documentation

  • If you have a function like isAvailable(), explain why it exists in the docs. Research cases where it may return false such as in a simulator or particular OS version.
  • Document OS version availability for functions and constants in the type definitions.

BAD module standards

  • APIs that are hard to import, e.g. import * as MediaLibrary from 'expo-media-library'; instead of import { MediaLibrary } from 'expo/media';
  • Extraneous abstractions over native functionality. The native module is installing on the global, do not wrap it in another layer for no reason.
  • Extraneous async methods when sync methods are possible.
  • Boolean flags instead of string union types for options.
  • Supporting legacy React Native architecture.

Views

Take API inspiration from great web component libraries like BaseUI and Radix.

Consider if you're building a control or a display component. Controls should have more interactive APIs, while display components should be more declarative.

Prefer functions on views instead of useImperativeHandle + findNodeHandle.

swift
1AsyncFunction("capture") { (view, options: Options) -> Ref in 2 return try capture(self.appContext, view) 3}

Remember to export views in the module:

swift
1import ExpoModulesCore 2 3public class ExpoWebViewModule: Module { 4 public func definition() -> ModuleDefinition { 5 Name("ExpoWebView") 6 7 View(ExpoWebView.self) {} 8 } 9}

Marshalling-style API

Consider this example https://github.com/EvanBacon/expo-shared-objects-haptics-example/blob/be90e92f8dba9b0807009502ab25c423c57e640d/modules/my-module/ios/MyModule.swift#L1C1-L178C2

Using @retroactive Convertible and AnyArgument to convert between Swift types and dictionaries enables passing complex data structures across the boundary without writing custom serialization code for each type.

swift
1extension CHHapticEventParameter: @retroactive Convertible, AnyArgument { 2 public static func convert(from value: Any?, appContext: AppContext) throws -> Self { 3 guard let dict = value as? [String: Any], 4 let parameterIDRaw = dict["parameterID"] as? String, 5 let value = dict["value"] as? Double else { 6 throw NotADictionaryException() 7 } 8 return Self(parameterID: CHHapticEvent.ParameterID(rawValue: parameterIDRaw), value: Float(value)) 9 } 10} 11 12extension CHHapticEvent: @retroactive Convertible, AnyArgument { 13 public static func convert(from value: Any?, appContext: AppContext) throws -> Self { 14 guard let dict = value as? [String: Any], 15 let eventTypeRaw = dict["eventType"] as? String, 16 let relativeTime = dict["relativeTime"] as? Double else { 17 throw NotADictionaryException() 18 } 19 let eventType = CHHapticEvent.EventType(rawValue: eventTypeRaw) 20 let parameters = (dict["parameters"] as? [[String: Any]])?.compactMap { paramDict -> CHHapticEventParameter? in 21 try? CHHapticEventParameter.convert(from: paramDict, appContext: appContext) 22 } ?? [] 23 return Self(eventType: eventType, parameters: parameters, relativeTime: relativeTime) 24 } 25} 26 27extension CHHapticDynamicParameter: @retroactive Convertible, AnyArgument { 28 public static func convert(from value: Any?, appContext: AppContext) throws -> Self { 29 guard let dict = value as? [String: Any], 30 let parameterIDRaw = dict["parameterID"] as? String, 31 let value = dict["value"] as? Double, 32 let relativeTime = dict["relativeTime"] as? Double else { 33 throw NotADictionaryException() 34 } 35 36 return Self(parameterID: CHHapticDynamicParameter.ID(rawValue: parameterIDRaw), value: Float(value), relativeTime: relativeTime) 37 } 38} 39 40extension CHHapticPattern: @retroactive Convertible, AnyArgument { 41 public static func convert(from value: Any?, appContext: AppContext) throws -> Self { 42 guard let dict = value as? [String: Any], 43 let eventsArray = dict["events"] as? [[String: Any]] else { 44 throw NotADictionaryException() 45 } 46 let events = try eventsArray.map { eventDict -> CHHapticEvent in 47 try CHHapticEvent.convert(from: eventDict, appContext: appContext) 48 } 49 let parameters = (dict["parameters"] as? [[String: Any]])?.compactMap { paramDict -> CHHapticDynamicParameter? in 50 return try? CHHapticDynamicParameter.convert(from: paramDict, appContext: appContext) 51 } ?? [] 52 return try Self(events: events, parameters: parameters) 53 } 54} 55 56internal final class NotAnArrayException: Exception { 57 override var reason: String { 58 "Given value is not an array" 59 } 60} 61 62internal final class IncorrectArraySizeException: GenericException<(expected: Int, actual: Int)> { 63 override var reason: String { 64 "Given array has unexpected number of elements: \(param.actual), expected: \(param.expected)" 65 } 66} 67 68internal final class NotADictionaryException: Exception { 69 override var reason: String { 70 "Given value is not a dictionary" 71 } 72} 73

Later this can be used to implement methods that accept complex data structures as arguments.

swift
1Function("playPattern") { (pattern: CHHapticPattern) in 2 let player = try hapticEngine.makePlayer(with: pattern) 3 try player.start(atTime: 0) 4}

Use shorthand where possible, especially when the JS value matches the Swift value:

swift
1Property("__typename") { $0.__typename }

Shared objects

Shared objects are long-lived native instances that are shared to JS. They can be used to keep heavy state objects, such as a decoded bitmap, alive across React components, rather than spinning up a new native instance every time a component mounts.

Interacting with AppDelegate

To interact with HealthKit, the module may need to respond to app lifecycle events. This can be done by implementing the ExpoAppDelegateSubscriber protocol.

swift
1import ExpoModulesCore 2 3public class ExpoHeadAppDelegateSubscriber: ExpoAppDelegateSubscriber { 4 5// Any AppDelegate methods you want to implement 6 public func application( 7 _ application: UIApplication, 8 continue userActivity: NSUserActivity, 9 restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void 10 ) -> Bool { 11 launchedActivity = userActivity 12 13 // ... 14 15 return false 16 } 17}

Then add the subscriber to the expo-module.config.json:

json
1{ 2 "platforms": ["apple", "android", "web"], 3 "apple": { 4 "modules": ["ExpoHeadModule", ...], 5 "appDelegateSubscribers": ["ExpoHeadAppDelegateSubscriber"] 6 } 7}

Expo ecosystem integration

Verification

  • Run yarn expo run:ios --no-bundler in an Expo app to headlessly compile the module and verify there are no compilation errors.

相关技能

寻找 expo-modules 的替代方案 (Alternative) 或可搭配使用的同类 community Skill?探索以下相关开源技能。

查看全部

openclaw-release-maintainer

Logo of openclaw
openclaw

Your own personal AI assistant. Any OS. Any Platform. The lobster way. 🦞

333.8k
0
AI

widget-generator

Logo of f
f

为prompts.chat的信息反馈系统生成可定制的插件小部件

149.6k
0
AI

flags

Logo of vercel
vercel

React 框架

138.4k
0
浏览器

pr-review

Logo of pytorch
pytorch

Python中具有强大GPU加速的张量和动态神经网络

98.6k
0
开发者工具