Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@fulln
Copy link
Contributor

@fulln fulln commented Jan 21, 2026

Summary

Add get_icon_state() and set_icon_state() methods to SpringBoardServicesClient for reading and writing iOS home screen icon layouts.

🎉 BREAKTHROUGH: set_icon_state DOES work on iOS 18+ after fixing date precision issues!

Changes

Added Methods

  1. get_icon_state(format_version: Option<String>)

    • Retrieves complete home screen layout including icon positions and folders
    • Supports optional formatVersion parameter for compatibility
    • Automatically normalizes date precision for compatibility with set_icon_state
  2. set_icon_state(icon_state: plist::Value)

    • Sets home screen icon layout
    • Can swap icons, rearrange pages, modify folders
    • ✅ Works on iOS 18.7.3 (previously thought to be blocked)
  3. set_icon_state_with_version(icon_state, format_version)

    • Sets icon state with explicit format version
    • Use format_version="2" for direct icon access without nested sections

New Utility Module

Created idevice/src/utils/plist.rs:

  • truncate_dates_to_seconds() - Recursively normalizes plist dates
  • Solves iOS date precision compatibility issue
  • Reusable for other services
  • Comprehensive unit tests

The Date Precision Bug Fix

Problem Discovery

Initial set_icon_state implementation 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:

2026-01-17T03:09:58.332738876Z

iOS only accepts second precision:

2026-01-17T03:09:58Z

When dates have nanosecond precision, iOS silently rejects the icon state change.

Solution

  1. Created truncate_dates_to_seconds() utility to normalize dates
  2. Applied in get_icon_state() so returned data is immediately usable in set_icon_state()
  3. Users don't need to know about the precision issue

Testing

Tested on:

  • Device: iPhone 16,2 (iPhone 15 Pro Max)
  • iOS Version: 18.7.3 (Build 22H217)
  • Date: January 2026

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

// Read current state
let original = client.get_icon_state(Some("2".to_string())).await?;

// Swap two icons on first page
let mut modified = original.clone();
// ... swap logic ...

// Apply changes
client.set_icon_state_with_version(modified, Some("2".to_string())).await?;

// Verify on device - icons successfully swapped!

Why It Works Now

The previous assumption that "iOS 18+ blocks setIconState" was incorrect. The real issue was:

  1. Date precision incompatibility causing silent failures
  2. Insufficient verification methodology

With proper date normalization, set_icon_state works perfectly on iOS 18+.

Use Cases

  • Backup/restore home screen layouts
  • Automation - programmatic icon arrangement
  • Device management - enforce corporate layouts
  • Development tools - reset test device state
  • User migrations - transfer layouts between devices

Breaking Changes

None. These are new methods that don't affect existing functionality.

Related

Checklist

  • Code compiles without warnings
  • Tested on real device (iOS 18.7.3)
  • Documentation includes usage examples
  • API follows existing code style
  • Unit tests added and passing
  • No breaking changes
  • Date precision issue documented

…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)
Copilot AI review requested due to automatic review settings January 21, 2026 02:31
Copy link

Copilot AI left a 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?;
Copy link

Copilot AI Jan 21, 2026

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.

Suggested change
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);
}
}

Copilot uses AI. Check for mistakes.
fulln added 3 commits January 21, 2026 11:13
- 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
@fulln fulln changed the title feat(springboard): add get_icon_state method for reading home screen layout feat(springboard): add get_icon_state and set_icon_state methods with iOS 18+ support Jan 21, 2026
@fulln
Copy link
Contributor Author

fulln commented Jan 21, 2026

Hey @jkcoxson!

This PR has been significantly updated from the original version. Key changes:

What's New

  • ✅ Added set_icon_state() and set_icon_state_with_version() methods
  • ✅ Fixed critical date precision bug that was causing silent failures
  • ✅ Created reusable utils::plist module with comprehensive tests
  • ✅ Confirmed working on iOS 18.7.3 (iPhone 15 Pro Max)

The Bug That Made It Seem Broken

iOS silently rejects icon states with nanosecond-precision dates. Rust's plist crate serializes with nanosecond precision by default, which made set_icon_state appear to execute successfully but not actually move icons.

The fix: truncate all dates to second precision before iOS sees them.

Testing

Real 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. 🚀

Repository owner deleted a comment from Copilot AI Jan 21, 2026
/// ```
///
/// # Notes
/// - This method does NOT work on iOS 18+ due to Apple's security restrictions
Copy link
Owner

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>,
Copy link
Owner

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
@fulln fulln requested a review from jkcoxson January 21, 2026 09:05
@jkcoxson jkcoxson merged commit 9a71279 into jkcoxson:master Jan 22, 2026
3 checks passed
@jkcoxson
Copy link
Owner

Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants