From 683fa1a77a23c509479134ea92cffa1f52203c64 Mon Sep 17 00:00:00 2001 From: Evan Bacon Date: Wed, 27 May 2020 17:34:07 -0700 Subject: [PATCH 1/3] Convert bare-expo to swift --- apps/bare-expo/ios/BareExpo-Bridging-Header.h | 31 ++++ .../ios/BareExpo.xcodeproj/project.pbxproj | 27 ++-- apps/bare-expo/ios/BareExpo/AppDelegate.h | 18 --- apps/bare-expo/ios/BareExpo/AppDelegate.m | 102 ------------ apps/bare-expo/ios/BareExpo/AppDelegate.swift | 148 ++++++++++++++++++ apps/bare-expo/ios/BareExpo/main.m | 16 -- 6 files changed, 196 insertions(+), 146 deletions(-) create mode 100644 apps/bare-expo/ios/BareExpo-Bridging-Header.h delete mode 100644 apps/bare-expo/ios/BareExpo/AppDelegate.h delete mode 100644 apps/bare-expo/ios/BareExpo/AppDelegate.m create mode 100644 apps/bare-expo/ios/BareExpo/AppDelegate.swift delete mode 100644 apps/bare-expo/ios/BareExpo/main.m diff --git a/apps/bare-expo/ios/BareExpo-Bridging-Header.h b/apps/bare-expo/ios/BareExpo-Bridging-Header.h new file mode 100644 index 0000000000000..0a8755b2c610e --- /dev/null +++ b/apps/bare-expo/ios/BareExpo-Bridging-Header.h @@ -0,0 +1,31 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +// React + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + + +// Unimodules + +#import +#import +#import +#import + +// OTA Updates + +//#import + diff --git a/apps/bare-expo/ios/BareExpo.xcodeproj/project.pbxproj b/apps/bare-expo/ios/BareExpo.xcodeproj/project.pbxproj index 664369f8711d6..d84cee7f306f0 100644 --- a/apps/bare-expo/ios/BareExpo.xcodeproj/project.pbxproj +++ b/apps/bare-expo/ios/BareExpo.xcodeproj/project.pbxproj @@ -8,12 +8,11 @@ /* Begin PBXBuildFile section */ 00E356F31AD99517003FC87E /* BareExpoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* BareExpoTests.m */; }; - 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; - 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 31B5C869245847DF0086F49B /* notification.wav in Resources */ = {isa = PBXBuildFile; fileRef = 31B5C868245847DF0086F49B /* notification.wav */; }; 6EACD0A8207D4B44E882DAB9 /* libPods-BareExpo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 88C45DD943C52814593043BC /* libPods-BareExpo.a */; }; + CD59639C247F2EFA0030EECA /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD59639B247F2EFA0030EECA /* AppDelegate.swift */; }; CD6B041323091F4B002044FF /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD6B041223091F4B002044FF /* StoreKit.framework */; }; E1653C7C414D0CD8F87150FE /* libPods-BareExpoTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 028439B18A901F7A2CF09BB9 /* libPods-BareExpoTests.a */; }; /* End PBXBuildFile section */ @@ -35,12 +34,9 @@ 00E356F21AD99517003FC87E /* BareExpoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BareExpoTests.m; sourceTree = ""; }; 028439B18A901F7A2CF09BB9 /* libPods-BareExpoTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-BareExpoTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07F961A680F5B00A75B9A /* Bare Expo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Bare Expo.app"; sourceTree = BUILT_PRODUCTS_DIR; }; - 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = BareExpo/AppDelegate.h; sourceTree = ""; }; - 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = BareExpo/AppDelegate.m; sourceTree = ""; }; 13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = BareExpo/Images.xcassets; sourceTree = ""; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = BareExpo/Info.plist; sourceTree = ""; }; - 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = BareExpo/main.m; sourceTree = ""; }; 2D16E6891FA4F8E400B85C8A /* libReact.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libReact.a; sourceTree = BUILT_PRODUCTS_DIR; }; 31B5C868245847DF0086F49B /* notification.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = notification.wav; sourceTree = ""; }; 31B7D64323A904E900CE18C0 /* Bare Expo.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = "Bare Expo.entitlements"; path = "BareExpo/Bare Expo.entitlements"; sourceTree = ""; }; @@ -48,6 +44,8 @@ 70419E2A27811C660476A295 /* Pods-BareExpo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BareExpo.release.xcconfig"; path = "Target Support Files/Pods-BareExpo/Pods-BareExpo.release.xcconfig"; sourceTree = ""; }; 7EF74F8A2123893DE8D71406 /* Pods-BareExpoTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BareExpoTests.debug.xcconfig"; path = "Target Support Files/Pods-BareExpoTests/Pods-BareExpoTests.debug.xcconfig"; sourceTree = ""; }; 88C45DD943C52814593043BC /* libPods-BareExpo.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-BareExpo.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + CD59639A247F2EF90030EECA /* BareExpo-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BareExpo-Bridging-Header.h"; sourceTree = ""; }; + CD59639B247F2EFA0030EECA /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = BareExpo/AppDelegate.swift; sourceTree = ""; }; CD6B041223091F4B002044FF /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; }; E4628F702B77F544CEDC686D /* Pods-BareExpoTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BareExpoTests.release.xcconfig"; path = "Target Support Files/Pods-BareExpoTests/Pods-BareExpoTests.release.xcconfig"; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; @@ -95,15 +93,14 @@ 13B07FAE1A68108700A75B9A /* BareExpo */ = { isa = PBXGroup; children = ( + CD59639B247F2EFA0030EECA /* AppDelegate.swift */, 31B7D64323A904E900CE18C0 /* Bare Expo.entitlements */, 008F07F21AC5B25A0029DE68 /* main.jsbundle */, - 13B07FAF1A68108700A75B9A /* AppDelegate.h */, - 13B07FB01A68108700A75B9A /* AppDelegate.m */, 13B07FB51A68108700A75B9A /* Images.xcassets */, 13B07FB61A68108700A75B9A /* Info.plist */, 13B07FB11A68108700A75B9A /* LaunchScreen.xib */, - 13B07FB71A68108700A75B9A /* main.m */, 31B5C868245847DF0086F49B /* notification.wav */, + CD59639A247F2EF90030EECA /* BareExpo-Bridging-Header.h */, ); name = BareExpo; sourceTree = ""; @@ -223,6 +220,7 @@ }; 13B07F861A680F5B00A75B9A = { DevelopmentTeam = C8D8QTF339; + LastSwiftMigration = 1140; }; }; }; @@ -423,8 +421,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, - 13B07FC11A68108700A75B9A /* main.m in Sources */, + CD59639C247F2EFA0030EECA /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -455,6 +452,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 7EF74F8A2123893DE8D71406 /* Pods-BareExpoTests.debug.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -478,6 +476,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = E4628F702B77F544CEDC686D /* Pods-BareExpoTests.release.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; COPY_PHASE_STRIP = NO; INFOPLIST_FILE = BareExpoTests/Info.plist; @@ -499,6 +498,7 @@ baseConfigurationReference = 4ADC22B6EC034901305B8CDC /* Pods-BareExpo.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = "BareExpo/Bare Expo.entitlements"; CURRENT_PROJECT_VERSION = 1; DEAD_CODE_STRIPPING = NO; @@ -510,8 +510,12 @@ "-ObjC", "-lc++", ); + OTHER_SWIFT_FLAGS = "$(inherited) -D COCOAPODS -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/yoga/Yoga.modulemap\" -DDEBUG"; PRODUCT_BUNDLE_IDENTIFIER = dev.expo.Payments; PRODUCT_NAME = "Bare Expo"; + SWIFT_OBJC_BRIDGING_HEADER = "BareExpo-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; }; @@ -522,6 +526,7 @@ baseConfigurationReference = 70419E2A27811C660476A295 /* Pods-BareExpo.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = "BareExpo/Bare Expo.entitlements"; CURRENT_PROJECT_VERSION = 1; DEAD_CODE_STRIPPING = YES; @@ -535,6 +540,8 @@ ); PRODUCT_BUNDLE_IDENTIFIER = dev.expo.Payments; PRODUCT_NAME = "Bare Expo"; + SWIFT_OBJC_BRIDGING_HEADER = "BareExpo-Bridging-Header.h"; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; }; diff --git a/apps/bare-expo/ios/BareExpo/AppDelegate.h b/apps/bare-expo/ios/BareExpo/AppDelegate.h deleted file mode 100644 index 78fbb4d64496a..0000000000000 --- a/apps/bare-expo/ios/BareExpo/AppDelegate.h +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import -#import -#import -#import - -@interface AppDelegate : UMAppDelegateWrapper - -@property (nonatomic, strong) UMModuleRegistryAdapter *moduleRegistryAdapter; -@property (nonatomic, strong) UIWindow *window; - -@end diff --git a/apps/bare-expo/ios/BareExpo/AppDelegate.m b/apps/bare-expo/ios/BareExpo/AppDelegate.m deleted file mode 100644 index ae4ea14bef6e7..0000000000000 --- a/apps/bare-expo/ios/BareExpo/AppDelegate.m +++ /dev/null @@ -1,102 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import "AppDelegate.h" - -#import - -#import -#import -#import -#import - -#import -#import -#import - -@implementation AppDelegate - -@synthesize window = _window; - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ - [self ensureReactMethodSwizzlingSetUp]; - - self.moduleRegistryAdapter = [[UMModuleRegistryAdapter alloc] initWithModuleRegistryProvider:[[UMModuleRegistryProvider alloc] init]]; - RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; - RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"BareExpo" initialProperties:nil]; - rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; - - self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; - UIViewController *rootViewController = [UIViewController new]; - rootViewController.view = rootView; - self.window.rootViewController = rootViewController; - [self.window makeKeyAndVisible]; - - [super application:application didFinishLaunchingWithOptions:launchOptions]; - - return YES; -} - -- (NSArray> *)extraModulesForBridge:(RCTBridge *)bridge -{ - NSMutableArray> *extraModules = [NSMutableArray arrayWithArray:[_moduleRegistryAdapter extraModulesForBridge:bridge]]; - // You can inject any extra modules that you would like here, more information at: - // https://facebook.github.io/react-native/docs/native-modules-ios.html#dependency-injection - - // RCTDevMenu was removed when integrating React with Expo client: - // https://github.com/expo/react-native/commit/7f2912e8005ea6e81c45935241081153b822b988 - // Let's bring it back in Bare Expo. - [extraModules addObject:(id)[[RCTDevMenu alloc] init]]; - return extraModules; -} - -- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { -#ifdef DEBUG - return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; -#else - return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; -#endif -} - -#if RCT_DEV -- (BOOL)bridge:(RCTBridge *)bridge didNotFindModule:(NSString *)moduleName { - return YES; -} -#endif - - -- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options -{ - return [RCTLinkingManager application:app openURL:url options:options]; -} - -// Bring back React method swizzling removed from its Pod -// when integrating with Expo client. -// https://github.com/expo/react-native/commit/7f2912e8005ea6e81c45935241081153b822b988 -- (void)ensureReactMethodSwizzlingSetUp -{ - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wundeclared-selector" - // RCTKeyCommands.m - // swizzle UIResponder - RCTSwapInstanceMethods([UIResponder class], - @selector(keyCommands), - @selector(RCT_keyCommands)); - - // RCTDevMenu.m - // We're swizzling here because it's poor form to override methods in a category, - // however UIWindow doesn't actually implement motionEnded:withEvent:, so there's - // no need to call the original implementation. - RCTSwapInstanceMethods([UIWindow class], @selector(motionEnded:withEvent:), @selector(RCT_motionEnded:withEvent:)); - #pragma clang diagnostic pop - }); -} - -@end diff --git a/apps/bare-expo/ios/BareExpo/AppDelegate.swift b/apps/bare-expo/ios/BareExpo/AppDelegate.swift new file mode 100644 index 0000000000000..690fd186a2517 --- /dev/null +++ b/apps/bare-expo/ios/BareExpo/AppDelegate.swift @@ -0,0 +1,148 @@ +// +// AppDelegate.swift +// BareExpo +// +// Created by the Expo team on 5/27/20. +// Copyright © 2020 Expo. All rights reserved. +// + +import Foundation + +@UIApplicationMain +class AppDelegate: UMAppDelegateWrapper { + var launchOptions: [UIApplication.LaunchOptionsKey: Any]? + var moduleRegistryAdapter: UMModuleRegistryAdapter! + + override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + + ensureReactMethodSwizzlingSetUp() + + moduleRegistryAdapter = UMModuleRegistryAdapter(moduleRegistryProvider: UMModuleRegistryProvider()) + self.launchOptions = launchOptions + + self.window = UIWindow(frame: UIScreen.main.bounds) + + // DEBUG must be setup in Swift projects: https://stackoverflow.com/a/24112024/4047926 +// #if DEBUG + initializeReactNativeApp() +// #else +// let controller = EXUpdatesAppController.sharedInstance() +// controller.delegate = self +// controller.startAndShowLaunchScreen(window!) +// #endif + + super.application(application, didFinishLaunchingWithOptions: launchOptions); + + return true + } + + @discardableResult + func initializeReactNativeApp() -> RCTBridge? { + guard let bridge = RCTBridge(delegate: self, launchOptions: launchOptions) else { return nil } + let rootView = RCTRootView(bridge: bridge, moduleName: "BareExpo", initialProperties: nil) + let rootViewController = UIViewController() + rootView.backgroundColor = UIColor.white; + rootViewController.view = rootView + + window?.rootViewController = rootViewController + window?.makeKeyAndVisible() + + return bridge + } + + #if RCT_DEV + func bridge(_ bridge: RCTBridge!, didNotFindModule moduleName: String!) -> Bool { + return true; + } + #endif + + override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { + return RCTLinkingManager.application(app, open: url, options: options); + } +} + +// MARK: - RCTBridgeDelegate + +extension AppDelegate: RCTBridgeDelegate { + func sourceURL(for bridge: RCTBridge!) -> URL! { + #if DEBUG + return RCTBundleURLProvider.sharedSettings()?.jsBundleURL(forBundleRoot: "index", fallbackResource: nil) + #else +// return EXUpdatesAppController.sharedInstance().launchAssetUrl! + return Bundle.main.url(forResource: "main", withExtension: "jsbundle"); + #endif + } + + func extraModules(for bridge: RCTBridge!) -> [RCTBridgeModule]! { + var extraModules = moduleRegistryAdapter.extraModules(for: bridge) + // You can inject any extra modules that you would like here, more information at: + // https://facebook.github.io/react-native/docs/native-modules-ios.html#dependency-injection + + // RCTDevMenu was removed when integrating React with Expo client: + // https://github.com/expo/react-native/commit/7f2912e8005ea6e81c45935241081153b822b988 + // Let's bring it back in Bare Expo. + extraModules?.append(RCTDevMenu() as! RCTBridgeModule) + return extraModules + } +} + +// MARK: - Expo fork of React Native + +public class Dispatch +{ + private static var _onceTracker = [String]() + + public class func once(file: String = #file, + function: String = #function, + line: Int = #line, + block: () -> Void) { + let token = "\(file):\(function):\(line)" + once(token: token, block: block) + } + + /** + Executes a block of code, associated with a unique token, only once. The code is thread safe and will + only execute the code once even in the presence of multithreaded calls. + + - parameter token: A unique reverse DNS style name such as com.vectorform. or a GUID + - parameter block: Block to execute once + */ + public class func once(token: String, + block: () -> Void) { + objc_sync_enter(self) + defer { objc_sync_exit(self) } + + guard !_onceTracker.contains(token) else { return } + + _onceTracker.append(token) + block() + } +} + +extension AppDelegate { + // Bring back React method swizzling removed from its Pod + // when integrating with Expo client. + // https://github.com/expo/react-native/commit/7f2912e8005ea6e81c45935241081153b822b988 + func ensureReactMethodSwizzlingSetUp() { + Dispatch.once { + + //#pragma clang diagnostic push + //#pragma clang diagnostic ignored "-Wundeclared-selector" + // RCTKeyCommands.m + // swizzle UIResponder + RCTSwapInstanceMethods(UIResponder.self, + #selector(getter: UIResponder.keyCommands), + Selector(("RCT_keyCommands"))); + + // RCTDevMenu.m + // We're swizzling here because it's poor form to override methods in a category, + // however UIWindow doesn't actually implement motionEnded:withEvent:, so there's + // no need to call the original implementation. + RCTSwapInstanceMethods(UIWindow.self, + #selector(UIResponder.motionEnded(_:with:)), + Selector(("RCT_motionEnded:withEvent:"))); + //#pragma clang diagnostic pop + } + } +} + diff --git a/apps/bare-expo/ios/BareExpo/main.m b/apps/bare-expo/ios/BareExpo/main.m deleted file mode 100644 index c316cf816e736..0000000000000 --- a/apps/bare-expo/ios/BareExpo/main.m +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import - -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} From 23a5c2912e4e4912b117b095d8af8133e7de183b Mon Sep 17 00:00:00 2001 From: Evan Bacon Date: Thu, 28 May 2020 10:32:06 -0700 Subject: [PATCH 2/3] Clean up swift code --- .../ios/BareExpo.xcodeproj/project.pbxproj | 4 + apps/bare-expo/ios/BareExpo/AppDelegate.swift | 131 ++++++------------ apps/bare-expo/ios/BareExpo/Dispatch.swift | 40 ++++++ 3 files changed, 84 insertions(+), 91 deletions(-) create mode 100644 apps/bare-expo/ios/BareExpo/Dispatch.swift diff --git a/apps/bare-expo/ios/BareExpo.xcodeproj/project.pbxproj b/apps/bare-expo/ios/BareExpo.xcodeproj/project.pbxproj index d84cee7f306f0..96ed64e2ac7eb 100644 --- a/apps/bare-expo/ios/BareExpo.xcodeproj/project.pbxproj +++ b/apps/bare-expo/ios/BareExpo.xcodeproj/project.pbxproj @@ -14,6 +14,7 @@ 6EACD0A8207D4B44E882DAB9 /* libPods-BareExpo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 88C45DD943C52814593043BC /* libPods-BareExpo.a */; }; CD59639C247F2EFA0030EECA /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD59639B247F2EFA0030EECA /* AppDelegate.swift */; }; CD6B041323091F4B002044FF /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD6B041223091F4B002044FF /* StoreKit.framework */; }; + CDDB247C24802C4C00F6E7AC /* Dispatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDDB247B24802C4C00F6E7AC /* Dispatch.swift */; }; E1653C7C414D0CD8F87150FE /* libPods-BareExpoTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 028439B18A901F7A2CF09BB9 /* libPods-BareExpoTests.a */; }; /* End PBXBuildFile section */ @@ -47,6 +48,7 @@ CD59639A247F2EF90030EECA /* BareExpo-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BareExpo-Bridging-Header.h"; sourceTree = ""; }; CD59639B247F2EFA0030EECA /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = BareExpo/AppDelegate.swift; sourceTree = ""; }; CD6B041223091F4B002044FF /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; }; + CDDB247B24802C4C00F6E7AC /* Dispatch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Dispatch.swift; path = BareExpo/Dispatch.swift; sourceTree = ""; }; E4628F702B77F544CEDC686D /* Pods-BareExpoTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BareExpoTests.release.xcconfig"; path = "Target Support Files/Pods-BareExpoTests/Pods-BareExpoTests.release.xcconfig"; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; ED2971642150620600B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS12.0.sdk/System/Library/Frameworks/JavaScriptCore.framework; sourceTree = DEVELOPER_DIR; }; @@ -94,6 +96,7 @@ isa = PBXGroup; children = ( CD59639B247F2EFA0030EECA /* AppDelegate.swift */, + CDDB247B24802C4C00F6E7AC /* Dispatch.swift */, 31B7D64323A904E900CE18C0 /* Bare Expo.entitlements */, 008F07F21AC5B25A0029DE68 /* main.jsbundle */, 13B07FB51A68108700A75B9A /* Images.xcassets */, @@ -422,6 +425,7 @@ buildActionMask = 2147483647; files = ( CD59639C247F2EFA0030EECA /* AppDelegate.swift in Sources */, + CDDB247C24802C4C00F6E7AC /* Dispatch.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/apps/bare-expo/ios/BareExpo/AppDelegate.swift b/apps/bare-expo/ios/BareExpo/AppDelegate.swift index 690fd186a2517..69e5890c4327b 100644 --- a/apps/bare-expo/ios/BareExpo/AppDelegate.swift +++ b/apps/bare-expo/ios/BareExpo/AppDelegate.swift @@ -10,7 +10,6 @@ import Foundation @UIApplicationMain class AppDelegate: UMAppDelegateWrapper { - var launchOptions: [UIApplication.LaunchOptionsKey: Any]? var moduleRegistryAdapter: UMModuleRegistryAdapter! override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { @@ -18,108 +17,34 @@ class AppDelegate: UMAppDelegateWrapper { ensureReactMethodSwizzlingSetUp() moduleRegistryAdapter = UMModuleRegistryAdapter(moduleRegistryProvider: UMModuleRegistryProvider()) - self.launchOptions = launchOptions - self.window = UIWindow(frame: UIScreen.main.bounds) - - // DEBUG must be setup in Swift projects: https://stackoverflow.com/a/24112024/4047926 -// #if DEBUG - initializeReactNativeApp() -// #else -// let controller = EXUpdatesAppController.sharedInstance() -// controller.delegate = self -// controller.startAndShowLaunchScreen(window!) -// #endif + window = UIWindow(frame: UIScreen.main.bounds) + + if let bridge = RCTBridge(delegate: self, launchOptions: launchOptions) { + let rootView = RCTRootView(bridge: bridge, moduleName: "BareExpo", initialProperties: nil) + let rootViewController = UIViewController() + rootView.backgroundColor = UIColor.white + rootViewController.view = rootView + + window?.rootViewController = rootViewController + window?.makeKeyAndVisible() + } - super.application(application, didFinishLaunchingWithOptions: launchOptions); + super.application(application, didFinishLaunchingWithOptions: launchOptions) return true } - @discardableResult - func initializeReactNativeApp() -> RCTBridge? { - guard let bridge = RCTBridge(delegate: self, launchOptions: launchOptions) else { return nil } - let rootView = RCTRootView(bridge: bridge, moduleName: "BareExpo", initialProperties: nil) - let rootViewController = UIViewController() - rootView.backgroundColor = UIColor.white; - rootViewController.view = rootView - - window?.rootViewController = rootViewController - window?.makeKeyAndVisible() - - return bridge - } - #if RCT_DEV func bridge(_ bridge: RCTBridge!, didNotFindModule moduleName: String!) -> Bool { - return true; + return true } #endif override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { - return RCTLinkingManager.application(app, open: url, options: options); - } -} - -// MARK: - RCTBridgeDelegate - -extension AppDelegate: RCTBridgeDelegate { - func sourceURL(for bridge: RCTBridge!) -> URL! { - #if DEBUG - return RCTBundleURLProvider.sharedSettings()?.jsBundleURL(forBundleRoot: "index", fallbackResource: nil) - #else -// return EXUpdatesAppController.sharedInstance().launchAssetUrl! - return Bundle.main.url(forResource: "main", withExtension: "jsbundle"); - #endif + return RCTLinkingManager.application(app, open: url, options: options) } - func extraModules(for bridge: RCTBridge!) -> [RCTBridgeModule]! { - var extraModules = moduleRegistryAdapter.extraModules(for: bridge) - // You can inject any extra modules that you would like here, more information at: - // https://facebook.github.io/react-native/docs/native-modules-ios.html#dependency-injection - - // RCTDevMenu was removed when integrating React with Expo client: - // https://github.com/expo/react-native/commit/7f2912e8005ea6e81c45935241081153b822b988 - // Let's bring it back in Bare Expo. - extraModules?.append(RCTDevMenu() as! RCTBridgeModule) - return extraModules - } -} - -// MARK: - Expo fork of React Native - -public class Dispatch -{ - private static var _onceTracker = [String]() - - public class func once(file: String = #file, - function: String = #function, - line: Int = #line, - block: () -> Void) { - let token = "\(file):\(function):\(line)" - once(token: token, block: block) - } - - /** - Executes a block of code, associated with a unique token, only once. The code is thread safe and will - only execute the code once even in the presence of multithreaded calls. - - - parameter token: A unique reverse DNS style name such as com.vectorform. or a GUID - - parameter block: Block to execute once - */ - public class func once(token: String, - block: () -> Void) { - objc_sync_enter(self) - defer { objc_sync_exit(self) } - - guard !_onceTracker.contains(token) else { return } - - _onceTracker.append(token) - block() - } -} - -extension AppDelegate { // Bring back React method swizzling removed from its Pod // when integrating with Expo client. // https://github.com/expo/react-native/commit/7f2912e8005ea6e81c45935241081153b822b988 @@ -132,7 +57,7 @@ extension AppDelegate { // swizzle UIResponder RCTSwapInstanceMethods(UIResponder.self, #selector(getter: UIResponder.keyCommands), - Selector(("RCT_keyCommands"))); + Selector(("RCT_keyCommands"))) // RCTDevMenu.m // We're swizzling here because it's poor form to override methods in a category, @@ -140,9 +65,33 @@ extension AppDelegate { // no need to call the original implementation. RCTSwapInstanceMethods(UIWindow.self, #selector(UIResponder.motionEnded(_:with:)), - Selector(("RCT_motionEnded:withEvent:"))); + Selector(("RCT_motionEnded:withEvent:"))) //#pragma clang diagnostic pop } } } +// MARK: - RCTBridgeDelegate + +extension AppDelegate: RCTBridgeDelegate { + func sourceURL(for bridge: RCTBridge!) -> URL! { + // DEBUG must be setup in Swift projects: https://stackoverflow.com/a/24112024/4047926 + #if DEBUG + return RCTBundleURLProvider.sharedSettings()?.jsBundleURL(forBundleRoot: "index", fallbackResource: nil) + #else + return Bundle.main.url(forResource: "main", withExtension: "jsbundle") + #endif + } + + func extraModules(for bridge: RCTBridge!) -> [RCTBridgeModule]! { + var extraModules = moduleRegistryAdapter.extraModules(for: bridge) + // You can inject any extra modules that you would like here, more information at: + // https://facebook.github.io/react-native/docs/native-modules-ios.html#dependency-injection + + // RCTDevMenu was removed when integrating React with Expo client: + // https://github.com/expo/react-native/commit/7f2912e8005ea6e81c45935241081153b822b988 + // Let's bring it back in Bare Expo. + extraModules?.append(RCTDevMenu() as! RCTBridgeModule) + return extraModules + } +} diff --git a/apps/bare-expo/ios/BareExpo/Dispatch.swift b/apps/bare-expo/ios/BareExpo/Dispatch.swift new file mode 100644 index 0000000000000..1b7a0ee99496d --- /dev/null +++ b/apps/bare-expo/ios/BareExpo/Dispatch.swift @@ -0,0 +1,40 @@ +// +// Dispatch.swift +// BareExpo +// +// Created by the Expo team on 5/27/20. +// Copyright © 2020 Expo. All rights reserved. +// + +import Foundation + +public class Dispatch +{ + private static var _onceTracker = [String]() + + public class func once(file: String = #file, + function: String = #function, + line: Int = #line, + block: () -> Void) { + let token = "\(file):\(function):\(line)" + once(token: token, block: block) + } + + /** + Executes a block of code, associated with a unique token, only once. The code is thread safe and will + only execute the code once even in the presence of multithreaded calls. + + - parameter token: A unique reverse DNS style name such as com.vectorform. or a GUID + - parameter block: Block to execute once + */ + public class func once(token: String, + block: () -> Void) { + objc_sync_enter(self) + defer { objc_sync_exit(self) } + + guard !_onceTracker.contains(token) else { return } + + _onceTracker.append(token) + block() + } +} From 978f88d1ca05b7296c744798b5d729ac5c802385 Mon Sep 17 00:00:00 2001 From: Evan Bacon Date: Thu, 28 May 2020 14:20:04 -0700 Subject: [PATCH 3/3] Update AppDelegate.swift --- apps/bare-expo/ios/BareExpo/AppDelegate.swift | 4 ---- 1 file changed, 4 deletions(-) diff --git a/apps/bare-expo/ios/BareExpo/AppDelegate.swift b/apps/bare-expo/ios/BareExpo/AppDelegate.swift index 69e5890c4327b..235e16e357daf 100644 --- a/apps/bare-expo/ios/BareExpo/AppDelegate.swift +++ b/apps/bare-expo/ios/BareExpo/AppDelegate.swift @@ -50,9 +50,6 @@ class AppDelegate: UMAppDelegateWrapper { // https://github.com/expo/react-native/commit/7f2912e8005ea6e81c45935241081153b822b988 func ensureReactMethodSwizzlingSetUp() { Dispatch.once { - - //#pragma clang diagnostic push - //#pragma clang diagnostic ignored "-Wundeclared-selector" // RCTKeyCommands.m // swizzle UIResponder RCTSwapInstanceMethods(UIResponder.self, @@ -66,7 +63,6 @@ class AppDelegate: UMAppDelegateWrapper { RCTSwapInstanceMethods(UIWindow.self, #selector(UIResponder.motionEnded(_:with:)), Selector(("RCT_motionEnded:withEvent:"))) - //#pragma clang diagnostic pop } } }