The error I am getting is the following.
Thread 1: "Unsupported object <CPInformationTemplate: 0x6000012de010> <identifier: 3444D3F1-ECFF-4953-B543-459286E11371, userInfo: (null), tabTitle: (null), tabImage: (null), showsTabBadge: 0> passed to setRootTemplate:animated:completion:. Allowed classes: {(\n CPTabBarTemplate,\n CPListTemplate,\n CPGridTemplate,\n CPAlertTemplate,\n CPVoiceControlTemplate,\n CPNowPlayingTemplate\n)}"
All I am trying to do so, far is show a simple basic text. - I am following https://adapptor.com.au/blog/enhance-existing-apps-with-carplay
Any suggestions would be helpful.
import Foundation
import CarPlay
class CarPlaySceneDelegate: UIResponder, CPTemplateApplicationSceneDelegate {
func templateApplicationScene(_ templateApplicationScene: CPTemplateApplicationScene,
didConnect interfaceController: CPInterfaceController) {
if #available(iOS 14.0, *) {
let screen = CPInformationTemplate(title: "Root", layout: .leading, items: [CPInformationItem(title: "Hello", detail: "CarPlay")], actions: [])
interfaceController.setRootTemplate(screen, animated: true, completion: { _,_ in
// Do nothing
})
} else {
// Fallback on earlier versions
}
}
}
My AppDelegate is:
//
// AppDelegate.swift
// vscroll
//
// Created by Russell Harrower on 17/8/20.
// Copyright © 2020 Russell Harrower. All rights reserved.
//
import UIKit
import Flurry_iOS_SDK
import AVKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
MusicPlayer.shared.startBackgroundMusic(url:"https://api.drn1.com.au:9000/station/DRN1", type: "radio")
setupNotifications()
Flurry.startSession("GJV665GWWF25GPCD25W8", with: FlurrySessionBuilder
.init()
.withCrashReporting(true)
.withLogLevel(FlurryLogLevelAll))
return true
}
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
if(connectingSceneSession.role == UISceneSession.Role.carTemplateApplication) {
let scene = UISceneConfiguration(name: "CarPlay", sessionRole: connectingSceneSession.role)
// At the time of writing this blog post there seems to be a bug with the info.plist file where
// the delegateClass isn't set correctly. So we manually set it here.
if #available(iOS 14.0, *) {
scene.delegateClass = CarPlaySceneDelegate.self
} else {
// Fallback on earlier versions
}
return scene
} else {
let scene = UISceneConfiguration(name: "Phone", sessionRole: connectingSceneSession.role)
return scene
}
}
// MARK: UISceneSession Lifecycle
/* func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}*/
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
//CUSTOM CODE
func setupNotifications() {
// Get the default notification center instance.
let nc = NotificationCenter.default
nc.addObserver(self,
selector: #selector(handleInterruption),
name: AVAudioSession.interruptionNotification,
object: nil)
}
#objc func handleInterruption(notification: Notification) {
guard let userInfo = notification.userInfo,
let interruptionTypeRawValue = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt,
let interruptionType = AVAudioSession.InterruptionType(rawValue: interruptionTypeRawValue) else {
return
}
switch interruptionType {
case .began:
print("interruption began")
case .ended:
MusicPlayer.shared.player?.play()
print("interruption ended")
default:
print("UNKNOWN")
}
}
}
Which entitlements you have defined in your project? The templates availability depends on defined app entitlements.
Usage of the unsupported template (CPInformationTemplate) cause your error.
For example from documentation:
You can’t use CPInformationTemplate in apps with the audio
entitlement.
Related
I am new to Xcode and I am working on my Google sign-in project. After successfully logging in with google, I cannot find the user profile in firebase. I think I am missing the code for uploading user credentials to firebase. I can barely understand the documentation and I don't know what to do. By the way, how can I navigate to another view controller after signing in? I tried lots of ways but none of them work. Any help is appreciated.
My AppDelegate code:
import UIKit
import Firebase
import GoogleSignIn
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, GIDSignInDelegate{
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
GIDSignIn.sharedInstance()?.clientID = "//I have it in my actual code"
GIDSignIn.sharedInstance()?.delegate = self
return true
}
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
if let error = error {
print(error)
return
}
guard
let authentication = user?.authentication,
let idToken = authentication.idToken
else {
return
}
let credential = GoogleAuthProvider.credential(withIDToken: idToken,
accessToken: authentication.accessToken)
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
return GIDSignIn.sharedInstance().handle(url)
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
}
The code of the log-in view controller
import UIKit
import GoogleSignIn
class WelcomeViewController: UIViewController {
#IBOutlet weak var gooleButton: GIDSignInButton!
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
GIDSignIn.sharedInstance()?.presentingViewController = self
gooleButton.style = .wide
gooleButton.colorScheme = .dark
}
}
From what I see your code signs the user in with Google to get the credentials, but then doesn't call signIn(with: ) which is needed in order to sign in to Firebase Authentication.
Have a look at Step 3: authenticate with Firebase. While the code there looks a bit intimidating, that's mostly because it handled many different cases. At its minimum you can sign in to Firebase with your credentials by doing:
Auth.auth().signIn(with: credential) { authResult, error in
if let error = error {
let authError = error as NSError
print(error.localizedDescription)
return
}
// User is signed in
// ...
}
How can I go to another view controller after successfully signing with google? I've tried "self.inputViewController?.performSegue(withIdentifier: "goToMain", sender: self)" in my App Delegate but not getting any respond. Am I supposed to add the method in App Delegate or the view controller with the sign-in button?
App Delegate
import UIKit
import Firebase
import GoogleSignIn
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, GIDSignInDelegate{
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
GIDSignIn.sharedInstance()?.clientID = "my_client_id"
GIDSignIn.sharedInstance()?.delegate = self
return true
}
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
if let error = error {
print(error)
return
}
guard
let authentication = user?.authentication,
let idToken = authentication.idToken
else {
return
}
let credential = GoogleAuthProvider.credential(withIDToken: idToken,
accessToken: authentication.accessToken)
Auth.auth().signIn(with: credential) { authResult, error in
if let error = error {
let authError = error as NSError
print(authError.localizedDescription)
return
}
self.inputViewController?.performSegue(withIdentifier: "goToMain", sender: self)
}
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
return GIDSignIn.sharedInstance().handle(url)
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
}
Are you sure about the inputViewController is not nil? This may a reason for not working.
You can add a function to test this, or you can use the print function to check, or, you can use debug point to check inputViewController is nil or not.
I'd like to add comment but I don't have enough reputation point :).
Good luck.
I am following this tutorial from Firebase to implement Direct Links into my app: Firebase Dynamic Links
My code in my app delegate never seems to run properly. When I run the project I am able to use the link and open the app. But none of the print statements will run so I can't tell if it ran successfully or not:
import UIKit
import Firebase
#main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
FirebaseApp.configure()
return true
}
func handleincomingDynamicLink(_ dynamicLink: DynamicLink) {
guard let url = dynamicLink.url else {
print("Thats weird. My dynamic object link has no url")
return
}
print("Your incoming link parameter is \(url.absoluteString)")
}
func application(_ application: UIApplication, continue userActivity: NSUserActivity,
restorationHandler: #escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
let handled = DynamicLinks.dynamicLinks()
.handleUniversalLink(userActivity.webpageURL!) { dynamiclink, error in
guard error == nil else {
print("Found an error! \(error!.localizedDescription)")
return
}
if let dynamicLink = dynamiclink {
self.handleincomingDynamicLink(dynamicLink)
}
}
return handled
}
#available(iOS 9.0, *)
func application(_ app: UIApplication, open url: URL,
options: [UIApplication.OpenURLOptionsKey: Any]) -> Bool {
return application(app, open: url,
sourceApplication: options[UIApplication.OpenURLOptionsKey
.sourceApplication] as? String,
annotation: "")
}
func application(_ application: UIApplication, open url: URL, sourceApplication: String?,
annotation: Any) -> Bool {
if let dynamicLink = DynamicLinks.dynamicLinks().dynamicLink(fromCustomSchemeURL: url) {
return true
}
return false
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
}
Xcode gives me this error after I use the link:
[connection] nw_read_request_report [C1] Receive failed with error "Software caused connection abort"
use below delegate method in SceneDelegate Class:
func scene(_ scene: UIScene, continue userActivity: NSUserActivity)
Using Firebase Dynamic Links, I want to be able to click a link to open an iOS app.
The app is under development and is not yet on the AppStore.
I set it while looking at the document, but even if the app is started by clicking the link, the application (_: continue: restorationHandler :) method in AppDelegate is not called.
I set it according to the following procedure. Is something wrong?
Add "pod 'Firebase / DynamicLinks'" to Podfile and install
Open the .xcworkspace file
Create Dynamic Links “https://XXXX.page.link/test”
Access “https://XXXX.page.link/apple-app-site-association”
{"applinks":{"apps":[],"details":[{"appID":"XXXXXXX.[Bundle
ID]","paths":["NOT /_/","/"]}]}}
Create a URL type to use for dynamic links
Enable "Associated Domains" and add "applinks: XXXX.page.link"
Implement AppDelegate as below
import UIKit
import Firebase
import FirebaseDynamicLinks
#UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
FirebaseApp.configure()
return true
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
func application(_ application: UIApplication, continue userActivity: NSUserActivity,
restorationHandler: #escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
let handled = DynamicLinks.dynamicLinks().handleUniversalLink(userActivity.webpageURL!) { (dynamiclink, error) in
// ...
}
return handled
}
#available(iOS 9.0, *)
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool {
return application(app, open: url,
sourceApplication: options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String,
annotation: "")
}
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
if let dynamicLink = DynamicLinks.dynamicLinks().dynamicLink(fromCustomSchemeURL: url) {
// Handle the deep link. For example, show the deep-linked content or
// apply a promotional offer to the user's account.
// ...
return true
}
return false
}
}
I was calling the scene method of SceneDelegate.
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
// Create the SwiftUI view that provides the window contents.
let rootView = ContentView()
// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: rootView)
self.window = window
window.makeKeyAndVisible()
}
guard let userActivity = connectionOptions.userActivities.first(where: { $0.webpageURL != nil }) else { return }
print("url: \(userActivity.webpageURL!)")
}
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
print("url: \(userActivity.webpageURL!)")
}
...
}
Implementation should be in SceneDelgate instead of AppDelegate
I can't seem to resolve this issue. I went in and deleted all parse and fb SDKs and then downloaded the newest parse and fb SDKs and put into project.
Still getting this error in logs. Don't even get to fb screen. Below is my code. I have researched all instances of this issue and yet no resolve. I am missing something.
AppDelegate.swift:
import UIKit
import Parse
import ParseFacebookUtilsV4
import Bolts
// If you want to use any of the UI components, uncomment this line
// import ParseUI
// If you want to use Crash Reporting - uncomment this line
// import ParseCrashReporting
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
//--------------------------------------
// MARK: - UIApplicationDelegate
//--------------------------------------
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Enable storing and querying data from Local Datastore.
// Remove this line if you don't want to use Local Datastore features or want to use cachePolicy.
Parse.enableLocalDatastore()
let parseConfiguration = ParseClientConfiguration(block: { (ParseMutableClientConfiguration) -> Void in
ParseMutableClientConfiguration.applicationId = "xxx"
ParseMutableClientConfiguration.clientKey = "xxx"
ParseMutableClientConfiguration.server = "https://yourapp.herokuapp.com/parse"
})
Parse.initializeWithConfiguration(parseConfiguration)
PFFacebookUtils.initializeFacebookWithApplicationLaunchOptions(launchOptions)
PFUser.enableAutomaticUser()
let defaultACL = PFACL();
// If you would like all objects to be private by default, remove this line.
defaultACL.publicReadAccess = true
PFACL.setDefaultACL(defaultACL, withAccessForCurrentUser:true)
if application.applicationState != UIApplicationState.Background {
// Track an app open here if we launch with a push, unless
// "content_available" was used to trigger a background push (introduced in iOS 7).
// In that case, we skip tracking here to avoid double counting the app-open.
let preBackgroundPush = !application.respondsToSelector("backgroundRefreshStatus")
let oldPushHandlerOnly = !self.respondsToSelector("application:didReceiveRemoteNotification:fetchCompletionHandler:")
var noPushPayload = false;
if let options = launchOptions {
noPushPayload = options[UIApplicationLaunchOptionsRemoteNotificationKey] != nil;
}
if (preBackgroundPush || oldPushHandlerOnly || noPushPayload) {
PFAnalytics.trackAppOpenedWithLaunchOptions(launchOptions)
}
}
if application.respondsToSelector("registerUserNotificationSettings:") {
let settings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
application.registerUserNotificationSettings(settings)
application.registerForRemoteNotifications()
} else {
let types: UIRemoteNotificationType = [UIRemoteNotificationType.Badge, UIRemoteNotificationType.Alert, UIRemoteNotificationType.Sound]
application.registerForRemoteNotificationTypes(types)
}
return FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
}
//--------------------------------------
// MARK: Push Notifications
//--------------------------------------
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
let installation = PFInstallation.currentInstallation()
installation.setDeviceTokenFromData(deviceToken)
installation.saveInBackground()
PFPush.subscribeToChannelInBackground("") { (succeeded, error) in
if succeeded {
print("ParseStarterProject successfully subscribed to push notifications on the broadcast channel.");
} else {
print("ParseStarterProject failed to subscribe to push notifications on the broadcast channel with error = %#.", error)
}
}
}
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
if error.code == 3010 {
print("Push notifications are not supported in the iOS Simulator.")
} else {
print("application:didFailToRegisterForRemoteNotificationsWithError: %#", error)
}
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
PFPush.handlePush(userInfo)
if application.applicationState == UIApplicationState.Inactive {
PFAnalytics.trackAppOpenedWithRemoteNotificationPayload(userInfo)
}
}
func application(application: UIApplication,
openURL url: NSURL,
sourceApplication: String?,
annotation: AnyObject) -> Bool {
return FBSDKApplicationDelegate.sharedInstance().application(application, openURL: url, sourceApplication: sourceApplication, annotation: annotation)
}
func applicationDidBecomeActive(application: UIApplication) {
FBSDKAppEvents.activateApp()
}
}
ViewController.swift:
import UIKit
import Parse
import FBSDKCoreKit
import FBSDKLoginKit
import ParseFacebookUtilsV4
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// array of what we want to get from the fb user account
let permissions = ["public_profile"]
PFFacebookUtils.logInInBackgroundWithReadPermissions(permissions) {
(user: PFUser?, error: NSError?) -> Void in
if let error = error { // if error exists
print(error)
} else {
if let user = user { // if user exists
print(user)
}
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}