@maccesar/titools 2.2.4 → 2.2.8
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.
- package/README.md +23 -23
- package/lib/commands/update.js +4 -12
- package/package.json +1 -1
- package/skills/alloy-guides/SKILL.md +31 -31
- package/skills/alloy-guides/references/CONCEPTS.md +3 -3
- package/skills/alloy-guides/references/CONTROLLERS.md +1 -1
- package/skills/alloy-guides/references/MODELS.md +6 -6
- package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +1 -1
- package/skills/alloy-guides/references/VIEWS_XML.md +1 -1
- package/skills/alloy-guides/references/WIDGETS.md +1 -1
- package/skills/alloy-howtos/SKILL.md +27 -27
- package/skills/alloy-howtos/references/best_practices.md +9 -9
- package/skills/alloy-howtos/references/cli_reference.md +14 -14
- package/skills/alloy-howtos/references/config_files.md +16 -16
- package/skills/alloy-howtos/references/custom_tags.md +16 -16
- package/skills/alloy-howtos/references/debugging_troubleshooting.md +11 -15
- package/skills/alloy-howtos/references/samples.md +19 -19
- package/skills/purgetss/SKILL.md +11 -1
- package/skills/purgetss/references/animation-system.md +1 -1
- package/skills/purgetss/references/cli-commands.md +3 -3
- package/skills/purgetss/references/customization-deep-dive.md +1 -1
- package/skills/purgetss/references/dynamic-component-creation.md +1 -1
- package/skills/purgetss/references/icon-fonts.md +4 -0
- package/skills/purgetss/references/installation-setup.md +8 -1
- package/skills/purgetss/references/migration-guide.md +4 -0
- package/skills/purgetss/references/tikit-components.md +193 -204
- package/skills/purgetss/references/ui-ux-design.md +1 -1
- package/skills/ti-expert/SKILL.md +78 -118
- package/skills/ti-expert/references/alloy-builtins.md +18 -18
- package/skills/ti-expert/references/alloy-structure.md +21 -21
- package/skills/ti-expert/references/anti-patterns.md +15 -15
- package/skills/ti-expert/references/cli-expert.md +15 -15
- package/skills/ti-expert/references/code-conventions.md +38 -38
- package/skills/ti-expert/references/contracts.md +8 -8
- package/skills/ti-expert/references/controller-patterns.md +14 -14
- package/skills/ti-expert/references/error-handling.md +11 -11
- package/skills/ti-expert/references/examples.md +12 -12
- package/skills/ti-expert/references/migration-patterns.md +24 -24
- package/skills/ti-expert/references/patterns.md +10 -10
- package/skills/ti-expert/references/performance-listview.md +16 -16
- package/skills/ti-expert/references/performance-optimization.md +41 -41
- package/skills/ti-expert/references/security-device.md +22 -22
- package/skills/ti-expert/references/security-fundamentals.md +19 -19
- package/skills/ti-expert/references/state-management.md +33 -33
- package/skills/ti-expert/references/testing-e2e-ci.md +25 -25
- package/skills/ti-expert/references/testing-unit.md +24 -24
- package/skills/ti-expert/references/theming.md +15 -15
- package/skills/ti-guides/SKILL.md +58 -60
- package/skills/ti-guides/references/advanced-data-and-images.md +33 -33
- package/skills/ti-guides/references/android-manifest.md +15 -15
- package/skills/ti-guides/references/app-distribution.md +70 -166
- package/skills/ti-guides/references/application-frameworks.md +96 -114
- package/skills/ti-guides/references/cli-reference.md +294 -294
- package/skills/ti-guides/references/coding-best-practices.md +42 -33
- package/skills/ti-guides/references/commonjs-advanced.md +57 -51
- package/skills/ti-guides/references/hello-world.md +36 -36
- package/skills/ti-guides/references/hyperloop-native-access.md +66 -66
- package/skills/ti-guides/references/javascript-primer.md +83 -101
- package/skills/ti-guides/references/reserved-words.md +9 -9
- package/skills/ti-guides/references/resources.md +75 -83
- package/skills/ti-guides/references/style-and-conventions.md +35 -28
- package/skills/ti-guides/references/tiapp-config.md +110 -74
- package/skills/ti-howtos/SKILL.md +88 -92
- package/skills/ti-howtos/references/android-platform-deep-dives.md +104 -104
- package/skills/ti-howtos/references/automation-fastlane-appium.md +39 -39
- package/skills/ti-howtos/references/buffer-codec-streams.md +60 -60
- package/skills/ti-howtos/references/cross-platform-development.md +115 -136
- package/skills/ti-howtos/references/debugging-profiling.md +167 -181
- package/skills/ti-howtos/references/extending-titanium.md +121 -121
- package/skills/ti-howtos/references/google-maps-v2.md +84 -82
- package/skills/ti-howtos/references/ios-map-kit.md +65 -60
- package/skills/ti-howtos/references/ios-platform-deep-dives.md +123 -123
- package/skills/ti-howtos/references/local-data-sources.md +79 -78
- package/skills/ti-howtos/references/location-and-maps.md +116 -120
- package/skills/ti-howtos/references/media-apis.md +87 -86
- package/skills/ti-howtos/references/notification-services.md +250 -260
- package/skills/ti-howtos/references/remote-data-sources.md +98 -93
- package/skills/ti-howtos/references/tutorials.md +226 -216
- package/skills/ti-howtos/references/using-modules.md +73 -102
- package/skills/ti-howtos/references/web-content-integration.md +101 -103
- package/skills/ti-howtos/references/webpack-build-pipeline.md +52 -44
- package/skills/ti-ui/SKILL.md +85 -85
- package/skills/ti-ui/references/accessibility-deep-dive.md +57 -57
- package/skills/ti-ui/references/animation-and-matrices.md +79 -79
- package/skills/ti-ui/references/application-structures.md +96 -99
- package/skills/ti-ui/references/custom-fonts-styling.md +99 -99
- package/skills/ti-ui/references/event-handling.md +58 -58
- package/skills/ti-ui/references/gestures.md +62 -64
- package/skills/ti-ui/references/icons-and-splash-screens.md +88 -88
- package/skills/ti-ui/references/layouts-and-positioning.md +87 -97
- package/skills/ti-ui/references/listviews-and-performance.md +107 -107
- package/skills/ti-ui/references/orientation.md +87 -88
- package/skills/ti-ui/references/platform-ui-android.md +87 -81
- package/skills/ti-ui/references/platform-ui-ios.md +63 -61
- package/skills/ti-ui/references/scrolling-views.md +29 -29
- package/skills/ti-ui/references/tableviews.md +56 -56
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
# iOS
|
|
1
|
+
# iOS platform deep dives
|
|
2
2
|
|
|
3
|
-
## 1. iOS 17+
|
|
4
|
-
Apple requires declaring the use of certain APIs to prevent
|
|
3
|
+
## 1. iOS 17+ privacy requirements (critical)
|
|
4
|
+
Apple requires declaring the use of certain APIs to prevent fingerprinting.
|
|
5
5
|
|
|
6
|
-
### PrivacyInfo.xcprivacy
|
|
6
|
+
### PrivacyInfo.xcprivacy file
|
|
7
7
|
Create this file in `app/assets/iphone/` (Alloy) or `Resources/iphone/` (Classic):
|
|
8
8
|
```xml
|
|
9
9
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
@@ -22,17 +22,17 @@ Create this file in `app/assets/iphone/` (Alloy) or `Resources/iphone/` (Classic
|
|
|
22
22
|
</dict>
|
|
23
23
|
</plist>
|
|
24
24
|
```
|
|
25
|
-
|
|
25
|
+
Common categories: `UserDefaults` (Ti.App.Properties), `FileTimestamp` (file.createdAt), `SystemBootTime`.
|
|
26
26
|
|
|
27
|
-
## 2. Background
|
|
27
|
+
## 2. Background services and silent push
|
|
28
28
|
|
|
29
29
|
### Overview
|
|
30
30
|
iOS allows limited background execution. For large downloads, use the `com.titaniumsdk.urlSession` module.
|
|
31
31
|
|
|
32
|
-
### Silent
|
|
33
|
-
|
|
32
|
+
### Silent push (background update)
|
|
33
|
+
Wakes up the app to download content without showing a notification.
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
`tiapp.xml`:
|
|
36
36
|
```xml
|
|
37
37
|
<key>UIBackgroundModes</key>
|
|
38
38
|
<array>
|
|
@@ -40,18 +40,18 @@ Allows waking up the app to download content without showing a notification to t
|
|
|
40
40
|
</array>
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
`app.js`:
|
|
44
44
|
```javascript
|
|
45
45
|
Ti.App.iOS.addEventListener('silentpush', (e) => {
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
// Start download or update
|
|
47
|
+
Ti.API.info(`Data received: ${JSON.stringify(e)}`);
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
// Mandatory to call upon completion (max 30 seconds)
|
|
50
|
+
Ti.App.iOS.endBackgroundHandler(e.handlerId);
|
|
51
51
|
});
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
### Background
|
|
54
|
+
### Background fetch
|
|
55
55
|
```javascript
|
|
56
56
|
// Enable in tiapp.xml:
|
|
57
57
|
// <key>UIBackgroundModes</key>
|
|
@@ -61,58 +61,58 @@ Ti.App.iOS.addEventListener('silentpush', (e) => {
|
|
|
61
61
|
Ti.App.iOS.setMinimumBackgroundFetchInterval(Ti.App.iOS.BACKGROUNDFETCHINTERVAL_MIN);
|
|
62
62
|
|
|
63
63
|
Ti.App.iOS.addEventListener('backgroundfetch', (e) => {
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
// Fetch new data
|
|
65
|
+
Ti.API.info('Background fetch triggered');
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
// Must call endBackgroundHandler when done (max 30 seconds)
|
|
68
|
+
Ti.App.iOS.endBackgroundHandler(e.handlerId);
|
|
69
69
|
});
|
|
70
70
|
|
|
71
71
|
// To disable background fetch:
|
|
72
72
|
// Ti.App.iOS.setMinimumBackgroundFetchInterval(Ti.App.iOS.BACKGROUNDFETCHINTERVAL_NEVER);
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
-
### URL Session
|
|
76
|
-
For large downloads that continue even if the app is suspended, use
|
|
75
|
+
### URL Session module
|
|
76
|
+
For large downloads that continue even if the app is suspended, use `com.titaniumsdk.urlSession`:
|
|
77
77
|
|
|
78
78
|
```javascript
|
|
79
79
|
const urlSession = require('com.titaniumsdk.urlSession');
|
|
80
80
|
|
|
81
81
|
const config = urlSession.createSessionConfiguration({
|
|
82
|
-
|
|
82
|
+
identifier: 'com.myapp.downloads'
|
|
83
83
|
});
|
|
84
84
|
|
|
85
85
|
const session = urlSession.createSession({
|
|
86
|
-
|
|
86
|
+
configuration: config
|
|
87
87
|
});
|
|
88
88
|
|
|
89
89
|
// Start a download task
|
|
90
90
|
session.downloadTask({
|
|
91
|
-
|
|
91
|
+
url: 'https://example.com/largefile.zip'
|
|
92
92
|
});
|
|
93
93
|
|
|
94
94
|
// Monitor progress
|
|
95
95
|
session.addEventListener('downloadprogress', (e) => {
|
|
96
|
-
|
|
96
|
+
Ti.API.info(`Progress: ${e.totalBytesWritten}/${e.totalBytesExpectedToWrite}`);
|
|
97
97
|
});
|
|
98
98
|
|
|
99
99
|
session.addEventListener('downloadcompleted', (e) => {
|
|
100
|
-
|
|
100
|
+
Ti.API.info(`Download saved to: ${e.data}`);
|
|
101
101
|
});
|
|
102
102
|
|
|
103
103
|
session.addEventListener('sessioncompleted', (e) => {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
if (!e.success) {
|
|
105
|
+
Ti.API.error(`Session error: ${e.errorDescription}`);
|
|
106
|
+
}
|
|
107
107
|
});
|
|
108
108
|
|
|
109
109
|
// Invalidate session when no longer needed
|
|
110
110
|
session.invalidateAndCancel();
|
|
111
111
|
```
|
|
112
112
|
|
|
113
|
-
## 3. iCloud
|
|
113
|
+
## 3. iCloud services and backup control
|
|
114
114
|
|
|
115
|
-
### Disable
|
|
115
|
+
### Disable individual backup (best practice)
|
|
116
116
|
Apple rejects apps that upload unnecessary data to iCloud. Disable backup for temporary or recreatable files.
|
|
117
117
|
|
|
118
118
|
```javascript
|
|
@@ -120,49 +120,49 @@ const file = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, 'cach
|
|
|
120
120
|
file.remoteBackup = false; // Prevents upload to iCloud/iTunes
|
|
121
121
|
```
|
|
122
122
|
|
|
123
|
-
### Recursive
|
|
123
|
+
### Recursive folder backup disable
|
|
124
124
|
```javascript
|
|
125
125
|
function disableiCloudBackup(folder) {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
126
|
+
const dir = Ti.Filesystem.getFile(folder);
|
|
127
|
+
const files = dir.getDirectoryListing();
|
|
128
|
+
files.forEach((name) => {
|
|
129
|
+
const f = Ti.Filesystem.getFile(folder, name);
|
|
130
|
+
f.remoteBackup = false;
|
|
131
|
+
if (f.isDirectory()) disableiCloudBackup(f.nativePath);
|
|
132
|
+
});
|
|
133
133
|
}
|
|
134
134
|
```
|
|
135
135
|
|
|
136
|
-
## 4. WatchKit
|
|
136
|
+
## 4. WatchKit and Ti.WatchSession
|
|
137
137
|
|
|
138
138
|
For watchOS 2+, use `Ti.WatchSession` for bidirectional communication.
|
|
139
139
|
|
|
140
|
-
### Activate
|
|
140
|
+
### Activate session
|
|
141
141
|
```javascript
|
|
142
142
|
if (Ti.WatchSession.isSupported) {
|
|
143
|
-
|
|
143
|
+
Ti.WatchSession.activateSession();
|
|
144
144
|
}
|
|
145
145
|
```
|
|
146
146
|
|
|
147
|
-
### Send
|
|
147
|
+
### Send message (immediate)
|
|
148
148
|
```javascript
|
|
149
149
|
if (Ti.WatchSession.isReachable) {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
150
|
+
Ti.WatchSession.sendMessage({
|
|
151
|
+
orderId: '123',
|
|
152
|
+
status: 'shipped'
|
|
153
|
+
});
|
|
154
154
|
}
|
|
155
155
|
```
|
|
156
156
|
|
|
157
|
-
### Receive
|
|
157
|
+
### Receive data from Watch
|
|
158
158
|
```javascript
|
|
159
159
|
Ti.WatchSession.addEventListener('receivemessage', (e) => {
|
|
160
|
-
|
|
160
|
+
Ti.API.info(`Message from Watch: ${e.message}`);
|
|
161
161
|
});
|
|
162
162
|
```
|
|
163
163
|
|
|
164
|
-
### Provisioning
|
|
165
|
-
Both the iOS app and WatchKit extension need separate provisioning profiles. Configure in tiapp.xml
|
|
164
|
+
### Provisioning profiles for Watch
|
|
165
|
+
Both the iOS app and WatchKit extension need separate provisioning profiles. Configure in `tiapp.xml`:
|
|
166
166
|
```xml
|
|
167
167
|
<ios>
|
|
168
168
|
<extensions>
|
|
@@ -178,9 +178,9 @@ Both the iOS app and WatchKit extension need separate provisioning profiles. Con
|
|
|
178
178
|
</ios>
|
|
179
179
|
```
|
|
180
180
|
|
|
181
|
-
|
|
181
|
+
Note: for Xcode 8+, ensure your Team ID matches across all targets.
|
|
182
182
|
|
|
183
|
-
## 5. SiriKit
|
|
183
|
+
## 5. SiriKit and Siri intents
|
|
184
184
|
|
|
185
185
|
Allows your app to respond to Siri voice commands (Messaging, Payments, Workouts).
|
|
186
186
|
|
|
@@ -190,8 +190,8 @@ Allows your app to respond to Siri voice commands (Messaging, Payments, Workouts
|
|
|
190
190
|
<string>Siri will use your voice to send messages in this app.</string>
|
|
191
191
|
```
|
|
192
192
|
|
|
193
|
-
### Siri
|
|
194
|
-
|
|
193
|
+
### Siri extensions
|
|
194
|
+
Create an Intents Extension in Xcode and add it to the `extensions/` folder. Then register it in `tiapp.xml`:
|
|
195
195
|
```xml
|
|
196
196
|
<ios>
|
|
197
197
|
<extensions>
|
|
@@ -206,46 +206,46 @@ Requires creating an **Intents Extension** in Xcode and adding it to the `extens
|
|
|
206
206
|
</ios>
|
|
207
207
|
```
|
|
208
208
|
|
|
209
|
-
### Implementation
|
|
210
|
-
1.
|
|
211
|
-
2.
|
|
212
|
-
3.
|
|
213
|
-
4.
|
|
214
|
-
5.
|
|
215
|
-
6.
|
|
209
|
+
### Implementation steps
|
|
210
|
+
1. Register App ID with SiriKit capability in Apple Developer Portal.
|
|
211
|
+
2. Create Intents Extension in Xcode (File > New > Target > Intents Extension).
|
|
212
|
+
3. Configure entitlements (add `com.apple.developer.siri`).
|
|
213
|
+
4. Add extension to project (place in `extensions/` folder).
|
|
214
|
+
5. Register in `tiapp.xml` with provisioning profiles for the extension target.
|
|
215
|
+
6. Handle intents in the native extension code (Swift/Objective-C).
|
|
216
216
|
|
|
217
|
-
|
|
217
|
+
Note: SiriKit requires native code in the Intent Extension. The Titanium app receives results via `continueactivity` events.
|
|
218
218
|
|
|
219
|
-
## 6. Spotlight
|
|
219
|
+
## 6. Spotlight search (Core Spotlight)
|
|
220
220
|
|
|
221
|
-
Indexes your app
|
|
221
|
+
Indexes your app content to appear in global iOS search results.
|
|
222
222
|
|
|
223
223
|
```javascript
|
|
224
224
|
const itemAttr = Ti.App.iOS.createSearchableItemAttributeSet({
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
225
|
+
itemContentType: Ti.App.iOS.UTTYPE_TEXT,
|
|
226
|
+
title: 'My Article',
|
|
227
|
+
contentDescription: 'Content description...',
|
|
228
|
+
keywords: ['titanium', 'help']
|
|
229
229
|
});
|
|
230
230
|
|
|
231
231
|
const item = Ti.App.iOS.createSearchableItem({
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
232
|
+
uniqueIdentifier: 'id-123',
|
|
233
|
+
domainIdentifier: 'articles',
|
|
234
|
+
attributeSet: itemAttr
|
|
235
235
|
});
|
|
236
236
|
|
|
237
237
|
const indexer = Ti.App.iOS.createSearchableIndex();
|
|
238
238
|
indexer.addToDefaultSearchableIndex([item], (e) => {
|
|
239
|
-
|
|
239
|
+
if (e.success) Ti.API.info('Indexed!');
|
|
240
240
|
});
|
|
241
241
|
```
|
|
242
242
|
|
|
243
|
-
## 7. Core Motion
|
|
243
|
+
## 7. Core Motion module
|
|
244
244
|
|
|
245
245
|
### Overview
|
|
246
246
|
Core Motion provides access to hardware sensors: accelerometer, gyroscope, magnetometer, and more.
|
|
247
247
|
|
|
248
|
-
|
|
248
|
+
Requirements:
|
|
249
249
|
- Add module to `tiapp.xml`:
|
|
250
250
|
```xml
|
|
251
251
|
<modules>
|
|
@@ -253,10 +253,10 @@ Core Motion provides access to hardware sensors: accelerometer, gyroscope, magne
|
|
|
253
253
|
</modules>
|
|
254
254
|
```
|
|
255
255
|
|
|
256
|
-
-
|
|
256
|
+
- Can only test on device, not simulator
|
|
257
257
|
- Motion Activity permission required for Activity API
|
|
258
258
|
|
|
259
|
-
### Basic
|
|
259
|
+
### Basic workflow
|
|
260
260
|
|
|
261
261
|
1. Require the module:
|
|
262
262
|
```javascript
|
|
@@ -273,7 +273,7 @@ if (Accelerometer.isAccelerometerAvailable()) {
|
|
|
273
273
|
|
|
274
274
|
3. Start updates:
|
|
275
275
|
```javascript
|
|
276
|
-
Accelerometer.setAccelerometerUpdateInterval(1000);
|
|
276
|
+
Accelerometer.setAccelerometerUpdateInterval(1000); // 1 second
|
|
277
277
|
Accelerometer.startAccelerometerUpdates((e) => {
|
|
278
278
|
if (e.success) {
|
|
279
279
|
const data = e.acceleration;
|
|
@@ -287,11 +287,11 @@ Accelerometer.startAccelerometerUpdates((e) => {
|
|
|
287
287
|
Accelerometer.stopAccelerometerUpdates();
|
|
288
288
|
```
|
|
289
289
|
|
|
290
|
-
### Coordinate
|
|
290
|
+
### Coordinate system
|
|
291
291
|
Hold device in portrait mode, screen facing you:
|
|
292
|
-
-
|
|
293
|
-
-
|
|
294
|
-
-
|
|
292
|
+
- X-axis: width (positive = right, negative = left)
|
|
293
|
+
- Y-axis: height (positive = up, negative = down)
|
|
294
|
+
- Z-axis: through screen (positive = toward screen, negative = behind)
|
|
295
295
|
|
|
296
296
|
### Accelerometer
|
|
297
297
|
|
|
@@ -312,7 +312,7 @@ if (Accelerometer.isAccelerometerAvailable()) {
|
|
|
312
312
|
}
|
|
313
313
|
```
|
|
314
314
|
|
|
315
|
-
|
|
315
|
+
Use for: shake detection, device orientation, movement detection.
|
|
316
316
|
|
|
317
317
|
### Gyroscope
|
|
318
318
|
|
|
@@ -332,11 +332,11 @@ if (Gyroscope.isGyroAvailable()) {
|
|
|
332
332
|
}
|
|
333
333
|
```
|
|
334
334
|
|
|
335
|
-
|
|
335
|
+
Use for: rotation gestures, 3D motion tracking, enhanced UI.
|
|
336
336
|
|
|
337
337
|
### Magnetometer
|
|
338
338
|
|
|
339
|
-
Measures magnetic field strength (microteslas). Acts as digital compass.
|
|
339
|
+
Measures magnetic field strength (microteslas). Acts as a digital compass.
|
|
340
340
|
|
|
341
341
|
```javascript
|
|
342
342
|
var Magnetometer = CoreMotion.createMagnetometer();
|
|
@@ -349,11 +349,11 @@ if (Magnetometer.isMagnetometerAvailable()) {
|
|
|
349
349
|
}
|
|
350
350
|
```
|
|
351
351
|
|
|
352
|
-
|
|
352
|
+
Use for: compass direction, magnetic field detection.
|
|
353
353
|
|
|
354
|
-
### Device
|
|
354
|
+
### Device motion
|
|
355
355
|
|
|
356
|
-
Combines accelerometer, gyroscope, magnetometer for attitude and user acceleration.
|
|
356
|
+
Combines accelerometer, gyroscope, and magnetometer for attitude and user acceleration.
|
|
357
357
|
|
|
358
358
|
```javascript
|
|
359
359
|
var DeviceMotion = CoreMotion.createDeviceMotion();
|
|
@@ -383,16 +383,16 @@ if (DeviceMotion.isDeviceMotionAvailable()) {
|
|
|
383
383
|
}
|
|
384
384
|
```
|
|
385
385
|
|
|
386
|
-
|
|
386
|
+
Attitude formats:
|
|
387
387
|
- Pitch/Roll/Yaw (Euler angles)
|
|
388
388
|
- Quaternion (w, x, y, z)
|
|
389
389
|
- Rotation Matrix (m11-m33)
|
|
390
390
|
|
|
391
|
-
|
|
392
|
-
- `ATTITUDE_REFERENCE_FRAME_X_ARBITRARY_Z_VERTICAL` -
|
|
393
|
-
- `ATTITUDE_REFERENCE_FRAME_X_ARBITRARY_CORRECTED_Z_VERTICAL` -
|
|
394
|
-
- `ATTITUDE_REFERENCE_FRAME_X_MAGNETIC_NORTH_Z_VERTICAL` -
|
|
395
|
-
- `ATTITUDE_REFERENCE_FRAME_X_TRUE_NORTH_Z_VERTICAL` -
|
|
391
|
+
Reference frames:
|
|
392
|
+
- `ATTITUDE_REFERENCE_FRAME_X_ARBITRARY_Z_VERTICAL` - default
|
|
393
|
+
- `ATTITUDE_REFERENCE_FRAME_X_ARBITRARY_CORRECTED_Z_VERTICAL` - uses magnetometer for yaw
|
|
394
|
+
- `ATTITUDE_REFERENCE_FRAME_X_MAGNETIC_NORTH_Z_VERTICAL` - magnetic north
|
|
395
|
+
- `ATTITUDE_REFERENCE_FRAME_X_TRUE_NORTH_Z_VERTICAL` - true north (requires location)
|
|
396
396
|
|
|
397
397
|
### Activity API
|
|
398
398
|
|
|
@@ -417,10 +417,10 @@ MotionActivity.startActivityUpdates((e) => {
|
|
|
417
417
|
});
|
|
418
418
|
```
|
|
419
419
|
|
|
420
|
-
|
|
420
|
+
Query historical activity:
|
|
421
421
|
```javascript
|
|
422
422
|
var endDate = new Date();
|
|
423
|
-
var startDate = new Date(endDate.getTime() - 60 * 60 * 1000);
|
|
423
|
+
var startDate = new Date(endDate.getTime() - 60 * 60 * 1000); // 1 hour ago
|
|
424
424
|
|
|
425
425
|
MotionActivity.queryActivity({
|
|
426
426
|
start: startDate,
|
|
@@ -431,7 +431,7 @@ MotionActivity.queryActivity({
|
|
|
431
431
|
});
|
|
432
432
|
```
|
|
433
433
|
|
|
434
|
-
|
|
434
|
+
Requires Motion Activity permission in `tiapp.xml`:
|
|
435
435
|
```xml
|
|
436
436
|
<key>NSMotionUsageDescription</key>
|
|
437
437
|
<string>Need motion data for fitness tracking</string>
|
|
@@ -445,7 +445,7 @@ const Pedometer = CoreMotion.createPedometer();
|
|
|
445
445
|
if (Pedometer.isStepCountingAvailable()) {
|
|
446
446
|
// Start live updates
|
|
447
447
|
Pedometer.startPedometerUpdates({
|
|
448
|
-
start: new Date(new Date().getTime() - (60 * 60 * 1000))
|
|
448
|
+
start: new Date(new Date().getTime() - (60 * 60 * 1000)) // From 1 hour ago
|
|
449
449
|
}, (e) => {
|
|
450
450
|
Ti.API.info(`Steps: ${e.numberOfSteps}`);
|
|
451
451
|
Ti.API.info(`Distance: ${e.distance} meters`);
|
|
@@ -456,7 +456,7 @@ if (Pedometer.isStepCountingAvailable()) {
|
|
|
456
456
|
|
|
457
457
|
// Query historical data
|
|
458
458
|
var endDate = new Date();
|
|
459
|
-
var startDate = new Date(endDate.getTime() - 24 * 60 * 60 * 1000);
|
|
459
|
+
var startDate = new Date(endDate.getTime() - 24 * 60 * 60 * 1000); // 24 hours ago
|
|
460
460
|
|
|
461
461
|
Pedometer.queryPedometerData({
|
|
462
462
|
start: startDate,
|
|
@@ -466,17 +466,17 @@ Pedometer.queryPedometerData({
|
|
|
466
466
|
});
|
|
467
467
|
```
|
|
468
468
|
|
|
469
|
-
|
|
469
|
+
Use for: fitness apps, step challenges, activity tracking.
|
|
470
470
|
|
|
471
|
-
### Core Motion
|
|
471
|
+
### Core Motion best practices
|
|
472
472
|
|
|
473
|
-
1.
|
|
474
|
-
2.
|
|
475
|
-
3.
|
|
476
|
-
4.
|
|
477
|
-
5.
|
|
473
|
+
1. Always check availability; not all devices have all sensors.
|
|
474
|
+
2. Set appropriate update intervals; high frequency means more CPU/battery.
|
|
475
|
+
3. Stop updates when not needed to conserve battery.
|
|
476
|
+
4. Handle errors gracefully; sensors can fail or be unavailable.
|
|
477
|
+
5. Test on physical devices; sensors do not work in simulator.
|
|
478
478
|
|
|
479
|
-
## 8. Handoff
|
|
479
|
+
## 8. Handoff user activities
|
|
480
480
|
|
|
481
481
|
```javascript
|
|
482
482
|
const UserActivity = Ti.App.iOS.createUserActivity({
|
|
@@ -486,14 +486,14 @@ const UserActivity = Ti.App.iOS.createUserActivity({
|
|
|
486
486
|
articleId: '123',
|
|
487
487
|
scrollPosition: 450
|
|
488
488
|
},
|
|
489
|
-
webpageURL: 'https://myapp.com/articles/123'
|
|
489
|
+
webpageURL: 'https://myapp.com/articles/123' // For web fallback
|
|
490
490
|
});
|
|
491
491
|
|
|
492
492
|
// Mark as current activity
|
|
493
493
|
UserActivity.becomeCurrent();
|
|
494
494
|
```
|
|
495
495
|
|
|
496
|
-
### Handling
|
|
496
|
+
### Handling incoming Handoff
|
|
497
497
|
|
|
498
498
|
```javascript
|
|
499
499
|
Ti.App.iOS.addEventListener('continueactivity', function(e) {
|
|
@@ -508,14 +508,14 @@ Ti.App.iOS.addEventListener('continueactivity', function(e) {
|
|
|
508
508
|
});
|
|
509
509
|
```
|
|
510
510
|
|
|
511
|
-
### Invalidating
|
|
511
|
+
### Invalidating activities
|
|
512
512
|
|
|
513
513
|
```javascript
|
|
514
514
|
// When user closes article
|
|
515
515
|
UserActivity.invalidate();
|
|
516
516
|
```
|
|
517
517
|
|
|
518
|
-
### Declaring
|
|
518
|
+
### Declaring activity types in tiapp.xml
|
|
519
519
|
|
|
520
520
|
```xml
|
|
521
521
|
<key>NSUserActivityTypes</key>
|
|
@@ -532,7 +532,7 @@ UserActivity.invalidate();
|
|
|
532
532
|
- Both devices must be on the same Wi-Fi network
|
|
533
533
|
- Test with Safari first to verify Handoff works between your devices
|
|
534
534
|
|
|
535
|
-
## 9. Additional iOS
|
|
535
|
+
## 9. Additional iOS features
|
|
536
536
|
|
|
537
537
|
### 3D Touch (Force Touch)
|
|
538
538
|
|
|
@@ -551,7 +551,7 @@ if (Ti.Platform.forceTouchSupported) {
|
|
|
551
551
|
}
|
|
552
552
|
```
|
|
553
553
|
|
|
554
|
-
### Haptic
|
|
554
|
+
### Haptic feedback
|
|
555
555
|
|
|
556
556
|
```javascript
|
|
557
557
|
// Generate haptic feedback
|
|
@@ -567,7 +567,7 @@ generator.selectionChanged();
|
|
|
567
567
|
generator.notificationOccurred(Ti.UI.iOS.HAPTIC_FEEDBACK_TYPE_SUCCESS);
|
|
568
568
|
```
|
|
569
569
|
|
|
570
|
-
### Document
|
|
570
|
+
### Document interaction
|
|
571
571
|
|
|
572
572
|
Open documents in other apps:
|
|
573
573
|
|
|
@@ -583,13 +583,13 @@ docController.addEventListener('complete', function(e) {
|
|
|
583
583
|
win.add(docController);
|
|
584
584
|
```
|
|
585
585
|
|
|
586
|
-
## Best
|
|
586
|
+
## Best practices summary
|
|
587
587
|
|
|
588
|
-
1.
|
|
589
|
-
2.
|
|
590
|
-
3.
|
|
591
|
-
4.
|
|
592
|
-
5.
|
|
593
|
-
6.
|
|
594
|
-
7.
|
|
595
|
-
8.
|
|
588
|
+
1. Background services: use sparingly; stop when done.
|
|
589
|
+
2. Core Motion: check availability and test on device.
|
|
590
|
+
3. Spotlight: index content as it changes.
|
|
591
|
+
4. Handoff: provide a web URL fallback.
|
|
592
|
+
5. iCloud: use for small synced data, not large files.
|
|
593
|
+
6. SiriKit: requires native extension; use only if beneficial.
|
|
594
|
+
7. Permissions: always include usage descriptions in `tiapp.xml`.
|
|
595
|
+
8. Testing: many features require physical device testing.
|