@maccesar/titools 3.2.0 → 4.0.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 (102) hide show
  1. package/README.md +27 -61
  2. package/lib/cleanup.js +29 -0
  3. package/lib/commands/agents.js +8 -7
  4. package/lib/commands/skills.js +118 -23
  5. package/lib/config.js +13 -15
  6. package/lib/installer.js +5 -3
  7. package/lib/utils.js +36 -0
  8. package/package.json +1 -1
  9. package/skills/alloy-guides/SKILL.md +188 -0
  10. package/skills/alloy-guides/references/CLI_TASKS.md +233 -0
  11. package/skills/alloy-guides/references/CONCEPTS.md +171 -0
  12. package/skills/alloy-guides/references/CONTROLLERS.md +279 -0
  13. package/skills/alloy-guides/references/MODELS.md +742 -0
  14. package/skills/alloy-guides/references/MODELS_ADVANCED.md +482 -0
  15. package/skills/alloy-guides/references/PURGETSS.md +57 -0
  16. package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +235 -0
  17. package/skills/alloy-guides/references/VIEWS_STYLES.md +375 -0
  18. package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +102 -0
  19. package/skills/alloy-guides/references/VIEWS_XML.md +581 -0
  20. package/skills/alloy-guides/references/WIDGETS.md +160 -0
  21. package/skills/alloy-howtos/SKILL.md +179 -0
  22. package/skills/alloy-howtos/references/best_practices.md +121 -0
  23. package/skills/alloy-howtos/references/cli_reference.md +230 -0
  24. package/skills/alloy-howtos/references/config_files.md +158 -0
  25. package/skills/alloy-howtos/references/custom_tags.md +148 -0
  26. package/skills/alloy-howtos/references/debugging_troubleshooting.md +78 -0
  27. package/skills/alloy-howtos/references/samples.md +156 -0
  28. package/skills/purgetss/SKILL.md +184 -181
  29. package/skills/purgetss/references/EXAMPLES.md +8 -6
  30. package/skills/purgetss/references/app-branding.md +5 -0
  31. package/skills/purgetss/references/apply-directive.md +1 -1
  32. package/skills/purgetss/references/class-categories.md +1 -1
  33. package/skills/purgetss/references/class-index-properties.md +618 -0
  34. package/skills/purgetss/references/class-index.md +4 -610
  35. package/skills/purgetss/references/cli-commands.md +41 -410
  36. package/skills/purgetss/references/custom-fonts.md +292 -0
  37. package/skills/purgetss/references/custom-rules.md +1 -1
  38. package/skills/purgetss/references/customization-deep-dive.md +64 -1
  39. package/skills/purgetss/references/icon-fonts.md +208 -118
  40. package/skills/purgetss/references/installation-setup.md +4 -4
  41. package/skills/purgetss/references/migration-guide.md +53 -1
  42. package/skills/purgetss/references/multi-density-images.md +53 -2
  43. package/skills/purgetss/references/svg-pipeline.md +249 -0
  44. package/skills/purgetss/references/tikit-components.md +2 -2
  45. package/skills/purgetss/references/titanium-resets.md +2 -2
  46. package/skills/purgetss/references/ui-ux-design.md +7 -5
  47. package/skills/purgetss/references/version-history.md +71 -82
  48. package/skills/ti-api/SKILL.md +128 -0
  49. package/skills/ti-api/references/api-android.md +675 -0
  50. package/skills/ti-api/references/api-app-platform.md +636 -0
  51. package/skills/ti-api/references/api-core.md +764 -0
  52. package/skills/ti-api/references/api-data-network.md +641 -0
  53. package/skills/ti-api/references/api-media.md +655 -0
  54. package/skills/ti-api/references/api-modules-ble-bluetooth.md +657 -0
  55. package/skills/ti-api/references/api-modules-coremotion-urlsession.md +411 -0
  56. package/skills/ti-api/references/api-modules-map.md +632 -0
  57. package/skills/ti-api/references/api-modules-nfc.md +725 -0
  58. package/skills/ti-api/references/api-modules-social-misc.md +526 -0
  59. package/skills/ti-api/references/api-services.md +700 -0
  60. package/skills/ti-api/references/api-ui-android.md +499 -0
  61. package/skills/ti-api/references/api-ui-extras.md +702 -0
  62. package/skills/ti-api/references/api-ui-ios-animator.md +378 -0
  63. package/skills/ti-api/references/api-ui-ios.md +756 -0
  64. package/skills/ti-api/references/api-ui-lists.md +581 -0
  65. package/skills/ti-api/references/api-ui-text-input.md +607 -0
  66. package/skills/ti-api/references/api-ui-views.md +572 -0
  67. package/skills/ti-api/references/api-ui-windows-navigation.md +676 -0
  68. package/skills/ti-api/references/api-xml-global.md +743 -0
  69. package/skills/ti-guides/SKILL.md +82 -0
  70. package/skills/ti-guides/references/advanced-data-and-images.md +155 -0
  71. package/skills/ti-guides/references/android-manifest.md +97 -0
  72. package/skills/ti-guides/references/app-distribution.md +373 -0
  73. package/skills/ti-guides/references/application-frameworks.md +366 -0
  74. package/skills/ti-guides/references/cli-reference.md +700 -0
  75. package/skills/ti-guides/references/coding-best-practices.md +150 -0
  76. package/skills/ti-guides/references/commonjs-advanced.md +279 -0
  77. package/skills/ti-guides/references/hello-world.md +99 -0
  78. package/skills/ti-guides/references/hyperloop-native-access.md +458 -0
  79. package/skills/ti-guides/references/javascript-primer.md +402 -0
  80. package/skills/ti-guides/references/reserved-words.md +36 -0
  81. package/skills/ti-guides/references/resources.md +172 -0
  82. package/skills/ti-guides/references/style-and-conventions.md +104 -0
  83. package/skills/ti-guides/references/tiapp-config.md +655 -0
  84. package/skills/ti-howtos/SKILL.md +131 -0
  85. package/skills/ti-howtos/references/android-platform-deep-dives.md +609 -0
  86. package/skills/ti-howtos/references/automation-fastlane-appium.md +96 -0
  87. package/skills/ti-howtos/references/buffer-codec-streams.md +162 -0
  88. package/skills/ti-howtos/references/cross-platform-development.md +358 -0
  89. package/skills/ti-howtos/references/debugging-profiling.md +473 -0
  90. package/skills/ti-howtos/references/extending-titanium.md +684 -0
  91. package/skills/ti-howtos/references/google-maps-v2.md +172 -0
  92. package/skills/ti-howtos/references/ios-map-kit.md +149 -0
  93. package/skills/ti-howtos/references/ios-platform-deep-dives.md +595 -0
  94. package/skills/ti-howtos/references/local-data-sources.md +310 -0
  95. package/skills/ti-howtos/references/location-and-maps.md +267 -0
  96. package/skills/ti-howtos/references/media-apis.md +268 -0
  97. package/skills/ti-howtos/references/notification-services.md +539 -0
  98. package/skills/ti-howtos/references/remote-data-sources.md +339 -0
  99. package/skills/ti-howtos/references/tutorials.md +552 -0
  100. package/skills/ti-howtos/references/using-modules.md +182 -0
  101. package/skills/ti-howtos/references/web-content-integration.md +288 -0
  102. package/skills/ti-howtos/references/webpack-build-pipeline.md +125 -0
@@ -0,0 +1,684 @@
1
+ # Extending Titanium
2
+
3
+ ## 1. Module architecture (core concepts)
4
+
5
+ Titanium modules are based on a native class hierarchy that communicates with JavaScript:
6
+
7
+ - Proxy: base class that binds native code with JS and maintains object state
8
+ - Module: special Proxy that defines a namespace (for example, `Ti.UI`). Only one per project is allowed.
9
+ - ViewProxy: Proxy specialized in rendering views; manages the native view lifecycle
10
+ - View: the actual visual representation (for example, a `UIButton` or an Android `UIView`)
11
+
12
+ ### Proxy-view relationship
13
+ The `ViewProxy` keeps properties in JS even if the native view does not exist yet. When the view is added to the hierarchy, the Proxy creates the native `View` and applies all accumulated properties.
14
+
15
+ ### Threading considerations
16
+ - JavaScript in Titanium is single-threaded. All JS callbacks run on the JS runtime thread.
17
+ - Native modules can use background threads for heavy work, but UI operations must happen on the main/UI thread.
18
+ - On iOS, each Window with a `url` property gets its own JS context and thread. Avoid this pattern.
19
+ - Use `@Kroll.method(runOnUiThread=true)` (Android) to ensure a method runs on the UI thread.
20
+
21
+ ### Key Android Kroll annotations
22
+ - `@Kroll.method` - expose a Java method to JavaScript
23
+ - `@Kroll.getProperty` / `@Kroll.setProperty` - expose getter/setter properties
24
+ - `@Kroll.onAppCreate` - annotate a static method to run when the app process starts
25
+ - `propertyAccessors` in `@Kroll.proxy` - auto-generate getter/setter methods
26
+
27
+ ## 2. Module debugging in Xcode (iOS)
28
+
29
+ You can debug a native module directly within a Titanium project:
30
+
31
+ 1. Open the generated Xcode project at `build/iphone/<App>.xcodeproj`.
32
+ 2. Drag the module project (`.xcodeproj`) into the app project in Xcode.
33
+ 3. In the app, go to Build Phases → Dependencies and add the module.
34
+ 4. In Link Binary With Libraries, add the module's `.a` library or framework.
35
+ 5. Set a breakpoint in your native code and launch the app from Xcode.
36
+
37
+ ## 3. Upgrading to SDK 9.0.0+ (Android)
38
+
39
+ Titanium 9.0.0 introduced major Android changes:
40
+
41
+ - AndroidX: legacy support libraries are no longer supported. Migrate Java/Kotlin code to AndroidX.
42
+ - Gradle: modules now use Gradle for dependencies. Create `android/build.gradle` instead of copying `.jar` files into `lib/`.
43
+ - Architectures: include `arm64-v8a` and `x86_64` in the manifest.
44
+
45
+ Example module `build.gradle`:
46
+ ```gradle
47
+ dependencies {
48
+ implementation 'com.google.android.material:material:1.1.0'
49
+ }
50
+ ```
51
+
52
+ ## 4. Hyperloop
53
+
54
+ ### What is Hyperloop?
55
+
56
+ Hyperloop provides direct JavaScript access to native iOS and Android APIs without writing wrapper code. You can call native methods, create native objects, and interact with platform frameworks directly.
57
+
58
+ ### Prerequisites
59
+
60
+ For iOS:
61
+ - Requires `ti.hyperloop` module in `tiapp.xml`
62
+ - Only works with Classic Titanium projects (not Alloy initially, now supported)
63
+ - iOS 7+ deployment target
64
+
65
+ For Android:
66
+ - Requires `ti.hyperloop` module in `tiapp.xml`
67
+ - Android 4.0+ (API level 14+)
68
+
69
+ Enable in `tiapp.xml`:
70
+ ```xml
71
+ <modules>
72
+ <module platform="iphone">ti.hyperloop</module>
73
+ <module platform="android">ti.hyperloop</module>
74
+ </modules>
75
+ ```
76
+
77
+ ### Hyperloop basics
78
+
79
+ Pattern for accessing native APIs:
80
+ ```javascript
81
+ const NativeClass = require('path.to.NativeClass');
82
+ const instance = new NativeClass();
83
+ instance.methodName();
84
+ ```
85
+
86
+ ### iOS Hyperloop examples
87
+
88
+ #### Access iOS frameworks
89
+
90
+ ```javascript
91
+ // Access Foundation framework
92
+ const NSString = require('Foundation/NSString');
93
+ const NSMutableString = require('Foundation/NSMutableString');
94
+
95
+ // Create string
96
+ const str = NSString.stringWithString('Hello from Hyperloop');
97
+ Ti.API.info(`Length: ${str.length()}`);
98
+
99
+ // Mutable string
100
+ const mutable = NSMutableString.alloc().initWithString('Hello');
101
+ mutable.appendString(' Hyperloop');
102
+ Ti.API.info(mutable); // "Hello Hyperloop"
103
+ ```
104
+
105
+ #### Access UIKit
106
+
107
+ ```javascript
108
+ const UIViewController = require('UIKit/UIViewController');
109
+ const UIColor = require('UIKit/UIColor');
110
+
111
+ // Create native view controller
112
+ const controller = UIViewController.alloc().init();
113
+
114
+ // Set background color
115
+ controller.view().setBackgroundColor(
116
+ UIColor.redColor()
117
+ );
118
+ ```
119
+
120
+ #### Make native HTTP request
121
+
122
+ ```javascript
123
+ const NSURL = require('Foundation/NSURL');
124
+ const NSURLRequest = require('Foundation/NSURLRequest');
125
+ const NSURLSession = require('Foundation/NSURLSession');
126
+
127
+ const url = NSURL.URLWithString('https://api.example.com/data');
128
+ const request = NSURLRequest.requestWithURL(url);
129
+
130
+ const session = NSURLSession.sharedSession();
131
+ const task = session.dataTaskWithRequestCompletionHandler(request, (data, response, error) => {
132
+ if (!error) {
133
+ Ti.API.info('Response received');
134
+ // Process data
135
+ }
136
+ });
137
+
138
+ task.resume();
139
+ ```
140
+
141
+ #### Access CoreBluetooth (Bluetooth LE)
142
+
143
+ ```javascript
144
+ var CBCentralManager = require('CoreBluetooth/CBCentralManager');
145
+
146
+ var central = CBCentralManager.alloc().initWithDelegateQueueOptions(
147
+ null, // delegate
148
+ null // queue
149
+ );
150
+
151
+ // Check Bluetooth state
152
+ var state = central.state();
153
+ if (state === 5) { // CBCentralManagerStatePoweredOn
154
+ // Start scanning
155
+ central.scanForPeripheralsWithServicesOptions(null, null);
156
+ }
157
+ ```
158
+
159
+ #### Access AVFoundation (camera/video)
160
+
161
+ ```javascript
162
+ var AVCaptureDevice = require('AVFoundation/AVCaptureDevice');
163
+
164
+ // Get back camera
165
+ var devices = AVCaptureDevice.devicesWithMediaType('vide');
166
+ var backCamera = null;
167
+
168
+ for (var i = 0; i < devices.count(); i++) {
169
+ var device = devices.objectAtIndex(i);
170
+ if (device.position() === 1) { // AVCaptureDevicePositionBack
171
+ backCamera = device;
172
+ break;
173
+ }
174
+ }
175
+
176
+ // Configure camera
177
+ if (backCamera) {
178
+ backCamera.lockForConfiguration(null);
179
+ backCamera.setFlashMode(1); // AVCaptureFlashModeOn
180
+ backCamera.unlockForConfiguration();
181
+ }
182
+ ```
183
+
184
+ #### Access Address Book (contacts)
185
+
186
+ ```javascript
187
+ var ABAddressBook = require('AddressBook/ABAddressBook');
188
+
189
+ var addressBook = ABAddressBook.create();
190
+ var people = addressBook.people();
191
+
192
+ for (var i = 0; i < people.count(); i++) {
193
+ var person = people.objectAtIndex(i);
194
+ var firstName = person.valueForProperty(0); // kABPersonFirstNameProperty
195
+ Ti.API.info('Contact: ' + firstName);
196
+ }
197
+ ```
198
+
199
+ #### Access CoreLocation (enhanced)
200
+
201
+ ```javascript
202
+ var CLLocationManager = require('CoreLocation/CLLocationManager');
203
+ var CLLocation = require('CoreLocation/CLLocation');
204
+
205
+ var locationManager = CLLocationManager.alloc().init();
206
+ locationManager.setDelegate(null);
207
+ locationManager.setDesiredAccuracy(3); // kCLLocationAccuracyBest
208
+ locationManager.startUpdatingLocation();
209
+ ```
210
+
211
+ ### Android Hyperloop examples
212
+
213
+ #### Access Android frameworks
214
+
215
+ ```javascript
216
+ const Context = require('android.content.Context');
217
+ const Activity = require('android.app.Activity');
218
+ const Toast = require('android.widget.Toast');
219
+
220
+ // Get current activity
221
+ const activity = Ti.Android.currentActivity;
222
+
223
+ // Show toast
224
+ Toast.makeText(
225
+ activity,
226
+ 'Hello from Hyperloop',
227
+ Toast.LENGTH_SHORT
228
+ ).show();
229
+ ```
230
+
231
+ #### Access vibrator
232
+
233
+ ```javascript
234
+ const Vibrator = require('android.os.Vibrator');
235
+ const Context = require('android.content.Context');
236
+
237
+ const activity = Ti.Android.currentActivity;
238
+ const vibrator = activity.getSystemService(Context.VIBRATOR_SERVICE);
239
+
240
+ // Vibrate for 500ms
241
+ vibrator.vibrate(500);
242
+ ```
243
+
244
+ #### Access TelephonyManager
245
+
246
+ ```javascript
247
+ const TelephonyManager = require('android.telephony.TelephonyManager');
248
+ const Context = require('android.content.Context');
249
+
250
+ const activity = Ti.Android.currentActivity;
251
+ const tm = activity.getSystemService(Context.TELEPHONY_SERVICE);
252
+
253
+ // Get device ID
254
+ const deviceId = tm.getDeviceId();
255
+ Ti.API.info(`Device ID: ${deviceId}`);
256
+
257
+ // Get phone state
258
+ const state = tm.getCallState();
259
+ if (state === 0) {
260
+ Ti.API.info('Phone idle');
261
+ } else if (state === 1) {
262
+ Ti.API.info('Phone ringing');
263
+ } else if (state === 2) {
264
+ Ti.API.info('Phone offhook');
265
+ }
266
+ ```
267
+
268
+ #### Access WiFi Manager
269
+
270
+ ```javascript
271
+ const WifiManager = require('android.net.wifi.WifiManager');
272
+ const Context = require('android.content.Context');
273
+
274
+ const activity = Ti.Android.currentActivity;
275
+ const wifi = activity.getSystemService(Context.WIFI_SERVICE);
276
+
277
+ // Check WiFi enabled
278
+ if (wifi.isWifiEnabled()) {
279
+ // Get connection info
280
+ const info = wifi.getConnectionInfo();
281
+ const ssid = info.getSSID();
282
+ const speed = info.getLinkSpeed();
283
+ Ti.API.info(`Connected to: ${ssid} at ${speed} Mbps`);
284
+ }
285
+ ```
286
+
287
+ #### Access PackageManager
288
+
289
+ ```javascript
290
+ const PackageManager = require('android.content.pm.PackageManager');
291
+
292
+ const activity = Ti.Android.currentActivity;
293
+ const pm = activity.getPackageManager();
294
+
295
+ // Get installed apps
296
+ const packages = pm.getInstalledApplications(0);
297
+ for (let i = 0; i < packages.size(); i++) {
298
+ const pkg = packages.get(i);
299
+ const appName = pm.getApplicationLabel(pkg);
300
+ Ti.API.info(`App: ${appName}`);
301
+ }
302
+ ```
303
+
304
+ ### Hyperloop best practices
305
+
306
+ 1. Check platform availability. Use `Ti.Platform.osname` to branch code.
307
+ 2. Handle errors. Native calls can throw exceptions.
308
+ 3. Memory management: be aware of native object lifecycles.
309
+ 4. Test thoroughly. Native APIs have platform-specific behaviors.
310
+ 5. Document requirements. Note platform versions and permissions needed.
311
+ 6. Use try/catch. Wrap native calls for safety.
312
+
313
+ ```javascript
314
+ try {
315
+ const NativeClass = require('path.to.NativeClass');
316
+ const instance = new NativeClass();
317
+ // Use instance
318
+ } catch (e) {
319
+ Ti.API.error(`Hyperloop error: ${e.message}`);
320
+ }
321
+ ```
322
+
323
+ ## 3. Native module development
324
+
325
+ ### When to create native modules
326
+
327
+ Create a native module when you need to:
328
+ - Reuse native code across multiple Titanium apps
329
+ - Distribute functionality to other developers
330
+ - Implement complex native functionality not suitable for Hyperloop
331
+ - Maintain a stable API regardless of native SDK changes
332
+
333
+ ### Android module development
334
+
335
+ #### Quick start
336
+
337
+ 1. Create module structure:
338
+ ```
339
+ com.example.mymodule/
340
+ ├── src/
341
+ │ └── com/
342
+ │ └── example/
343
+ │ └── mymodule/
344
+ │ ├── ExampleModule.java
345
+ │ └── ExampleProxy.java
346
+ ├── build.properties
347
+ ├── build.xml
348
+ ├── timodule.xml
349
+ └── LICENSE
350
+ ```
351
+
352
+ 2. Module Java class:
353
+
354
+ ```java
355
+ package com.example.mymodule;
356
+
357
+ import org.appcelerator.kroll.KrollModule;
358
+ import org.appcelerator.kroll.annotations.KrollModule;
359
+
360
+ @KrollModule(name="MyModule", id="com.example.mymodule")
361
+ public class ExampleModule extends KrollModule {
362
+
363
+ public ExampleModule() {
364
+ super();
365
+ }
366
+
367
+ @Kroll.method
368
+ public String helloWorld() {
369
+ return "Hello from native module!";
370
+ }
371
+
372
+ @Kroll.method
373
+ public int add(int a, int b) {
374
+ return a + b;
375
+ }
376
+
377
+ @Kroll.getProperty
378
+ public String getVersion() {
379
+ return "1.0.0";
380
+ }
381
+ }
382
+ ```
383
+
384
+ 3. `timodule.xml`:
385
+ ```xml
386
+ <module>
387
+ <description>My Example Module</description>
388
+ <version>1.0.0</version>
389
+ <platform>android</platform>
390
+ <min-sdk>3.0.0.GA</min-sdk>
391
+ </module>
392
+ ```
393
+
394
+ 4. Build and package:
395
+ ```bash
396
+ ant clean
397
+ ant package
398
+ ```
399
+
400
+ #### Use in Titanium app
401
+
402
+ ```javascript
403
+ const myModule = require('com.example.mymodule');
404
+ Ti.API.info(myModule.helloWorld()); // "Hello from native module!"
405
+ Ti.API.info(myModule.add(5, 3)); // 8
406
+ Ti.API.info(myModule.version); // "1.0.0"
407
+ ```
408
+
409
+ #### Common Android module patterns
410
+
411
+ Accessing Android APIs:
412
+
413
+ ```java
414
+ import android.content.Context;
415
+ import android.location.LocationManager;
416
+
417
+ @Kroll.method
418
+ public boolean isGPSEnabled() {
419
+ LocationManager lm = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
420
+ return lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
421
+ }
422
+ ```
423
+
424
+ Firing events to JavaScript:
425
+
426
+ ```java
427
+ import org.appcelerator.kroll.KrollDict;
428
+
429
+ @Kroll.method
430
+ public void triggerEvent() {
431
+ KrollDict data = new KrollDict();
432
+ data.put("message", "Hello from native!");
433
+ fireEvent("myEvent", data);
434
+ }
435
+ ```
436
+
437
+ Receiving events from JavaScript:
438
+
439
+ ```java
440
+ @Kroll.method
441
+ public void startService() {
442
+ // Start service and listen for events
443
+ }
444
+ ```
445
+
446
+ ### iOS module development
447
+
448
+ #### Quick start
449
+
450
+ 1. Create module with template:
451
+ ```bash
452
+ # Use Titanium CLI
453
+ titanium create --type module --id com.example.mymodule --name MyModule --platform ios
454
+ ```
455
+
456
+ 2. Module structure:
457
+ ```
458
+ com.example.mymodule/
459
+ ├── Classes/
460
+ │ ├── ComExampleMymoduleModule.h
461
+ │ ├── ComExampleMymoduleModule.m
462
+ │ └── ComExampleMymoduleProxy.h
463
+ ├── documentation/
464
+ │ └── index.md
465
+ ├── assets/
466
+ ├── iphone/
467
+ │ └── MyModule_Prefix.pch
468
+ ├── timodule.xml
469
+ └── LICENSE
470
+ ```
471
+
472
+ 3. Module implementation (`ComExampleMymoduleModule.m`):
473
+
474
+ ```objc
475
+ #import "ComExampleMymoduleModule.h"
476
+
477
+ @implementation ComExampleMymoduleModule
478
+
479
+ #pragma mark Internal
480
+
481
+ - (id)moduleGUID {
482
+ return @"com.example.mymodule";
483
+ }
484
+
485
+ - (NSString *)moduleName {
486
+ return @"MyModule";
487
+ }
488
+
489
+ #pragma mark Lifecycle
490
+
491
+ - (void)startup {
492
+ [super startup];
493
+ DebugLog(@"[DEBUG] MyModule initialized");
494
+ }
495
+
496
+ - (void)shutdown:(id)sender {
497
+ [super shutdown:sender];
498
+ }
499
+
500
+ #pragma mark Cleanup
501
+
502
+ - (void)dealloc {
503
+ [super dealloc];
504
+ }
505
+
506
+ #pragma Public APIs
507
+
508
+ - (NSString*)version {
509
+ return @"1.0.0";
510
+ }
511
+
512
+ - (NSString*)helloWorld {
513
+ return @"Hello from native module!";
514
+ }
515
+
516
+ - (NSNumber*)add:(NSNumber*)a with:(NSNumber*)b {
517
+ return [NSNumber numberWithInt:[a intValue] + [b intValue]];
518
+ }
519
+
520
+ @end
521
+ ```
522
+
523
+ 4. `timodule.xml`:
524
+ ```xml
525
+ <module>
526
+ <description>My Example Module</description>
527
+ <version>1.0.0</version>
528
+ <platform>iphone</platform>
529
+ <min-sdk>3.0.0.GA</min-sdk>
530
+ </module>
531
+ ```
532
+
533
+ 5. Build and package:
534
+ ```bash
535
+ ./build.py
536
+ ```
537
+
538
+ 6. Use in Titanium app:
539
+
540
+ ```javascript
541
+ const myModule = require('com.example.mymodule');
542
+ Ti.API.info(myModule.helloWorld()); // "Hello from native module!"
543
+ Ti.API.info(myModule.add(5, { with: 3 })); // 8
544
+ Ti.API.info(myModule.version); // "1.0.0"
545
+ ```
546
+
547
+ #### Common iOS module patterns
548
+
549
+ Accessing iOS frameworks:
550
+
551
+ ```objc
552
+ #import <CoreLocation/CoreLocation.h>
553
+
554
+ - (void)startTracking {
555
+ CLLocationManager *manager = [[CLLocationManager alloc] init];
556
+ [manager setDelegate:self];
557
+ [manager startUpdatingLocation];
558
+ }
559
+ ```
560
+
561
+ Firing events to JavaScript:
562
+
563
+ ```objc
564
+ - (void)locationUpdated:(CLLocation*)location {
565
+ NSDictionary *event = @{
566
+ @"latitude": [NSNumber numberWithDouble:location.coordinate.latitude],
567
+ @"longitude": [NSNumber numberWithDouble:location.coordinate.longitude]
568
+ };
569
+ [self fireEvent:@"locationUpdate" withObject:event];
570
+ }
571
+ ```
572
+
573
+ View proxies (custom UI components):
574
+
575
+ ```objc
576
+ @interface MyViewProxy : TiViewProxy {
577
+ UIView *myView;
578
+ }
579
+
580
+ - (UIView *)view {
581
+ if (myView == nil) {
582
+ myView = [[MyCustomView alloc] initWithFrame:[self frame]];
583
+ }
584
+ return myView;
585
+ }
586
+
587
+ @end
588
+ ```
589
+
590
+ ### Module distribution
591
+
592
+ #### Packaging
593
+
594
+ Both platforms create a `.zip` file for distribution:
595
+
596
+ ```bash
597
+ # For iOS
598
+ ./build.py -d
599
+
600
+ # For Android
601
+ ant dist
602
+ ```
603
+
604
+ #### Installing module
605
+
606
+ 1. Local installation: extract to `/Library/Application Support/Titanium/modules/`
607
+ 2. Global installation: use `gittio` or `npm` for publishing
608
+ 3. Project-specific: place in the app's `modules/` directory
609
+
610
+ #### Module configuration in tiapp.xml
611
+
612
+ ```xml
613
+ <modules>
614
+ <module platform="android" version="1.0.0">com.example.mymodule</module>
615
+ <module platform="iphone" version="1.0.0">com.example.mymodule</module>
616
+ </modules>
617
+ ```
618
+
619
+ ## 4. Choosing between Hyperloop and native modules
620
+
621
+ ### Use Hyperloop when
622
+
623
+ - Prototyping native API access
624
+ - App-specific native functionality (not reusable)
625
+ - One-off native API calls
626
+ - Quick integration with platform features
627
+ - You do not need to distribute code
628
+
629
+ ### Use native modules when
630
+
631
+ - Creating reusable components
632
+ - Distributing to other developers
633
+ - Complex native logic with state management
634
+ - Need stable API abstraction
635
+ - Performance-critical code paths
636
+ - Custom UI components
637
+
638
+ ## 5. Finding and using third-party modules
639
+
640
+ ### Ti_slack marketplace
641
+
642
+ Search for existing modules at:
643
+ - https://fromzerotoapp.com/modules/
644
+ - https://github.com/search?q=titanium+module
645
+
646
+ ### Popular third-party modules
647
+
648
+ - ti.map - Enhanced mapping (Google Maps, Apple Maps)
649
+ - ti.paint - Drawing/signature capture
650
+ - ti.barcode - Barcode/QR scanning
651
+ - ti.admob - AdMob integration
652
+ - ti.facebook - Facebook SDK
653
+ - ti.googleplus - Google+ SDK
654
+ - ti.oauth2 - OAuth 2.0 client
655
+
656
+ ### Using third-party modules
657
+
658
+ 1. Download module zip
659
+ 2. Extract to modules directory
660
+ 3. Add to `tiapp.xml`:
661
+
662
+ ```xml
663
+ <modules>
664
+ <module platform="android">com.mapbox.map</module>
665
+ <module platform="iphone">com.mapbox.map</module>
666
+ </modules>
667
+ ```
668
+
669
+ 4. Require in code:
670
+
671
+ ```javascript
672
+ const Mapbox = require('com.mapbox.map');
673
+ ```
674
+
675
+ ## Best practices summary
676
+
677
+ 1. Try built-in APIs first; Titanium may already have what you need.
678
+ 2. Prefer Hyperloop for simple cases; less overhead.
679
+ 3. Create modules for reusable code; better distribution.
680
+ 4. Handle platform differences; branch code appropriately.
681
+ 5. Document dependencies; note SDK versions and requirements.
682
+ 6. Test on real devices; simulators may not support all features.
683
+ 7. Version your modules; use semantic versioning for compatibility.
684
+ 8. Provide examples; help users understand usage patterns.