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..96ed64e2ac7eb 100644 --- a/apps/bare-expo/ios/BareExpo.xcodeproj/project.pbxproj +++ b/apps/bare-expo/ios/BareExpo.xcodeproj/project.pbxproj @@ -8,13 +8,13 @@ /* 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 */; }; + 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 */ @@ -35,12 +35,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,7 +45,10 @@ 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; }; + 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; }; @@ -95,15 +95,15 @@ 13B07FAE1A68108700A75B9A /* BareExpo */ = { isa = PBXGroup; children = ( + CD59639B247F2EFA0030EECA /* AppDelegate.swift */, + CDDB247B24802C4C00F6E7AC /* Dispatch.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 +223,7 @@ }; 13B07F861A680F5B00A75B9A = { DevelopmentTeam = C8D8QTF339; + LastSwiftMigration = 1140; }; }; }; @@ -423,8 +424,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, - 13B07FC11A68108700A75B9A /* main.m in Sources */, + CD59639C247F2EFA0030EECA /* AppDelegate.swift in Sources */, + CDDB247C24802C4C00F6E7AC /* Dispatch.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -455,6 +456,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 +480,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 +502,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 +514,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 +530,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 +544,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..235e16e357daf --- /dev/null +++ b/apps/bare-expo/ios/BareExpo/AppDelegate.swift @@ -0,0 +1,93 @@ +// +// 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 moduleRegistryAdapter: UMModuleRegistryAdapter! + + override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + + ensureReactMethodSwizzlingSetUp() + + moduleRegistryAdapter = UMModuleRegistryAdapter(moduleRegistryProvider: UMModuleRegistryProvider()) + + 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) + + return true + } + + #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) + } + + // 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 { + // 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:"))) + } + } +} + +// 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() + } +} 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])); - } -}