Skip to content

iOS localized icons: defer setAlternateIconName: to active state (#4870 follow-up)#4873

Open
shai-almog wants to merge 1 commit intomasterfrom
ios-localized-icons-defer-active-state
Open

iOS localized icons: defer setAlternateIconName: to active state (#4870 follow-up)#4873
shai-almog wants to merge 1 commit intomasterfrom
ios-localized-icons-defer-active-state

Conversation

@shai-almog
Copy link
Copy Markdown
Collaborator

Summary

Follow-up to #4870 — that PR injected CFBundleIconName so actool emits the partial Info.plist with CFBundleAlternateIcons. The bundle config is now correct, but developers still reported "no localized icon and no permission dialog." Reason: the runtime selector calls -[UIApplication setAlternateIconName:completionHandler:] from application:didFinishLaunchingWithOptions:, where iOS cancels the call (NSCocoaErrorDomain code 3072) because no foreground UIScene is up yet to anchor the system alert. The previous completionHandler:nil swallowed the error.

This PR changes buildLocalizedIconSelectorObjC() in IPhoneBuilder so the runtime selector:

  • defers the icon switch to the next UIApplicationDidBecomeActiveNotification (or runs immediately on the main queue if the app is already active);
  • passes a real completion handler that NSLogs successes and errors so any remaining bundle-configuration problem is visible in the device log.

The matching BuildDaemon change is on its own branch (rebased onto current master after #70 was merged); a separate PR will land it there.

Test plan

  • Maven plugin compiles cleanly (mvn install -pl codenameone-maven-plugin -Plocal-dev-javase).
  • Generated cn1app-archetype project (mvn package … -Dcodename1.buildTarget=ios-source) emits:
    • Images.xcassets/AppIcon_es.appiconset/ with 60@2x, 60@3x, 76@2xipad, 83.5@2xipad PNGs and a matching Contents.json;
    • <key>CFBundleIconName</key><string>AppIcon</string> in the source Info.plist;
    • ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES = "AppIcon_es" in project.pbxproj;
    • cn1ApplyIcon block + UIApplicationDidBecomeActiveNotification observer at all three marker positions in CodenameOne_GLAppDelegate.m.
  • xcodebuild for iphonesimulator succeeds.
  • Final merged Info.plist in the built .app contains CFBundleAlternateIcons.AppIcon_es.
  • Simulator (iPhone 16 / iOS 18.6 and iPhone 17 / iOS 26.3.1) launched with es_ES locale: no NSError logged; LaunchServices logs Setting preferredIconName to AppIcon_es for { bundleID: com.example, ... }. With the prior dispatch_async-only attempt the same setup logged NSUserCancelledError — confirming the active-state observer is the variable that fixes it.

🤖 Generated with Claude Code

…surface errors (#4870 follow-up)

Builds on #4870 (CFBundleIconName injection) which made actool emit the
correct partial Info.plist. Even with a correctly merged
CFBundleIcons.CFBundleAlternateIcons table, calling
-[UIApplication setAlternateIconName:completionHandler:] from
application:didFinishLaunchingWithOptions: still fails silently with
NSCocoaErrorDomain Code=3072 ("operation was cancelled") because no
foreground UIScene is yet available to anchor the system icon-change
alert. Without a completion handler the failure was silent, which is
why developers reported "no localized icon and no permission dialog"
even after #4870.

Changes in buildLocalizedIconSelectorObjC():
* Defer the icon switch to the next UIApplicationDidBecomeActiveNotification
  (or run immediately on the main queue if the app is already active),
  giving iOS an active scene to host the system alert.
* Pass a real completion handler that NSLogs successes and errors so any
  remaining bundle-configuration problem is visible in the device log
  instead of being swallowed.

Validated end-to-end against a freshly generated cn1app-archetype
project: actool produces the expected CFBundleAlternateIcons entry, the
resulting .app builds for the iOS 18.6 and iOS 26.3 simulators, and
LaunchServices logs "Setting preferredIconName to AppIcon_es" on launch
under es_ES locale, where the prior selector logged
NSUserCancelledError. The matching change is in the BuildDaemon repo.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

✅ Continuous Quality Report

Test & Coverage

Static Analysis

  • SpotBugs [Report archive]
    • ByteCodeTranslator: 0 findings (no issues)
    • android: 0 findings (no issues)
    • codenameone-maven-plugin: 0 findings (no issues)
    • core-unittests: 0 findings (no issues)
    • ios: 0 findings (no issues)
  • PMD: 0 findings (no issues) [Report archive]
  • Checkstyle: 0 findings (no issues) [Report archive]

Generated automatically by the PR CI workflow.

@shai-almog
Copy link
Copy Markdown
Collaborator Author

shai-almog commented May 6, 2026

iOS screenshot updates

Compared 90 screenshots: 89 matched, 1 updated.

  • landscape — updated screenshot. Screenshot differs (2556x1179 px, bit depth 8).

    landscape
    Preview info: Preview provided by instrumentation.
    Full-resolution PNG saved as landscape.png in workflow artifacts.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 282 seconds

Build and Run Timing

Metric Duration
Simulator Boot 80000 ms
Simulator Boot (Run) 1000 ms
App Install 14000 ms
App Launch 11000 ms
Test Execution 269000 ms

Detailed Performance Metrics

Metric Duration
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 native encode 1384.000 ms
Base64 CN1 encode 1646.000 ms
Base64 encode ratio (CN1/native) 1.189x (18.9% slower)
Base64 native decode 801.000 ms
Base64 CN1 decode 989.000 ms
Base64 decode ratio (CN1/native) 1.235x (23.5% slower)
Base64 SIMD encode 401.000 ms
Base64 encode ratio (SIMD/native) 0.290x (71.0% faster)
Base64 encode ratio (SIMD/CN1) 0.244x (75.6% faster)
Base64 SIMD decode 412.000 ms
Base64 decode ratio (SIMD/native) 0.514x (48.6% faster)
Base64 decode ratio (SIMD/CN1) 0.417x (58.3% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 64.000 ms
Image createMask (SIMD on) 10.000 ms
Image createMask ratio (SIMD on/off) 0.156x (84.4% faster)
Image applyMask (SIMD off) 154.000 ms
Image applyMask (SIMD on) 77.000 ms
Image applyMask ratio (SIMD on/off) 0.500x (50.0% faster)
Image modifyAlpha (SIMD off) 132.000 ms
Image modifyAlpha (SIMD on) 78.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.591x (40.9% faster)
Image modifyAlpha removeColor (SIMD off) 163.000 ms
Image modifyAlpha removeColor (SIMD on) 86.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.528x (47.2% faster)
Image PNG encode (SIMD off) 1308.000 ms
Image PNG encode (SIMD on) 891.000 ms
Image PNG encode ratio (SIMD on/off) 0.681x (31.9% faster)
Image JPEG encode 526.000 ms

@shai-almog
Copy link
Copy Markdown
Collaborator Author

shai-almog commented May 6, 2026

Compared 90 screenshots: 90 matched.

Native Android coverage

  • 📊 Line coverage: 10.07% (5486/54499 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 7.92% (26940/340279), branch 3.61% (1177/32620), complexity 4.63% (1446/31249), method 8.14% (1189/14604), class 13.55% (266/1963)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6327 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.ClassReader – 0.00% (0/1519 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1148 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.MethodWriter – 0.00% (0/923 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/730 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/623 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.Frame – 0.00% (0/564 lines covered)
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysJvmKt – 0.00% (0/495 lines covered)
      • kotlinx.coroutines.kotlinx.coroutines.JobSupport – 0.00% (0/423 lines covered)

✅ Native Android screenshot tests passed.

Native Android coverage

  • 📊 Line coverage: 10.07% (5486/54499 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 7.92% (26940/340279), branch 3.61% (1177/32620), complexity 4.63% (1446/31249), method 8.14% (1189/14604), class 13.55% (266/1963)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6327 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.ClassReader – 0.00% (0/1519 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1148 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.MethodWriter – 0.00% (0/923 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/730 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/623 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.Frame – 0.00% (0/564 lines covered)
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysJvmKt – 0.00% (0/495 lines covered)
      • kotlinx.coroutines.kotlinx.coroutines.JobSupport – 0.00% (0/423 lines covered)

Benchmark Results

Detailed Performance Metrics

Metric Duration
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 native encode 1169.000 ms
Base64 CN1 encode 230.000 ms
Base64 encode ratio (CN1/native) 0.197x (80.3% faster)
Base64 native decode 913.000 ms
Base64 CN1 decode 366.000 ms
Base64 decode ratio (CN1/native) 0.401x (59.9% faster)
Image encode benchmark status skipped (SIMD unsupported)

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.

1 participant