-
Notifications
You must be signed in to change notification settings - Fork 57
feat(springboard): add get_icon_state and set_icon_state methods with iOS 18+ support #63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(springboard): add get_icon_state and set_icon_state methods with iOS 18+ support #63
Conversation
…layout Add get_icon_state() method to SpringBoardServicesClient that retrieves the current home screen icon layout from iOS devices. Features: - Read complete home screen layout including icon positions and folders - Support for optional formatVersion parameter - Works on all iOS versions (tested on iOS 18.7.3) - Comprehensive documentation with usage examples Note: This PR intentionally does NOT include set_icon_state() as that functionality is non-operational on iOS 18+ (see issue jkcoxson#62 for details). Tested on: - Device: iPhone 16,2 (iPhone 15 Pro) - iOS: 18.7.3 (Build 22H217)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds the get_icon_state() method to the SpringBoardServicesClient to retrieve the iOS home screen layout. The implementation enables read-only access to home screen icon arrangements, folder structures, and icon positions. The PR intentionally excludes the corresponding set_icon_state() method due to it being non-functional on iOS 18+.
Changes:
- Added
get_icon_state(format_version: Option<String>)method for reading home screen layout - Reformatted import statement (ordering change)
- Comprehensive documentation including usage example and iOS 18+ limitations note
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } | ||
|
|
||
| self.idevice.send_plist(req).await?; | ||
| let res = self.idevice.read_plist_value().await?; |
Copilot
AI
Jan 21, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The response from the device is not validated for errors before being returned. Unlike get_icon_pngdata which checks if the response contains the expected data field and returns UnexpectedResponse on error, this method returns the raw plist response without any validation. The device might return an error dictionary instead of the expected icon state data. Consider checking if the response contains an error field or validating that it contains the expected structure before returning it to the caller.
| let res = self.idevice.read_plist_value().await?; | |
| let res = self.idevice.read_plist_value().await?; | |
| // Some devices may return an error dictionary instead of icon state. | |
| // Detect this and surface it as an UnexpectedResponse, similar to get_icon_pngdata. | |
| if let plist::Value::Dictionary(ref dict) = res { | |
| if dict.contains_key("error") || dict.contains_key("Error") { | |
| return Err(IdeviceError::UnexpectedResponse); | |
| } | |
| } |
- Implement set_icon_state() to modify home screen layout - Implement set_icon_state_with_version() with format_version parameter - Add truncate_dates_to_seconds() to convert nanosecond precision dates to second precision - Fix iOS compatibility issue where high-precision dates were rejected - Successfully tested on iOS 18.7.3 (previously believed to be restricted) - Follows pymobiledevice3 implementation pattern
…dule - Move date truncation logic from springboardservices to reusable utils::plist module - Add comprehensive unit tests for date truncation functionality - Add public API documentation for the utility function - This makes the date normalization logic available for other services that may need it
- Move date truncation from set_icon_state to get_icon_state - Eliminates unnecessary clone() operation in set_icon_state - Better performance when setting icon state multiple times - Cleaner API: data from get_icon_state is directly usable in set_icon_state - Users don't need to worry about date precision issues
|
Hey @jkcoxson! This PR has been significantly updated from the original version. Key changes: What's New
The Bug That Made It Seem BrokeniOS silently rejects icon states with nanosecond-precision dates. Rust's plist crate serializes with nanosecond precision by default, which made The fix: truncate all dates to second precision before iOS sees them. TestingReal device testing confirmed icons successfully swap positions. Cross-verified with pymobiledevice3's Python implementation. Ready for review! Let me know if you'd like any changes. 🚀 |
| /// ``` | ||
| /// | ||
| /// # Notes | ||
| /// - This method does NOT work on iOS 18+ due to Apple's security restrictions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this comment still necessary?
| pub async fn set_icon_state_with_version( | ||
| &mut self, | ||
| icon_state: plist::Value, | ||
| format_version: Option<String>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above, string ref and :? syntax
… error validation - Change format_version parameter from Option<String> to Option<&str> for consistency - Remove outdated iOS 18+ restriction comments since setIconState works on iOS 18+ - Add error validation to get_icon_state method similar to get_icon_pngdata - Update documentation to reflect accurate iOS compatibility
|
Thank you |
Summary
Add
get_icon_state()andset_icon_state()methods toSpringBoardServicesClientfor reading and writing iOS home screen icon layouts.🎉 BREAKTHROUGH:
set_icon_stateDOES work on iOS 18+ after fixing date precision issues!Changes
Added Methods
get_icon_state(format_version: Option<String>)formatVersionparameter for compatibilityset_icon_stateset_icon_state(icon_state: plist::Value)set_icon_state_with_version(icon_state, format_version)format_version="2"for direct icon access without nested sectionsNew Utility Module
Created
idevice/src/utils/plist.rs:truncate_dates_to_seconds()- Recursively normalizes plist datesThe Date Precision Bug Fix
Problem Discovery
Initial
set_icon_stateimplementation appeared to work (no errors) but icons didn't actually move. After extensive debugging, discovered the root cause:Rust's plist crate serializes dates with nanosecond precision:
iOS only accepts second precision:
When dates have nanosecond precision, iOS silently rejects the icon state change.
Solution
truncate_dates_to_seconds()utility to normalize datesget_icon_state()so returned data is immediately usable inset_icon_state()Testing
Tested on:
Test Results
✅
get_icon_state()- Successfully retrieves icon layout✅
set_icon_state()- Successfully modifies icon layout✅ Confirmed icons actually move on iOS 18.7.3
✅ Python pymobiledevice3 cross-verification successful
✅ All unit tests passing
Verification Method
Why It Works Now
The previous assumption that "iOS 18+ blocks setIconState" was incorrect. The real issue was:
With proper date normalization,
set_icon_stateworks perfectly on iOS 18+.Use Cases
Breaking Changes
None. These are new methods that don't affect existing functionality.
Related
Checklist