Repository navigation
fix: iOS 27에서 앱이 실행되지 않는 문제를 UIScene 생명주기로 고친다 - #47
Conversation
iOS 27 SDK로 링크된 앱은 실행 시점에 UIKit이 Scene 매니페스트를 검사한다. 우리 앱은 매니페스트 없이 AppDelegate가 UIWindow(frame:)로 창을 직접 띄우는 예전 방식이라 이 검사(UIApplicationEvaluateRuntimeIssueForNoSceneLifecycleAdoption) 에서 EXC_BREAKPOINT로 멈추고, iOS 27 베타 기기에서 앱이 열리지 않았다. iOS 26.6.1 기기에서는 같은 TestFlight 빌드(1.7.2/22)가 정상 실행됐다. - SceneDelegate를 얇은 어댑터로 추가한다. RN은 지금처럼 didFinishLaunching에서 시작하고, 그 window를 연결된 UIWindowScene에 붙인다. window를 새로 만들지 않는 건 RNFB messaging·expo-system-ui가 delegate.window를 읽기 때문이다 - Scene 생명주기에서는 iOS가 AppDelegate의 open url / continue userActivity를 부르지 않는다. cold(connectionOptions)·warm(scene 콜백) URL을 모두 AppDelegate의 기존 메서드로 위임해 firebaseauth 필터 → Expo 구독자 → RCTLinkingManager 순서를 그대로 탄다. RCTLinkingManager를 직접 부르면 expo-linking 구독자를 건너뛰어 expo-router가 읽는 ExpoLinkingRegistry.initialURL이 비고, cold start 딥링크가 홈으로 떨어진다 - withIosPrebuildFixes가 매니페스트와 SceneDelegate를 생성하게 해서 expo prebuild --clean 뒤에도 유지된다 Expo SDK 54의 ExpoAppDelegate에는 Scene 지원이 없어 SDK 업그레이드 대신 이 방식을 택했다. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
WalkthroughiOS Scene 지원을 추가했습니다. SceneDelegate가 window를 Scene에 연결하고 URL 및 user activity 처리를 AppDelegate에 전달합니다. 설정 플러그인과 앱 프로젝트에 Scene manifest와 SceneDelegate 파일 등록을 추가했습니다. ChangesiOS Scene 지원
Priority: ➖ Normal Estimated code review effort: 2 (Simple) | ~10 minutes Change: Bug fix Sequence Diagram(s)sequenceDiagram
participant iOS as iOS Scene
participant SceneDelegate
participant AppDelegate
iOS->>SceneDelegate: Scene 연결 옵션 전달
opt URL이 있는 경우
SceneDelegate->>AppDelegate: application(_:open:options:) 호출
end
opt user activity가 있는 경우
SceneDelegate->>AppDelegate: application(_:continue:restorationHandler:) 호출
end
Suggested reviewers: Merge Risk: ⚪ Minimal · up to
|
무엇
iOS 27 베타 기기에서 앱이 열리지 않는 문제를 고칩니다. 앱을 UIScene 생명주기로 전환합니다.
ios/app/SceneDelegate.swift(신규): AppDelegate가 띄운 RN window를 Scene에 붙이고, 들어온 URL은 AppDelegate의 기존 메서드로 위임합니다ios/app/Info.plist:UIApplicationSceneManifest추가ios/app.xcodeproj/project.pbxproj: SceneDelegate를 앱 타깃에 등록plugins/withIosPrebuildFixes.js,plugins/ios-prebuild-support/SceneDelegate.swift:expo prebuild뒤에도 위 변경이 다시 생성되도록 함왜
iOS 27 SDK로 빌드한 앱은 실행 시점에 UIKit이 Scene 매니페스트를 검사합니다. 우리 앱은 매니페스트 없이 AppDelegate가
UIWindow(frame:)로 창을 직접 띄우는 예전 방식이라, 이 검사(UIApplicationEvaluateRuntimeIssueForNoSceneLifecycleAdoption)에서EXC_BREAKPOINT로 멈춥니다.prod워크플로에서 Xcode 27 (27A266a) / macOS 27 (26A428)로 빌드됐습니다. 즉 iOS 27 SDK로 링크되어 강제 조건에 해당합니다 (Xcode Cloud 빌드 상세에서 확인).ExpoAppDelegate에는 Scene 지원이 없어서, SDK 업그레이드 대신 SceneDelegate를 직접 추가했습니다.설계: 기존 동작을 바꾸지 않기 위한 선택
AppDelegate의open url과continue userActivity를 호출하지 않습니다. 그래서 앱이 꺼진 상태에서 들어온 URL(connectionOptions)과 켜진 상태에서 들어온 URL(Scene 콜백)을 모두 AppDelegate의 기존 메서드로 넘깁니다. 그러면 firebaseauth 필터 → Expo 구독자 → RCTLinkingManager 순서가 그대로 유지됩니다.RCTLinkingManager를 직접 호출하면 expo-linking 구독자를 건너뜁니다. 그러면 expo-router가 읽는ExpoLinkingRegistry.initialURL이 비어서, 앱이 꺼진 상태에서 딥링크로 열 때 홈으로 떨어집니다.delegate.window를 읽기 때문에 같은 객체를 써야 합니다.applicationDidBecomeActive등)은 Scene 방식에서 호출되지 않습니다. 하지만 우리 의존성 중 이 콜백을 쓰는 곳은 없습니다. RN AppState, Mixpanel, RNFB는UIApplication*Notification을 구독하는데, 이 알림은 Scene 방식에서도 계속 나옵니다.UNUserNotificationCenter경로라 Scene과 관계가 없습니다.검증
iOS 26.2 시뮬레이터에서 Release 빌드로 확인했습니다. Scene 매니페스트가 있으면 iOS 26에서도 Scene 방식으로 실행되므로, 기존 동작이 깨지는지는 iOS 26에서 확인할 수 있습니다.
moadongapp://modalmoadongapp://modalexpo prebuild재생성 (임시 복사본)Scene 방식에서는 iOS가 AppDelegate의
open url을 직접 호출하지 않습니다. 따라서 딥링크가 동작했다는 것은 SceneDelegate의 위임이 작동한다는 증거입니다.아직 확인하지 못한 것
https://www.moadong.com/...: 시뮬레이터 빌드가 서명되지 않아 테스트하지 못했습니다참고 (리뷰에서 나온 것)
Linking.getInitialURL()이 앱이 꺼진 상태에서 들어온 URL을 받지 못합니다(launchOptions에 URL이 없음). 지금 앱은 expo-router의getLinkingURL()만 쓰므로 영향이 없습니다. 앞으로 초기 URL은getLinkingURL계열로 읽어야 합니다.ios/app/SceneDelegate.swift와plugins/ios-prebuild-support/SceneDelegate.swift는 같은 파일입니다. 기존 support 파일들과 같은 패턴이며, 한쪽만 고치면 prebuild 때 덮어써집니다.🤖 Generated with Claude Code
Summary by CodeRabbit