@maccesar/titools 5.3.0 → 5.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/CONTRIBUTING.md +1 -1
  2. package/README.md +31 -60
  3. package/agents/ti-pro.md +3 -1
  4. package/commands/ti-audit.md +6 -4
  5. package/docs/examples.md +9 -0
  6. package/docs/knowledge-index.md +2 -1
  7. package/lib/config.js +1 -0
  8. package/package.json +1 -1
  9. package/skills/alloy-guides/SKILL.md +18 -179
  10. package/skills/alloy-guides/references/CLI_TASKS.md +17 -216
  11. package/skills/alloy-guides/references/CONCEPTS.md +27 -162
  12. package/skills/alloy-guides/references/CONTROLLERS.md +38 -236
  13. package/skills/alloy-guides/references/MODELS.md +47 -723
  14. package/skills/alloy-guides/references/MODELS_ADVANCED.md +21 -482
  15. package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +12 -222
  16. package/skills/alloy-guides/references/VIEWS_STYLES.md +39 -358
  17. package/skills/alloy-guides/references/VIEWS_XML.md +36 -552
  18. package/skills/alloy-guides/references/WIDGETS.md +49 -127
  19. package/skills/alloy-howtos/SKILL.md +14 -169
  20. package/skills/alloy-howtos/references/best_practices.md +9 -113
  21. package/skills/alloy-howtos/references/cli_reference.md +18 -223
  22. package/skills/alloy-howtos/references/config_files.md +50 -133
  23. package/skills/alloy-howtos/references/debugging_troubleshooting.md +19 -63
  24. package/skills/alloy-howtos/references/samples.md +21 -138
  25. package/skills/ti-api/SKILL.md +10 -2
  26. package/skills/ti-api/references/api-android.md +36 -2
  27. package/skills/ti-api/references/api-app-platform.md +39 -3
  28. package/skills/ti-api/references/api-core.md +50 -18
  29. package/skills/ti-api/references/api-data-network.md +49 -35
  30. package/skills/ti-api/references/api-media.md +45 -27
  31. package/skills/ti-api/references/api-services.md +39 -9
  32. package/skills/ti-api/references/api-ui-android.md +33 -13
  33. package/skills/ti-api/references/api-ui-extras.md +41 -15
  34. package/skills/ti-api/references/api-ui-ios-animator.md +42 -26
  35. package/skills/ti-api/references/api-ui-ios.md +74 -2
  36. package/skills/ti-api/references/api-ui-lists.md +32 -16
  37. package/skills/ti-api/references/api-ui-text-input.md +34 -17
  38. package/skills/ti-api/references/api-ui-views.md +27 -1
  39. package/skills/ti-api/references/api-ui-windows-navigation.md +32 -18
  40. package/skills/ti-api/references/api-xml-global.md +66 -16
  41. package/skills/ti-create-release/SKILL.md +98 -0
  42. package/skills/ti-create-release/references/module-discovery.md +69 -0
  43. package/skills/ti-expert/references/adaptive-layouts.md +1 -1
  44. package/skills/ti-guides/SKILL.md +37 -76
  45. package/skills/ti-guides/references/advanced-data-and-images.md +122 -126
  46. package/skills/ti-guides/references/android-manifest.md +24 -83
  47. package/skills/ti-guides/references/app-distribution.md +31 -377
  48. package/skills/ti-guides/references/application-frameworks.md +127 -335
  49. package/skills/ti-guides/references/cli-reference.md +184 -633
  50. package/skills/ti-guides/references/commonjs-advanced.md +81 -231
  51. package/skills/ti-guides/references/compatibility-matrix.md +36 -75
  52. package/skills/ti-guides/references/hello-world.md +95 -70
  53. package/skills/ti-guides/references/hyperloop-native-access.md +52 -448
  54. package/skills/ti-guides/references/resources.md +174 -142
  55. package/skills/ti-guides/references/sdk-release-notes.md +28 -71
  56. package/skills/ti-guides/references/tiapp-config.md +222 -598
  57. package/skills/ti-howtos/SKILL.md +23 -123
  58. package/skills/ti-howtos/references/cross-platform-development.md +119 -324
  59. package/skills/ti-howtos/references/debugging-profiling.md +77 -445
  60. package/skills/ti-howtos/references/extending-titanium.md +199 -673
  61. package/skills/ti-howtos/references/local-data-sources.md +87 -300
  62. package/skills/ti-howtos/references/location-and-maps.md +86 -213
  63. package/skills/ti-howtos/references/media-apis.md +103 -223
  64. package/skills/ti-howtos/references/notification-services.md +86 -506
  65. package/skills/ti-howtos/references/remote-data-sources.md +97 -316
  66. package/skills/ti-howtos/references/using-modules.md +77 -133
  67. package/skills/ti-ui/SKILL.md +28 -143
  68. package/skills/ti-ui/references/icons-and-splash-screens.md +74 -403
  69. package/skills/ti-ui/references/layouts-and-positioning.md +175 -402
  70. package/skills/ti-ui/references/listviews-and-performance.md +100 -703
  71. package/skills/ti-ui/references/platform-conventions.md +180 -0
  72. package/skills/ti-ui/references/user-interface.md +43 -0
  73. package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +0 -102
  74. package/skills/alloy-howtos/references/custom_tags.md +0 -148
  75. package/skills/ti-guides/references/coding-best-practices.md +0 -149
  76. package/skills/ti-guides/references/javascript-primer.md +0 -414
  77. package/skills/ti-guides/references/reserved-words.md +0 -36
  78. package/skills/ti-guides/references/style-and-conventions.md +0 -103
  79. package/skills/ti-howtos/references/android-platform-deep-dives.md +0 -624
  80. package/skills/ti-howtos/references/automation-fastlane-appium.md +0 -96
  81. package/skills/ti-howtos/references/buffer-codec-streams.md +0 -162
  82. package/skills/ti-howtos/references/google-maps-v2.md +0 -172
  83. package/skills/ti-howtos/references/ios-map-kit.md +0 -149
  84. package/skills/ti-howtos/references/ios-platform-deep-dives.md +0 -611
  85. package/skills/ti-howtos/references/tutorials.md +0 -565
  86. package/skills/ti-howtos/references/web-content-integration.md +0 -287
  87. package/skills/ti-howtos/references/webpack-build-pipeline.md +0 -124
  88. package/skills/ti-ui/references/accessibility-deep-dive.md +0 -288
  89. package/skills/ti-ui/references/animation-and-matrices.md +0 -569
  90. package/skills/ti-ui/references/application-structures.md +0 -626
  91. package/skills/ti-ui/references/custom-fonts-styling.md +0 -549
  92. package/skills/ti-ui/references/event-handling.md +0 -401
  93. package/skills/ti-ui/references/gestures.md +0 -448
  94. package/skills/ti-ui/references/orientation.md +0 -374
  95. package/skills/ti-ui/references/platform-ui-android.md +0 -727
  96. package/skills/ti-ui/references/platform-ui-ios.md +0 -576
  97. package/skills/ti-ui/references/scrolling-views.md +0 -288
  98. package/skills/ti-ui/references/tableviews.md +0 -542
@@ -1,611 +0,0 @@
1
- # iOS platform deep dives
2
-
3
- <!-- TOC-START -->
4
- ## Contents
5
-
6
- - [1. iOS 17+ privacy requirements (critical)](#1-ios-17-privacy-requirements-critical)
7
- - [2. Background services and silent push](#2-background-services-and-silent-push)
8
- - [3. iCloud services and backup control](#3-icloud-services-and-backup-control)
9
- - [4. WatchKit and Ti.WatchSession](#4-watchkit-and-tiwatchsession)
10
- - [5. SiriKit and Siri intents](#5-sirikit-and-siri-intents)
11
- - [6. Spotlight search (Core Spotlight)](#6-spotlight-search-core-spotlight)
12
- - [7. Core Motion module](#7-core-motion-module)
13
- - [8. Handoff user activities](#8-handoff-user-activities)
14
- - [9. Additional iOS features](#9-additional-ios-features)
15
- - [Best practices summary](#best-practices-summary)
16
-
17
- <!-- TOC-END -->
18
-
19
- ## 1. iOS 17+ privacy requirements (critical)
20
- Apple requires declaring the use of certain APIs to prevent fingerprinting.
21
-
22
- ### PrivacyInfo.xcprivacy file
23
- Create this file in `app/assets/iphone/` (Alloy) or `Resources/iphone/` (Classic):
24
- ```xml
25
- <?xml version="1.0" encoding="UTF-8"?>
26
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
27
- <plist version="1.0">
28
- <dict>
29
- <key>NSPrivacyAccessedAPITypes</key>
30
- <array>
31
- <dict>
32
- <key>NSPrivacyAccessedAPIType</key>
33
- <string>NSPrivacyAccessedAPICategoryUserDefaults</string>
34
- <key>NSPrivacyAccessedAPITypeReasons</key>
35
- <array><string>AC6B.1</string></array>
36
- </dict>
37
- </array>
38
- </dict>
39
- </plist>
40
- ```
41
- Common categories: `UserDefaults` (Ti.App.Properties), `FileTimestamp` (file.createdAt), `SystemBootTime`.
42
-
43
- ## 2. Background services and silent push
44
-
45
- ### Overview
46
- iOS allows limited background execution. For large downloads, use the `com.titaniumsdk.urlSession` module.
47
-
48
- ### Silent push (background update)
49
- Wakes up the app to download content without showing a notification.
50
-
51
- `tiapp.xml`:
52
- ```xml
53
- <key>UIBackgroundModes</key>
54
- <array>
55
- <string>remote-notification</string>
56
- </array>
57
- ```
58
-
59
- `app.js`:
60
- ```javascript
61
- Ti.App.iOS.addEventListener('silentpush', (e) => {
62
- // Start download or update
63
- Ti.API.info(`Data received: ${JSON.stringify(e)}`);
64
-
65
- // Mandatory to call upon completion (max 30 seconds)
66
- Ti.App.iOS.endBackgroundHandler(e.handlerId);
67
- });
68
- ```
69
-
70
- ### Background fetch
71
- ```javascript
72
- // Enable in tiapp.xml:
73
- // <key>UIBackgroundModes</key>
74
- // <array><string>fetch</string></array>
75
-
76
- // Set minimum fetch interval
77
- Ti.App.iOS.setMinimumBackgroundFetchInterval(Ti.App.iOS.BACKGROUNDFETCHINTERVAL_MIN);
78
-
79
- Ti.App.iOS.addEventListener('backgroundfetch', (e) => {
80
- // Fetch new data
81
- Ti.API.info('Background fetch triggered');
82
-
83
- // Must call endBackgroundHandler when done (max 30 seconds)
84
- Ti.App.iOS.endBackgroundHandler(e.handlerId);
85
- });
86
-
87
- // To disable background fetch:
88
- // Ti.App.iOS.setMinimumBackgroundFetchInterval(Ti.App.iOS.BACKGROUNDFETCHINTERVAL_NEVER);
89
- ```
90
-
91
- ### URL Session module
92
- For large downloads that continue even if the app is suspended, use `com.titaniumsdk.urlSession`:
93
-
94
- ```javascript
95
- const urlSession = require('com.titaniumsdk.urlSession');
96
-
97
- const config = urlSession.createSessionConfiguration({
98
- identifier: 'com.myapp.downloads'
99
- });
100
-
101
- const session = urlSession.createSession({
102
- configuration: config
103
- });
104
-
105
- // Start a download task
106
- session.downloadTask({
107
- url: 'https://example.com/largefile.zip'
108
- });
109
-
110
- // Monitor progress
111
- session.addEventListener('downloadprogress', (e) => {
112
- Ti.API.info(`Progress: ${e.totalBytesWritten}/${e.totalBytesExpectedToWrite}`);
113
- });
114
-
115
- session.addEventListener('downloadcompleted', (e) => {
116
- Ti.API.info(`Download saved to: ${e.data}`);
117
- });
118
-
119
- session.addEventListener('sessioncompleted', (e) => {
120
- if (!e.success) {
121
- Ti.API.error(`Session error: ${e.errorDescription}`);
122
- }
123
- });
124
-
125
- // Invalidate session when no longer needed
126
- session.invalidateAndCancel();
127
- ```
128
-
129
- ## 3. iCloud services and backup control
130
-
131
- ### Disable individual backup (best practice)
132
- Apple rejects apps that upload unnecessary data to iCloud. Disable backup for temporary or recreatable files.
133
-
134
- ```javascript
135
- const file = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, 'cache.dat');
136
- file.remoteBackup = false; // Prevents upload to iCloud/iTunes
137
- ```
138
-
139
- ### Recursive folder backup disable
140
- ```javascript
141
- function disableiCloudBackup(folder) {
142
- const dir = Ti.Filesystem.getFile(folder);
143
- const files = dir.getDirectoryListing();
144
- files.forEach((name) => {
145
- const f = Ti.Filesystem.getFile(folder, name);
146
- f.remoteBackup = false;
147
- if (f.isDirectory()) disableiCloudBackup(f.nativePath);
148
- });
149
- }
150
- ```
151
-
152
- ## 4. WatchKit and Ti.WatchSession
153
-
154
- For watchOS 2+, use `Ti.WatchSession` for bidirectional communication.
155
-
156
- ### Activate session
157
- ```javascript
158
- if (Ti.WatchSession.isSupported) {
159
- Ti.WatchSession.activateSession();
160
- }
161
- ```
162
-
163
- ### Send message (immediate)
164
- ```javascript
165
- if (Ti.WatchSession.isReachable) {
166
- Ti.WatchSession.sendMessage({
167
- orderId: '123',
168
- status: 'shipped'
169
- });
170
- }
171
- ```
172
-
173
- ### Receive data from Watch
174
- ```javascript
175
- Ti.WatchSession.addEventListener('receivemessage', (e) => {
176
- Ti.API.info(`Message from Watch: ${e.message}`);
177
- });
178
- ```
179
-
180
- ### Provisioning profiles for Watch
181
- Both the iOS app and WatchKit extension need separate provisioning profiles. Configure in `tiapp.xml`:
182
- ```xml
183
- <ios>
184
- <extensions>
185
- <extension projectPath="extensions/WatchApp/WatchApp.xcodeproj">
186
- <target name="WatchApp Extension">
187
- <provisioning-profiles>
188
- <device>WATCH_DEV_PROFILE_UUID</device>
189
- <dist-appstore>WATCH_DIST_PROFILE_UUID</dist-appstore>
190
- </provisioning-profiles>
191
- </target>
192
- </extension>
193
- </extensions>
194
- </ios>
195
- ```
196
-
197
- Note: for Xcode 8+, ensure your Team ID matches across all targets.
198
-
199
- ## 5. SiriKit and Siri intents
200
-
201
- Allows your app to respond to Siri voice commands (Messaging, Payments, Workouts).
202
-
203
- ### Configuration in tiapp.xml
204
- ```xml
205
- <key>NSSiriUsageDescription</key>
206
- <string>Siri will use your voice to send messages in this app.</string>
207
- ```
208
-
209
- ### Siri extensions
210
- Create an Intents Extension in Xcode and add it to the `extensions/` folder. Then register it in `tiapp.xml`:
211
- ```xml
212
- <ios>
213
- <extensions>
214
- <extension projectPath="extensions/SiriIntent/SiriIntent.xcodeproj">
215
- <target name="SiriIntent">
216
- <provisioning-profiles>
217
- <device>PROVISIONING_PROFILE_UUID</device>
218
- </provisioning-profiles>
219
- </target>
220
- </extension>
221
- </extensions>
222
- </ios>
223
- ```
224
-
225
- ### Implementation steps
226
- 1. Register App ID with SiriKit capability in Apple Developer Portal.
227
- 2. Create Intents Extension in Xcode (File > New > Target > Intents Extension).
228
- 3. Configure entitlements (add `com.apple.developer.siri`).
229
- 4. Add extension to project (place in `extensions/` folder).
230
- 5. Register in `tiapp.xml` with provisioning profiles for the extension target.
231
- 6. Handle intents in the native extension code (Swift/Objective-C).
232
-
233
- Note: SiriKit requires native code in the Intent Extension. The Titanium app receives results via `continueactivity` events.
234
-
235
- ## 6. Spotlight search (Core Spotlight)
236
-
237
- Indexes your app content to appear in global iOS search results.
238
-
239
- ```javascript
240
- const itemAttr = Ti.App.iOS.createSearchableItemAttributeSet({
241
- itemContentType: Ti.App.iOS.UTTYPE_TEXT,
242
- title: 'My Article',
243
- contentDescription: 'Content description...',
244
- keywords: ['titanium', 'help']
245
- });
246
-
247
- const item = Ti.App.iOS.createSearchableItem({
248
- uniqueIdentifier: 'id-123',
249
- domainIdentifier: 'articles',
250
- attributeSet: itemAttr
251
- });
252
-
253
- const indexer = Ti.App.iOS.createSearchableIndex();
254
- indexer.addToDefaultSearchableIndex([item], (e) => {
255
- if (e.success) Ti.API.info('Indexed!');
256
- });
257
- ```
258
-
259
- ## 7. Core Motion module
260
-
261
- ### Overview
262
- Core Motion provides access to hardware sensors: accelerometer, gyroscope, magnetometer, and more.
263
-
264
- Requirements:
265
- - Add module to `tiapp.xml`:
266
- ```xml
267
- <modules>
268
- <module platform="iphone">ti.coremotion</module>
269
- </modules>
270
- ```
271
-
272
- - Can only test on device, not simulator
273
- - Motion Activity permission required for Activity API
274
-
275
- ### Basic workflow
276
-
277
- 1. Require the module:
278
- ```javascript
279
- var CoreMotion = require('ti.coremotion');
280
- ```
281
-
282
- 2. Check availability:
283
- ```javascript
284
- var Accelerometer = CoreMotion.createAccelerometer();
285
- if (Accelerometer.isAccelerometerAvailable()) {
286
- // Use accelerometer
287
- }
288
- ```
289
-
290
- 3. Start updates:
291
- ```javascript
292
- Accelerometer.setAccelerometerUpdateInterval(1000); // 1 second
293
- Accelerometer.startAccelerometerUpdates((e) => {
294
- if (e.success) {
295
- const data = e.acceleration;
296
- Ti.API.info(`X: ${data.x} Y: ${data.y} Z: ${data.z}`);
297
- }
298
- });
299
- ```
300
-
301
- 4. Stop when done:
302
- ```javascript
303
- Accelerometer.stopAccelerometerUpdates();
304
- ```
305
-
306
- ### Coordinate system
307
- Hold device in portrait mode, screen facing you:
308
- - X-axis: width (positive = right, negative = left)
309
- - Y-axis: height (positive = up, negative = down)
310
- - Z-axis: through screen (positive = toward screen, negative = behind)
311
-
312
- ### Accelerometer
313
-
314
- Measures g-force acceleration along three axes.
315
-
316
- ```javascript
317
- var CoreMotion = require('ti.coremotion');
318
- var Accelerometer = CoreMotion.createAccelerometer();
319
-
320
- if (Accelerometer.isAccelerometerAvailable()) {
321
- Accelerometer.setAccelerometerUpdateInterval(100);
322
- Accelerometer.startAccelerometerUpdates(function(e) {
323
- if (e.success) {
324
- var data = e.acceleration;
325
- updateDisplay(data.x, data.y, data.z);
326
- }
327
- });
328
- }
329
- ```
330
-
331
- Use for: shake detection, device orientation, movement detection.
332
-
333
- ### Gyroscope
334
-
335
- Measures rotational rate along three axes (radians).
336
-
337
- ```javascript
338
- var Gyroscope = CoreMotion.createGyroscope();
339
-
340
- if (Gyroscope.isGyroAvailable()) {
341
- Gyroscope.setGyroUpdateInterval(100);
342
- Gyroscope.startGyroUpdates(function(e) {
343
- if (e.success) {
344
- var data = e.rotationRate;
345
- Ti.API.info('Rotation: X=' + data.x + ' Y=' + data.y + ' Z=' + data.z);
346
- }
347
- });
348
- }
349
- ```
350
-
351
- Use for: rotation gestures, 3D motion tracking, enhanced UI.
352
-
353
- ### Magnetometer
354
-
355
- Measures magnetic field strength (microteslas). Acts as a digital compass.
356
-
357
- ```javascript
358
- var Magnetometer = CoreMotion.createMagnetometer();
359
-
360
- if (Magnetometer.isMagnetometerAvailable()) {
361
- Magnetometer.startMagnetometerUpdates();
362
- // Or poll manually:
363
- var data = Magnetometer.getMagnetometerData();
364
- Ti.API.info('Magnetic field: ' + JSON.stringify(data.magneticField));
365
- }
366
- ```
367
-
368
- Use for: compass direction, magnetic field detection.
369
-
370
- ### Device motion
371
-
372
- Combines accelerometer, gyroscope, and magnetometer for attitude and user acceleration.
373
-
374
- ```javascript
375
- var DeviceMotion = CoreMotion.createDeviceMotion();
376
-
377
- if (DeviceMotion.isDeviceMotionAvailable()) {
378
- DeviceMotion.setDeviceMotionUpdateInterval(500);
379
-
380
- // Check available reference frames
381
- var frames = DeviceMotion.availableAttitudeReferenceFrames();
382
-
383
- if (frames & CoreMotion.ATTITUDE_REFERENCE_FRAME_X_TRUE_NORTH_Z_VERTICAL) {
384
- // Use true north reference
385
- DeviceMotion.startDeviceMotionUpdatesUsingReferenceFrame(
386
- { referenceFrame: CoreMotion.ATTITUDE_REFERENCE_FRAME_X_TRUE_NORTH_Z_VERTICAL },
387
- (e) => {
388
- if (e.success) {
389
- // Attitude: orientation (pitch, roll, yaw)
390
- const attitude = e.attitude;
391
- Ti.API.info(`Pitch: ${attitude.pitch} Roll: ${attitude.roll} Yaw: ${attitude.yaw}`);
392
-
393
- // User acceleration: force applied by user (not gravity)
394
- const userAccel = e.userAcceleration;
395
- }
396
- }
397
- );
398
- }
399
- }
400
- ```
401
-
402
- Attitude formats:
403
- - Pitch/Roll/Yaw (Euler angles)
404
- - Quaternion (w, x, y, z)
405
- - Rotation Matrix (m11-m33)
406
-
407
- Reference frames:
408
- - `ATTITUDE_REFERENCE_FRAME_X_ARBITRARY_Z_VERTICAL` - default
409
- - `ATTITUDE_REFERENCE_FRAME_X_ARBITRARY_CORRECTED_Z_VERTICAL` - uses magnetometer for yaw
410
- - `ATTITUDE_REFERENCE_FRAME_X_MAGNETIC_NORTH_Z_VERTICAL` - magnetic north
411
- - `ATTITUDE_REFERENCE_FRAME_X_TRUE_NORTH_Z_VERTICAL` - true north (requires location)
412
-
413
- ### Activity API
414
-
415
- ```javascript
416
- const MotionActivity = CoreMotion.createMotionActivity();
417
-
418
- MotionActivity.startActivityUpdates((e) => {
419
- const activity = e.activity;
420
-
421
- // Check confidence
422
- if (activity.confidence !== CoreMotion.MOTION_ACTIVITY_CONFIDENCE_LOW) {
423
- if (activity.walking) {
424
- Ti.API.info('User is walking');
425
- } else if (activity.running) {
426
- Ti.API.info('User is running');
427
- } else if (activity.automotive) {
428
- Ti.API.info('User in vehicle');
429
- } else if (activity.stationary) {
430
- Ti.API.info('Device stationary');
431
- }
432
- }
433
- });
434
- ```
435
-
436
- Query historical activity:
437
- ```javascript
438
- var endDate = new Date();
439
- var startDate = new Date(endDate.getTime() - 60 * 60 * 1000); // 1 hour ago
440
-
441
- MotionActivity.queryActivity({
442
- start: startDate,
443
- end: endDate
444
- }, function(e) {
445
- var activities = e.activities;
446
- // Process historical data
447
- });
448
- ```
449
-
450
- Requires Motion Activity permission in `tiapp.xml`:
451
- ```xml
452
- <key>NSMotionUsageDescription</key>
453
- <string>Need motion data for fitness tracking</string>
454
- ```
455
-
456
- ### Pedometer
457
-
458
- ```javascript
459
- const Pedometer = CoreMotion.createPedometer();
460
-
461
- if (Pedometer.isStepCountingAvailable()) {
462
- // Start live updates
463
- Pedometer.startPedometerUpdates({
464
- start: new Date(new Date().getTime() - (60 * 60 * 1000)) // From 1 hour ago
465
- }, (e) => {
466
- Ti.API.info(`Steps: ${e.numberOfSteps}`);
467
- Ti.API.info(`Distance: ${e.distance} meters`);
468
- Ti.API.info(`Floors up: ${e.floorsAscended}`);
469
- Ti.API.info(`Floors down: ${e.floorsDescended}`);
470
- });
471
- }
472
-
473
- // Query historical data
474
- var endDate = new Date();
475
- var startDate = new Date(endDate.getTime() - 24 * 60 * 60 * 1000); // 24 hours ago
476
-
477
- Pedometer.queryPedometerData({
478
- start: startDate,
479
- end: endDate
480
- }, function(e) {
481
- Ti.API.info('Steps in last 24h: ' + e.numberOfSteps);
482
- });
483
- ```
484
-
485
- Use for: fitness apps, step challenges, activity tracking.
486
-
487
- ### Core Motion best practices
488
-
489
- 1. Always check availability; not all devices have all sensors.
490
- 2. Set appropriate update intervals; high frequency means more CPU/battery.
491
- 3. Stop updates when not needed to conserve battery.
492
- 4. Handle errors gracefully; sensors can fail or be unavailable.
493
- 5. Test on physical devices; sensors do not work in simulator.
494
-
495
- ## 8. Handoff user activities
496
-
497
- ```javascript
498
- const UserActivity = Ti.App.iOS.createUserActivity({
499
- activityType: 'com.myapp.reading-article',
500
- title: 'Reading: Titanium SDK Guide',
501
- userInfo: {
502
- articleId: '123',
503
- scrollPosition: 450
504
- },
505
- webpageURL: 'https://myapp.com/articles/123' // For web fallback
506
- });
507
-
508
- // Mark as current activity
509
- UserActivity.becomeCurrent();
510
- ```
511
-
512
- ### Handling incoming Handoff
513
-
514
- ```javascript
515
- Ti.App.iOS.addEventListener('continueactivity', function(e) {
516
- if (e.activityType === 'com.myapp.reading-article') {
517
- var userInfo = e.userInfo;
518
-
519
- // Restore activity state
520
- openArticle(userInfo.articleId, {
521
- scrollTo: userInfo.scrollPosition
522
- });
523
- }
524
- });
525
- ```
526
-
527
- ### Invalidating activities
528
-
529
- ```javascript
530
- // When user closes article
531
- UserActivity.invalidate();
532
- ```
533
-
534
- ### Declaring activity types in tiapp.xml
535
-
536
- ```xml
537
- <key>NSUserActivityTypes</key>
538
- <array>
539
- <string>com.myapp.reading-article</string>
540
- <string>com.myapp.editing-document</string>
541
- <string>com.myapp.viewing-product</string>
542
- </array>
543
- ```
544
-
545
- ### Requirements
546
- - Both devices must be signed into the same iCloud account
547
- - Bluetooth LE must be enabled on both devices
548
- - Both devices must be on the same Wi-Fi network
549
- - Test with Safari first to verify Handoff works between your devices
550
-
551
- ## 9. Additional iOS features
552
-
553
- ### 3D Touch (Force Touch)
554
-
555
- ```javascript
556
- // Check for 3D Touch support
557
- if (Ti.Platform.forceTouchSupported) {
558
- view.addEventListener('touchstart', (e) => {
559
- const force = e.force || 0;
560
- const maxForce = e.maximumForce || 1;
561
-
562
- if (force / maxForce > 0.75) {
563
- // Deep press
564
- showQuickActions();
565
- }
566
- });
567
- }
568
- ```
569
-
570
- ### Haptic feedback
571
-
572
- ```javascript
573
- // Generate haptic feedback
574
- const generator = Ti.UI.iOS.createHapticFeedbackGenerator();
575
-
576
- // Impact feedback (light, medium, heavy)
577
- generator.impactOccurred(Ti.UI.iOS.HAPTIC_FEEDBACK_STYLE_MEDIUM);
578
-
579
- // Selection feedback
580
- generator.selectionChanged();
581
-
582
- // Notification feedback (success, warning, error)
583
- generator.notificationOccurred(Ti.UI.iOS.HAPTIC_FEEDBACK_TYPE_SUCCESS);
584
- ```
585
-
586
- ### Document interaction
587
-
588
- Open documents in other apps:
589
-
590
- ```javascript
591
- var docController = Ti.UI.iOS.createDocumentViewer({
592
- url: file.nativePath
593
- });
594
-
595
- docController.addEventListener('complete', function(e) {
596
- Ti.API.info('Document interaction complete');
597
- });
598
-
599
- win.add(docController);
600
- ```
601
-
602
- ## Best practices summary
603
-
604
- 1. Background services: use sparingly; stop when done.
605
- 2. Core Motion: check availability and test on device.
606
- 3. Spotlight: index content as it changes.
607
- 4. Handoff: provide a web URL fallback.
608
- 5. iCloud: use for small synced data, not large files.
609
- 6. SiriKit: requires native extension; use only if beneficial.
610
- 7. Permissions: always include usage descriptions in `tiapp.xml`.
611
- 8. Testing: many features require physical device testing.