Description
Hey! I cannot understand why I am having so much difficulty getting this library setup for IOS. I got it working with minimal effort on my part for Android. This issue is happening after I followed meticulously what the documentations say on setting up for IOS, but to no avail. What could I possibly be doing wrong. FYI, I'm trying very hard to use this library with my Expo project even though this is a bare bones React Native library and it was not built for this use case. However, I feel like I am getting very close. I am fully aware that this library has been transitioning from Objective-C in favor of Swift for much of the code base, however I since I am trying to keep my App stable being that it uses a lot of Expo, I would like to keep it in Objective-C if possible.
Here is the error output:
⚠️ ld: Could not find or use auto-linked framework 'CoreAudioTypes': framework 'CoreAudioTypes' not found
❌ clang: error: linker command failed with exit code 1 (use -v to see invocation)
Here is my relevant project folder layout and code:
.
└── ./ios/
├── ./ios/build/
├── ./ios/Pods/
├── ./ios/MyProject/
│ ├── ./ios/MyProject/Images.xcassets/
│ ├── ./ios/MyProject/Supporting/
│ ├── ./ios/MyProject/AppDelegate.h
│ ├── ./ios/MyProject/AppDelegate.mm
│ ├── ./ios/MyProject/CarSceneDelegate.h
│ ├── ./ios/MyProject/CarSceneDelegate.m
│ ├── ./ios/MyProject/Info.plist
│ ├── ./ios/MyProject/main.m
│ ├── ./ios/MyProject/noop-file.swift
│ ├── ./ios/MyProject/PhoneSceneDelegate.h
│ ├── ./ios/MyProject/PhoneSceneDelegate.m
│ ├── ./ios/MyProject/SplashScreen.storyboard
│ ├── ./ios/MyProject/MyProject-Bridging-Header.h
│ └── ./ios/MyProject/MyProject.entitlements
├── ./ios/MyProject.xcodeproj/
├── ./ios/MyProject.xcworkspace/
└── ./ios/Other Files
AppDelegate.h
#import <Foundation/Foundation.h>
#import <React/RCTBridgeDelegate.h>
#import <RCTAppDelegate.h>
#import <UIKit/UIKit.h>
#import <Expo/Expo.h>
#import <CarPlay/CarPlay.h>
@interface AppDelegate : EXAppDelegateWrapper <RCTBridgeDelegate, UIApplicationDelegate, CPApplicationDelegate>
@property (nonatomic, strong) UIWindow *window;
@property (nonatomic, strong) UIView *rootView;
@property (nonatomic, strong) RCTBridge *bridge;
- (void)initAppFromSceneWithConnectionOptions:(UISceneConnectionOptions *)connectionOptions;
@end
AppDelegate.mm
#import <RNCarPlay.h>
#import <React/RCTBridge.h>
#import <React/RCTRootView.h>
#import <Firebase/Firebase.h>
#import "CarSceneDelegate.h"
#import "PhoneSceneDelegate.h"
#import "AppDelegate.h"
#import <React/RCTBundleURLProvider.h>
#import <React/RCTLinkingManager.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// @generated begin @react-native-firebase/app-didFinishLaunchingWithOptions - expo prebuild (DO NOT MODIFY) sync-ecd111c37e49fdd1ed6354203cd6b1e2a38cccda
[FIRApp configure];
// @generated end @react-native-firebase/app-didFinishLaunchingWithOptions
self.moduleName = @"main";
// You can add your custom initial props in the dictionary below.
// They will be passed down to the ViewController used by React Native.
self.initialProps = @{};
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
return [self getBundleURL];
}
- (NSURL *)getBundleURL
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@".expo/.virtual-metro-entry"];
#else
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}
// Linking API
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
return [super application:application openURL:url options:options] || [RCTLinkingManager application:application openURL:url options:options];
}
// Universal Links
- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {
BOOL result = [RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
return [super application:application continueUserActivity:userActivity restorationHandler:restorationHandler] || result;
}
// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
return [super application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
return [super application:application didFailToRegisterForRemoteNotificationsWithError:error];
}
// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
return [super application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
if (@available(iOS 13.0, *)) {
if (connectingSceneSession.role == CPTemplateApplicationSceneSessionRoleApplication) {
UISceneConfiguration *scene = [[UISceneConfiguration alloc] initWithName:@"CarPlay" sessionRole:connectingSceneSession.role];
scene.delegateClass = [CarSceneDelegate class];
return scene;
} else {
UISceneConfiguration *scene = [[UISceneConfiguration alloc] initWithName:@"Phone" sessionRole:connectingSceneSession.role];
scene.delegateClass = [PhoneSceneDelegate class];
return scene;
}
} else {
return nil;
}
}
- (UIView *)rootView {
if (!_rootView) {
if (!self.bridge) {
self.bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:nil];
}
_rootView = [[RCTRootView alloc] initWithBridge:self.bridge
moduleName:@"main"
initialProperties:nil];
}
return _rootView;
}
- (void)initAppFromSceneWithConnectionOptions:(UISceneConnectionOptions *)connectionOptions
{
if (!self.bridge) {
self.bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:[self connectionOptionsToLaunchOptions:connectionOptions]];
}
self.rootView = [self rootView];
}
- (NSDictionary *)connectionOptionsToLaunchOptions:(UISceneConnectionOptions *)connectionOptions
{
NSMutableDictionary *launchOptions = [NSMutableDictionary dictionary];
if (connectionOptions.notificationResponse) {
launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] = connectionOptions.notificationResponse.notification.request.content.userInfo;
}
if (connectionOptions.userActivities.count > 0) {
NSUserActivity *userActivity = connectionOptions.userActivities.allObjects.firstObject;
NSDictionary *userActivityDictionary = @{
@"UIApplicationLaunchOptionsUserActivityTypeKey": userActivity.activityType,
@"UIApplicationLaunchOptionsUserActivityKey": userActivity
};
launchOptions[UIApplicationLaunchOptionsUserActivityDictionaryKey] = userActivityDictionary;
}
return launchOptions;
}
- (void)application:(UIApplication *)application didConnectCarInterfaceController:(CPInterfaceController *)interfaceController toWindow:(CPWindow *)window {
[RNCarPlay connectWithInterfaceController:interfaceController window:window];
}
- (void)application:(nonnull UIApplication *)application didDisconnectCarInterfaceController:(nonnull CPInterfaceController *)interfaceController fromWindow:(nonnull CPWindow *)window {
[RNCarPlay disconnect];
}
@end
CarSceneDelegate.h
#import <UIKit/UIKit.h>
#import <CarPlay/CarPlay.h>
@interface CarSceneDelegate : UIResponder <CPTemplateApplicationSceneDelegate>
@end
CarSceneDelegate
#import "CarSceneDelegate.h"
#import "AppDelegate.h"
#import <RNCarPlay.h>
@implementation CarSceneDelegate
- (void)templateApplicationScene:(CPTemplateApplicationScene *)templateApplicationScene
didConnectInterfaceController:(CPInterfaceController *)interfaceController {
AppDelegate *appDelegate = (AppDelegate *)UIApplication.sharedApplication.delegate;
[appDelegate initAppFromSceneWithConnectionOptions:templateApplicationScene.connectionOptions];
[RNCarPlay connectWithInterfaceController:interfaceController window:templateApplicationScene.carWindow];
}
- (void)templateApplicationScene:(CPTemplateApplicationScene *)templateApplicationScene
didDisconnectInterfaceController:(CPInterfaceController *)interfaceController {
[RNCarPlay disconnect];
}
@end
main.m
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
PhoneSceneDelegate.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface PhoneSceneDelegate : UIResponder <UIWindowSceneDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
PhoneSceneDelegate.m
#import "PhoneSceneDelegate.h"
#import "AppDelegate.h"
@implementation PhoneSceneDelegate
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
AppDelegate *appDelegate = (AppDelegate *)UIApplication.sharedApplication.delegate;
UIWindowScene *windowScene = (UIWindowScene *)scene;
[appDelegate initAppFromSceneWithConnectionOptions:connectionOptions];
UIViewController *rootViewController = [[UIViewController alloc] init];
rootViewController.view = appDelegate.rootView;
UIWindow *window = [[UIWindow alloc] initWithWindowScene:windowScene];
window.rootViewController = rootViewController;
self.window = window;
[window makeKeyAndVisible];
}
@end
To Reproduce
Try building the project with my configuration for IOS.
Expected behavior
To build successfully for IOS.
Screenshots/Videos
If applicable, add screenshots to help explain your problem.
CarPlay (please complete the following information):
- Device: iPhone 13 mini simulator
- OS version IOS 15.5
- RNCarPlay version 2.4.0-beta.2
Additional context
I have the following Apple entitlements:
"com.apple.developer.carplay-audio": true,
"com.apple.developer.playable-content": true
Activity