Cydia Substrate Pitfalls: Difference between revisions

From iPhone Development Wiki
(Created page with 'MobileSubstrate Pitfalls 1. Access ivars through their associated property if it exists 2. Always call the old implementation of the method unless you require suppressing the d…')
 
m (I fail at wiki formatting)
Line 1: Line 1:
MobileSubstrate Pitfalls
# Access ivars through their associated property if it exists
 
# Always call the old implementation of the method unless you require suppressing the default behaviour. Similarly, only call the old implementation of a method from within the method hook.
1. Access ivars through their associated property if it exists
# Always include a filter plist; if you require access to only SpringBoard, use "com.apple.springboard"; if you require access to all UIKit apps, use "com.apple.UIKit"
 
# Avoid UIAlertView in SpringBoard--it doesn't participate in the SpringBoard-wide alert system; use a custom SBAlertItem subclass instead (not necessary for cases where you don't care if they system destroys your alert)
2. Always call the old implementation of the method unless you require suppressing the default behaviour. Similarly, only call the old implementation of a method from within the method hook.
# Use documented/public SDK features where possible. Often a public SDK is available in earlier OS versions
 
# Preferences.framework changed drastically between 3.1 and 3.2; buyer beware. Use PreferenceLoader and standard preferences plists for simple panes, PSViewController+UITableView for more complex panes (using PSListController is more difficult than it should be and is subject to many OS changes)
3. Always include a filter plist; if you require access to only SpringBoard, use "com.apple.springboard"; if you require access to all UIKit apps, use "com.apple.UIKit"
# Use autoresizingMask and layoutSubviews to make your extension resolution independent and rotation aware
 
# Don't modify OS or Cydia files; use runtime-replacement instead
4. Avoid UIAlertView in SpringBoard--it doesn't participate in the SpringBoard-wide alert system; use a custom SBAlertItem subclass instead (not necessary for cases where you don't care if they system destroys your alert)
# Avoid doing extra work--the methods your extension hooks may be called from inside a tight loop; disk access is considered a LOT of extra work (related: properties are actually method calls, they can be slow)
 
# UI* methods must be performed on the main thread (this includes UIImage! use CGImageSource and company if you need to load images from a background thread)
5. Use documented/public SDK features where possible. Often a public SDK is available in earlier OS versions
# Never block the main thread! Performing any operation that can take significant time on the main thread is evil (that includes _any_ operation that hits the network)
 
# Access resources through NSBundle that way they can be themed via WinterBoard
6. Preferences.framework changed drastically between 3.1 and 3.2; buyer beware. Use PreferenceLoader and standard preferences plists for simple panes, PSViewController+UITableView for more complex panes (using PSListController is more difficult than it should be and is subject to many OS changes)
# Include the proper Depends: line in your Debian control file (that way Cydia will automatically install dependencies and will alert users when they are missing required components like firmware version)
 
# If your extension exposes an API, document it! Include headers _inside_ your deb package so they're easy to find.
7. Use autoresizingMask and layoutSubviews to make your extension resolution independent and rotation aware
# Ensure your extension is localizable; use the standard .lproj system where possible. Avoid having images that include text.
 
# Make sure your deb package doesn't include hidden .DS_Store, ._*, or thumbs.db files
8. Don't modify OS or Cydia files; use runtime-replacement instead
# Don't assume the ivar layout of classes; they can and will change
 
# Use an established hooking framework (substrate.h, CaptainHook.h or logos); there are too many details that have to be just right
9. Avoid doing extra work--the methods your extension hooks may be called from inside a tight loop; disk access is considered a LOT of extra work (related: properties are actually method calls, they can be slow)
# If accessing low-level graphics hardware, beware that first-generation devices do _not_ have a unified memory model (VRAM and regular RAM are separate regions)
 
# Participate in the memory warning system if your extension has a significant memory footprint; release everything you can
10. UI* methods must be performed on the main thread (this includes UIImage! use CGImageSource and company if you need to load images from a background thread)
# Use mmap when working with large datasets--the kernel will swap it in and out of memory as necessary (but avoid heavy writes, as that's no better than virtual memory)
 
# Never inhibit MobileSubstrate's safe mode (commonly, this occurs with invalid icon layouts--IconSupport to the rescue)
11. Never block the main thread! Performing any operation that can take significant time on the main thread is evil (that includes _any_ operation that hits the network)
# Compile against the earliest possible firmware you can (compile against 3.0, not 3.0.1, 3.1 or 3.1.2); use feature detection if necessary
 
# Respect the users' privacy. The IMEI, cell number, contacts list and email inbox are definitely private information. MAC address, Bluetooth address and UDID may be considered private information depending on the jurisdiction
12. Access resources through NSBundle that way they can be themed via WinterBoard
# Strip symbols if you have something to hide; use standard C (or C++) for the hidden parts--Objective-C will spill your details
 
# Many private frameworks have public headers available for Mac OS X; use them (also, there are header packs floating around--kennytm's is one of the best and is legal to distribute)
13. Include the proper Depends: line in your Debian control file (that way Cydia will automatically install dependencies and will alert users when they are missing required components like firmware version)
# Only link to the frameworks you actually need--importing unnecessary frameworks will increase app launch time (use dlopen/dlsym to load libraries and access symbols at runtime after the app has launched)
 
# Use a private prefix on classes and extension methods: Objective-C has NO namespacing capabilities. (examples: two Preferences classes that behave differently; two extensions define a -[NSData base64String] that behave slightly differently)
14. If your extension exposes an API, document it! Include headers _inside_ your deb package so they're easy to find.
# Store preferences in /var/mobile/Library/Preferences to have iTunes back it up
 
# Store data in /var/mobile/Library/AddressBook or /var/mobile/Library/Keyboard to avoid the sandbox restrictions
15. Ensure your extension is localizable; use the standard .lproj system where possible. Avoid having images that include text.
# Avoid waking the device or keeping the device from sleeping. If your extension needs to do something periodically, hook the Mail applications's sync and integrate the action within that. (scheduler/alarm extensions need not apply)
 
# Avoid CPU/GPU/disk intensive activity where the user would not expect it (battery life!)
16. Make sure your deb package doesn't include hidden .DS_Store, ._*, or thumbs.db files
# Don't overuse NSLog/CFLog/fprintf(stderr, …); they're slow and synchronous
 
# If your extension exposes an icon, include both the 29x29 and 59x60 icon sizes (more for iPad)
17. Don't assume the ivar layout of classes; they can and will change
# Expect others to hook the same methods you do; expect them not to have read this list and to have done crazy things
 
# Prefer hooking methods over hooking functions--new jailbreaks don't always have kernel patches and MobileSubstrate may not support newer ARM instructions
18. Use an established hooking framework (substrate.h, CaptainHook.h or logos); there are too many details that have to be just right
# Avoid changing the class of objects returned by public APIs--some App Store applications perform unnecessary checks against the class of an object and will fail
 
# Prefer binary plists over XML--they're much quicker and don't force an XML parser to load (text plists are also quick, but seem to be deprecated)
19. If accessing low-level graphics hardware, beware that first-generation devices do _not_ have a unified memory model (VRAM and regular RAM are separate regions)
# Manage memory correctly as per the Cocoa memory management guidelines; ensure all hooks comply as well
 
20. Participate in the memory warning system if your extension has a significant memory footprint; release everything you can
 
21. Use mmap to avoid having your entire dataset in memory--the kernel will swap it in and out of memory as necessary (but avoid heavy writes, as that's no better than virtual memory)
 
22. Never inhibit MobileSubstrate's safe mode (commonly, this occurs with invalid icon layouts--IconSupport to the rescue)
 
23. Compile against the earliest possible firmware you can (compile against 3.0, not 3.0.1, 3.1 or 3.1.2); use feature detection if necessary
 
24. Respect the users' privacy. The IMEI, cell number, contacts list and email inbox are definitely private information. MAC address, Bluetooth address and UDID may be considered private information depending on the jurisdiction
 
25. Strip symbols if you have something to hide; use standard C (or C++) for the hidden parts--Objective-C will spill your details
 
26. Many private frameworks have public headers available for Mac OS X; use them (also, there are header packs floating around--kennytm's is one of the best and is legal to distribute)
 
27. Only link to the frameworks you actually need--importing unnecessary frameworks will increase app launch time (use dlopen/dlsym to load libraries and access symbols at runtime after the app has launched)
 
28. Use a private prefix on classes and extension methods: Objective-C has NO namespacing capabilities. (examples: two Preferences classes that behave differently; two extensions define a -[NSData base64String] that behave slightly differently)
 
29. Store preferences in /var/mobile/Library/Preferences to have iTunes back it up
 
30. Store data in /var/mobile/Library/AddressBook or /var/mobile/Library/Keyboard to avoid the sandbox restrictions
 
31. Avoid waking the device or keeping the device from sleeping. If your extension needs to do something periodically, hook the Mail applications's sync and integrate the action within that. (scheduler/alarm extensions need not apply)
 
32. Avoid CPU/GPU/disk intensive activity where the user would not expect it (battery life!)
 
33. Don't overuse NSLog/CFLog/fprintf(stderr, …); they're slow and synchronous
 
34. If your extension exposes an icon, include both the 29x29 and 59x60 icon sizes (more for iPad)
 
35. Expect others to hook the same methods you do; expect them not to have read this list and to have done crazy things
 
36. Prefer hooking methods over hooking functions--new jailbreaks don't always have kernel patches and MobileSubstrate may not support newer ARM instructions
 
37. Avoid changing the class of objects returned by public APIs--some App Store applications perform unnecessary checks against the class of an object and will fail
 
38. Prefer binary plists over XML--they're much quicker and don't force an XML parser to load (text plists are also quick, but seem to be deprecated)
 
39. Manage memory correctly as per the Cocoa memory management guidelines; ensure all hooks comply as well


This list is a work in progress. Please edit as necessary --rpetrich
This list is a work in progress. Please edit as necessary --rpetrich

Revision as of 06:47, 11 May 2010

  1. Access ivars through their associated property if it exists
  2. Always call the old implementation of the method unless you require suppressing the default behaviour. Similarly, only call the old implementation of a method from within the method hook.
  3. Always include a filter plist; if you require access to only SpringBoard, use "com.apple.springboard"; if you require access to all UIKit apps, use "com.apple.UIKit"
  4. Avoid UIAlertView in SpringBoard--it doesn't participate in the SpringBoard-wide alert system; use a custom SBAlertItem subclass instead (not necessary for cases where you don't care if they system destroys your alert)
  5. Use documented/public SDK features where possible. Often a public SDK is available in earlier OS versions
  6. Preferences.framework changed drastically between 3.1 and 3.2; buyer beware. Use PreferenceLoader and standard preferences plists for simple panes, PSViewController+UITableView for more complex panes (using PSListController is more difficult than it should be and is subject to many OS changes)
  7. Use autoresizingMask and layoutSubviews to make your extension resolution independent and rotation aware
  8. Don't modify OS or Cydia files; use runtime-replacement instead
  9. Avoid doing extra work--the methods your extension hooks may be called from inside a tight loop; disk access is considered a LOT of extra work (related: properties are actually method calls, they can be slow)
  10. UI* methods must be performed on the main thread (this includes UIImage! use CGImageSource and company if you need to load images from a background thread)
  11. Never block the main thread! Performing any operation that can take significant time on the main thread is evil (that includes _any_ operation that hits the network)
  12. Access resources through NSBundle that way they can be themed via WinterBoard
  13. Include the proper Depends: line in your Debian control file (that way Cydia will automatically install dependencies and will alert users when they are missing required components like firmware version)
  14. If your extension exposes an API, document it! Include headers _inside_ your deb package so they're easy to find.
  15. Ensure your extension is localizable; use the standard .lproj system where possible. Avoid having images that include text.
  16. Make sure your deb package doesn't include hidden .DS_Store, ._*, or thumbs.db files
  17. Don't assume the ivar layout of classes; they can and will change
  18. Use an established hooking framework (substrate.h, CaptainHook.h or logos); there are too many details that have to be just right
  19. If accessing low-level graphics hardware, beware that first-generation devices do _not_ have a unified memory model (VRAM and regular RAM are separate regions)
  20. Participate in the memory warning system if your extension has a significant memory footprint; release everything you can
  21. Use mmap when working with large datasets--the kernel will swap it in and out of memory as necessary (but avoid heavy writes, as that's no better than virtual memory)
  22. Never inhibit MobileSubstrate's safe mode (commonly, this occurs with invalid icon layouts--IconSupport to the rescue)
  23. Compile against the earliest possible firmware you can (compile against 3.0, not 3.0.1, 3.1 or 3.1.2); use feature detection if necessary
  24. Respect the users' privacy. The IMEI, cell number, contacts list and email inbox are definitely private information. MAC address, Bluetooth address and UDID may be considered private information depending on the jurisdiction
  25. Strip symbols if you have something to hide; use standard C (or C++) for the hidden parts--Objective-C will spill your details
  26. Many private frameworks have public headers available for Mac OS X; use them (also, there are header packs floating around--kennytm's is one of the best and is legal to distribute)
  27. Only link to the frameworks you actually need--importing unnecessary frameworks will increase app launch time (use dlopen/dlsym to load libraries and access symbols at runtime after the app has launched)
  28. Use a private prefix on classes and extension methods: Objective-C has NO namespacing capabilities. (examples: two Preferences classes that behave differently; two extensions define a -[NSData base64String] that behave slightly differently)
  29. Store preferences in /var/mobile/Library/Preferences to have iTunes back it up
  30. Store data in /var/mobile/Library/AddressBook or /var/mobile/Library/Keyboard to avoid the sandbox restrictions
  31. Avoid waking the device or keeping the device from sleeping. If your extension needs to do something periodically, hook the Mail applications's sync and integrate the action within that. (scheduler/alarm extensions need not apply)
  32. Avoid CPU/GPU/disk intensive activity where the user would not expect it (battery life!)
  33. Don't overuse NSLog/CFLog/fprintf(stderr, …); they're slow and synchronous
  34. If your extension exposes an icon, include both the 29x29 and 59x60 icon sizes (more for iPad)
  35. Expect others to hook the same methods you do; expect them not to have read this list and to have done crazy things
  36. Prefer hooking methods over hooking functions--new jailbreaks don't always have kernel patches and MobileSubstrate may not support newer ARM instructions
  37. Avoid changing the class of objects returned by public APIs--some App Store applications perform unnecessary checks against the class of an object and will fail
  38. Prefer binary plists over XML--they're much quicker and don't force an XML parser to load (text plists are also quick, but seem to be deprecated)
  39. Manage memory correctly as per the Cocoa memory management guidelines; ensure all hooks comply as well

This list is a work in progress. Please edit as necessary --rpetrich