viewController.title is nil after init of Google a

2019-09-17 09:36发布

问题:

I followed Google analytics doc to add it to my swift app

I have done all that is said there, and yet my code fails in run time.

Here is my code in AppDelegate:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
    loadGoogleAnalytics()
    chooseAndLuanchStoryboard()
    initMembersAfterViewControllerInit()
    return true
}

func loadGoogleAnalytics()
{
    // Configure tracker from GoogleService-Info.plist.
    var configureError:NSError?
    GGLContext.sharedInstance().configureWithError(&configureError)
    assert(configureError == nil, "Error configuring Google services: \(configureError)")

    // Optional: configure GAI options.
    let gai = GAI.sharedInstance()
    gai.trackUncaughtExceptions = true  // report uncaught exceptions
    gai.logger.logLevel = GAILogLevel.Error
}

Here is my code in the ViewController:

override public func viewWillAppear(animated: Bool) {
    super.viewWillAppear(true)

    let name = "Pattern~\(self.title!)"

    // The UA-XXXXX-Y tracker ID is loaded automatically from the
    // GoogleService-Info.plist by the `GGLContext` in the AppDelegate.
    // If you're copying this to an app just using Analytics, you'll
    // need to configure your tracking ID here.
    // [START screen_view_hit_swift]
    let tracker = GAI.sharedInstance().defaultTracker
    tracker.set(kGAIScreenName, value: name)

    let builder = GAIDictionaryBuilder.createScreenView()
    tracker.send(builder.build() as [NSObject : AnyObject])
    // [END screen_view_hit_swift]
}

override public func viewWillDisappear(animated: Bool) {
    keyboardManager.deregisterFromKeyboardNotifications()
    stopRefreshTimer()
}

I get this run-time error because self.title in let name = "Pattern~\(self.title!)" is nil

2016-02-05 19:44:44.377 Inline[95803:3750273] The configuration file 'GoogleService-Info.plist' is for another bundle identifier ('com.Inline.inline-ios'). Using this file the services may not be configured correctly. To continue with this configuration file, you may change your app's bundle identifier to 'com.Inline.inline-ios'. Or you can download a new configuration file that matches your bundle identifier from https://developers.google.com/mobile/add and replace the current one.
2016-02-05 19:44:44.383 Inline[95803:] <GMR/INFO> App measurement v.1302000 started
2016-02-05 19:44:44.384 Inline[95803:] <GMR/INFO> To enable debug logging set the following application argument: -GMRDebugEnabled (see http://goo.gl/Y0Yjwu)
2016-02-05 19:44:45.999 Inline[95803:] <GMR/INFO> App measurement enabled
2016-02-05 19:44:46.034 Inline[95803:3750273] Unknown class logo in Interface Builder file.
2016-02-05 19:44:46.048 Inline[95803:3750273] Failed to set (keyPath) user defined inspected property on (UIView): [<UIView 0x7faf9a079730> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key keyPath.
2016-02-05 19:44:46.048 Inline[95803:3750273] Failed to set (keyPath) user defined inspected property on (UIView): [<UIView 0x7faf9a0729a0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key keyPath.
2016-02-05 19:44:46.048 Inline[95803:3750273] Failed to set (keyPath) user defined inspected property on (UIView): [<UIView 0x7faf9a07f8b0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key keyPath.
2016-02-05 19:44:46.051 Inline[95803:3750273] Device ID: (null)
2016-02-05 19:44:46.051 Inline[95803:3750273] RegisterDevice RPC request
scanning for beacons
fatal error: unexpectedly found nil while unwrapping an Optional value

how can I make the self.title be non-nil?

回答1:

Init on didFinishLaunchingWithOptions

let gai = GAI.sharedInstance()
let id = "UA-ID"
gai.trackerWithTrackingId(id)
gai.trackUncaughtExceptions = true
gai.logger.logLevel = GAILogLevel.Warning
gai.defaultTracker.allowIDFACollection = false

Easy way to call google analytics via setScreenName on viewDidAppear.

extension UIViewController {
    func setScreeName(name: String) {
        self.title = name
        self.sendScreenView()
    }

    func sendScreenView() {
        let tracker = GAI.sharedInstance().defaultTracker
        tracker.set(kGAIScreenName, value: self.title)
        let builder = GAIDictionaryBuilder.createScreenView()
        tracker.send(builder.build() as [NSObject : AnyObject])
    }

    func trackEvent(category: String, action: String, label: String, value: NSNumber?) {
        let tracker = GAI.sharedInstance().defaultTracker
        let trackDictionary = GAIDictionaryBuilder.createEventWithCategory(category, action: action, label: label, value: value)
        tracker.send(trackDictionary.build() as [NSObject : AnyObject])
    }
}


回答2:

I have a same issue and found out that defaultTracker property makes trouble.

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(true)

    // I called trackerWithTrackingId method in AppDelegate, 
    // but defaultTracker value could be nil.
    // So, you got a error message like this :
    // fatal error: unexpectedly found nil while unwrapping an Optional value
    // According to google analytics documents, trackerWithTrackingId has an
    // initial value with nil, and then will be set with return value
    // from trackerWithTrackingId method call. 
    // But it doesn't look work well sometimes.

    if let default_tracker = GAI.sharedInstance().defaultTracker {
        #if DEBUG

            print("default tracker")

        #endif
    }

    // Instead of defaultTracker, use trackerWithTrackingId method
    // it will return a new tracker(=create) or the existing tracker  
    let tracker = GAI.sharedInstance().trackerWithTrackingId("tracking-ID")
    tracker.set(kGAIScreenName, value: "ViewController")

    let builder = GAIDictionaryBuilder.createScreenView()
    tracker.send(builder.build() as [NSObject : AnyObject])
}

Interestingly, the default tracker works well in AppDelegate.

    let tracker = GAI.sharedInstance().trackerWithTrackingId("tracking-ID")
    GAI.sharedInstance().trackUncaughtExceptions = true;
    GAI.sharedInstance().dispatchInterval = 20
    GAI.sharedInstance().logger.logLevel = .Warning //.Verbose


    let firstTracker = GAI.sharedInstance().defaultTracker

    if tracker.isEqual(firstTracker) {
        #if DEBUG

            print("same Tracker")

        #endif
    } 

My project Env

  • Podfile

pod 'GoogleAnalytics'

  • Bridging-Header.h
#import <GoogleAnalytics/GAI.h>
#import <GoogleAnalytics/GAIFields.h>
#import <GoogleAnalytics/GAILogger.h>
#import <GoogleAnalytics/GAIDictionaryBuilder.h>
#import <GoogleAnalytics/GAITrackedViewController.h>
#import <GoogleAnalytics/GAITracker.h>

I use Google Analytics with CocoaPods but can not follow instructions in google analytics for swift. Because I don't want to add GoogleService-Info.plist in my project.



回答3:

When using

let name = "Pattern~\(self.title!)"

for your tracking, make sure you have the View Controller Title set either in code or in Interface Builder: