Implement Google Analytics in ios swift - ios

I am following the Analytics for iOS (developers.google.com/analytics/devguides/collection/ios/v3/?ver=swift) guide and I've got errors in my Swift code Project that I can't fix.
I am working with XCode 6.4, Swift and the iOS Deployment Target 8.1.
Step 1
First I installed a Google SDK using CocoaPods.
This is the console result after running pod install command:
Updating local specs repositories
CocoaPods 1.0.0.beta.2 is available.
To update use: `gem install cocoapods --pre`
[!] This is a test version we'd love you to try.
For more information see http://blog.cocoapods.org
and the CHANGELOG for this version http://git.io/BaH8pQ.
Analyzing dependencies
Downloading dependencies
Using Google (1.0.7)
Using GoogleAnalytics (3.14.0)
Using GoogleNetworkingUtilities (1.0.0)
Using GoogleSymbolUtilities (1.0.3)
Using GoogleUtilities (1.1.0)
Generating Pods project
Integrating client project
Sending stats
Pod installation complete! There is 1 dependency from the
Podfile and 5 total pods installed.
Step 2
Then opened, as said in the guide, my app's Project .xcworkspace file.
My Podfile looks like this:
# Uncomment this line to define a global platform for your project
# platform :ios, '8.0'
# Uncomment this line if you're using Swift
# use_frameworks!
target 'XXXXXX' do
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.1'
pod 'Google/Analytics', '~> 1.0.0'
end
target 'XXXXXXTests' do
pod 'Google/Analytics', '~> 1.0.0'
end
Where XXXXXX is my Project's name.
Step 3
I got the configuration file GoogleService-Info.plist and included in my Project adding all the targets (2 targets in my project).
Step 4
I created a BridgingHeader by by choosing File > New > File > iOS > Source > Header File.
I named it BridgingHeader.h and is in the root of my Project.
The content is:
#ifndef XXXXX_BridgingHeader_h
#define XXXXX_BridgingHeader_h
#import "Google/Analytics.h"
#import <Google/Analytics.h>
#include "GAI.h"
#import <CoreData/CoreData.h>
#import <SystemConfiguration/SystemConfiguration.h>
#import "Libraries/GoogleAnalytics/GAI.h"
#import "Libraries/GoogleAnalytics/GAIFields.h"
#import "Libraries/GoogleAnalytics/GAILogger.h"
#import "Libraries/GoogleAnalytics/GAITracker.h"
#import "Libraries/GoogleAnalytics/GAIDictionaryBuilder.h"
#endif
Where "XXXXX" is my Project's name.
Step 5
Now the problems:
I tried to include/import the Google Analytics into my AppDelegate.swift but I can't. This is the error:
AppDelegate.swift import Google Analytics
I also tried import "Google/Analytics.h" but another error appears: Expected identifier in import declaration.
How can I fix this so XCode doesn't give me errors?
Is the BridgingHeader wrong? Do I have to point at this somehow to recognize its inner headers?
Do I have to configure something else for the Google Analytics that I am missing right now?
Thank you very much.

There are two options for implementation with Google Analytics using CocoaPods.
pod 'Google/Analytics'
pod 'GoogleAnalytics'
There are pros and cons between them.
pod 'Google/Analytics'
need google configuration file(GoogleService-Info.plist)
simple bridging header file. Just add #import <Google/Analytics.h> in bridging header file.
add import Googlein every file you want to implement google analytics.
pod 'GoogleAnalytics'
no google configuration file(GoogleService-Info.plist)
more complex bridging header file.
I prefer to use pod 'GoogleAnalytics' but I'll explain how to solve this issue using pod 'Google/Analytics'
because the google official site recommends pod 'Google/Analytics'.
bridging header
You just need one line of code for google analytics.
#import <Google/Analytics.h>
Don't forget to set target-build setting for Objective-C-Bridging-Header.
You have to provide correct path to enable Objective-C-Bridging-Header.
Set Target-Build Setting-Objective-C-Bridging-Header
$(SRCROOT)/$(PRODUCT_NAME)/projectName_Bridging_Header.h
AppDelegate.swift
import Google
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?)
-> Bool { self.setupGoogleAnalytics()
..
self.setupGoogleAnalytics()
..
}
func setupGoogleAnalytics() {
// Configure tracker from GoogleService-Info.plist.
let configureError:NSError?
GGLContext.sharedInstance().configureWithError(&configureError)
assert(configureError == nil, "Error configuring Google services: \(configureError)")
let gai = GAI.sharedInstance()
gai.trackUncaughtExceptions = true // report uncaught exceptions
gai.logger.logLevel = GAILogLevel.Verbose // remove before app release
}
SomeViewController.swift
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
if let default_tracker = GAI.sharedInstance().defaultTracker {
#if DEBUG
print("default tracker")
#endif
}
// let tracker = GAI.sharedInstance().defaultTracker
let tracker = GAI.sharedInstance().trackerWithTrackingId("tracking_ID")
tracker.set(kGAIScreenName, value: screenName)
let builder = GAIDictionaryBuilder.createScreenView()
tracker.send(builder.build() as [NSObject : AnyObject])
}
Why do I use trackerWithTrackingId instead of defaultTracker property? You could got an error if you use defaultTracker :
fatal error: unexpectedly found nil while unwrapping an Optional value
defaultTracker property's initial value is nil, but it will be set after
trackerWithTrackingId method is called. But it doesn't work perfectly sometimes. To avoid this issue, I recommend that use trackerWithTrackingId method directly.
I make the sample project using pod 'GoogleAnalytics'. You can get an idea from it.
Good luck.
Test Env
GoogleAnalytics 3.14
Xcode 7.2.1

In Podfile
pod 'Google/Analytics'
In YourFantasticProjectName-Bridging-Header.h
#import "Google/Analytics.h"
You don't need this
GGLContext.sharedInstance().configureWithError(&configureError)
You need to have a proper tracker
let gai = GAI.sharedInstance()
let tracker = gai.tracker(withTrackingId: "UA-12345678-1")
In order for live view to work in GA dashboard, you must track screen using GAIDictionaryBuilder and correct key kGAIScreenName
tracker.set(kGAIScreenName, value: "this is my screen")
let event = GAIDictionaryBuilder.createScreenView()
tracker?.send(event!.build() as! [NSObject: Any])
In the same vein, to track events, you need to use GAIDictionaryBuilder as it will create dictionary with correct GA keys, and GA likes correct keys
let event = GAIDictionaryBuilder.createEvent(withCategory: "category", action: "action", label: "level", value: NSNumber(value: 120))
tracker?.send(event!.build() as! [NSObject: Any])
It seems to work in the simulator too

I faced the same problem. I could not import the "Google/Analytics.h" header as Xcode generate error. Because "Google/Analytics.h" header is not available in the 'GoogleAnalytics sdk' as mentioned in Google's Official page.
So, i just used following line
#import "GAI.h"
Hope it will work just fine.
Environment
Xcode: 8.2
iOS :10.2

For swift 3:
var configureError:NSError? = nil
GGLContext.sharedInstance().configureWithError(&configureError)
assert(configureError == nil, "Error configuring Google services: \(configureError)")
let gai = GAI.sharedInstance()
gai?.trackUncaughtExceptions = true
gai?.logger.logLevel = GAILogLevel.verbose

I think it's better to send error to crashlytics, but continue executing an app:
func configureGoogleAnalytics() {
var configureError: NSError? = nil
GGLContext.sharedInstance().configureWithError(&configureError)
if configureError != nil {
Crashlytics.sharedInstance().recordError(configureError!)
}
}
Also check this answer for newest way to add analytics.

Related

Firebase auth anonymous in Swift2

I am trying to integrate Firebase backend to my app.
Created my podfile with
pod 'Firebase'
Everything looks fine with the sdk import
In my first view controller I do:
import Firebase
override func viewDidLoad() {
super.viewDidLoad()
let ref = Firebase(url: "https://<YOUR-FIREBASE-APP>.firebaseio.com")
ref.authAnonymouslyWithCompletionBlock { error, authData in
if error != nil {
// There was an error logging in anonymously
} else {
// We are now logged in
}
}
}
But i got an Can not call value of non-function type error
Thanks in advance
So they have changed the way you install Firebase with pods, Now instead of just adding pod 'Firebase' you must add the individual pods like this.
use_frameworks!
target “Your Project” do
pod 'Firebase/Core’
pod 'Firebase/Database’
pod 'Firebase/Auth’
end
However, you only need to put 'import Firebase' and it will cover all pods relating to Firebase. And don't forget to configure Firebase in the didFinishLaunchingWithOptions method of your AppDelegate!
FIRApp.configure()
Good Luck!!

Firebase error with swift code

I have try everythng and I have imported pods to my project, done it several times in several new projects, but always get this error:
'Cannot call value of non-function type 'module'
Is it possible that my cocoa-pods are damaged somehow?
When I insert this code:
import Firebase
let BASE_URL = "my_project_url"
var FIREBASE_REF = FIRDatabase.database().reference()
I can see in Output/Debug window that I am connected with firebase, but when I start with code:
let BASE_URL = "my_project_url"
let FIREBASE_REF = Firebase(url: BASE_URL)
var CURRENT_USER: Firebase
{
let userID = NSUserDefaults.standardUserDefaults().valueForKey("uid") as! String
let currentUser = Firebase(url: "\(FIREBASE_REF)").childByAppendingPath("users").childByAppendingPath(userID)
return currentUser!
}
always get error. I have really try stuff from a lot tutorials, I tried a lot of things over past few days and nothing happened.
I have also look and read this topics, but did not help:
Cannot call value of non-function type 'module'
xcode error : Cannot call value of non-function type module Firebase
Unable to connect Firebase to my Xcode swift app?
I have open many new projects, done it import pod many times, I have import pod with insert in my pod file:
pod "Firebase"
and like this:
pod "Firebase"
pod "Firebase/Database"
also tried like this:
pod 'Firebase', '>= 2.5.1'
pod "Firebase/Database"
but always the same problem. Pods are inserted, I see Firebase folder and I know this is OK, so what could be wrong?
Like I said, I see that I am connected with Firebase in Debug window, as soon I start coding, error appears, and it is in every project like this, even when I try different approach and different code.
Any ideas?
You're either using the wrong version of Firebase, or following the wrong guide, depending on what you're trying to do.
Your pod config will install the latest version (3.2.1) while the code you've written is for 2.5.1 and before.

Bridge Google Drive API to Swift

From a previously removed post:
I am struggling to get the Google Drive API to work with Swift, and hoping someone has a suggestion. Here is where I am at so far: I have the Google Drive API installed and working in an Objective-C ...
I am trying to reproduce this example from Google in Swift, but import GTLDrive returns an error in Xcode:
No such module 'GTLDrive.
I am unable to use GTLServiceDrive from the Swift classes.
Which combination of CocoaPod + bridging header should I use?
You need 3 things:
(1) Well formed Podfile
platform :ios, '8.0'
target 'GoogleDrive' do
pod 'Google-API-Client/Drive', '~> 1.0'
end
(2) Expose Google API through the bridging headers
#import "GTMOAuth2ViewControllerTouch.h"
#import "GTLDrive.h"
(3) No reference GTLDrive required in the Swift client class
override func viewDidLoad() {
super.viewDidLoad()
// ...
let service:GTLServiceDrive = GTLServiceDrive()
service.authorizer = GTMOAuth2ViewControllerTouch.authForGoogleFromKeychainForName("Drive API",
clientID: "YOUR_CLIENT_ID_HERE",
clientSecret: "YOUR_CLIENT_SECRET_HERE")
// ...
}
I just ran into that now in XCode 7.3, and fixed it with the following in the bridging header:
#import <GoogleAPIClient/GTLDrive.h>
Also, if you need the authentication portion:
#import <GTMOAuth2/GTMOAuth2ViewControllerTouch.h>
I threw away Google API Objective C library from Swift altogether and created an interim solution: https://github.com/metaprgmr/GoogleApiProxyForSwift. Incidentally, I used Google Drive as a guinnea pig, where you can find experiments at close to the end of its YouTube presentation. Check it out.

Failed to recognize AWSDynamoDB with XCode 7.0 Beta, iOS 8.3, and aws-ios-sdk-2.2.0

I am matching guides for using AWSDynamoDB in a test project using Swift 2 in XCode 7.0 Beta. I am required to use that platform instead of the previous stable one and make it work.
I am using the next links:
https://docs.aws.amazon.com/mobile/sdkforios/developerguide/setup.html
http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LoadData_Java.html
Best way to make Amazon AWS DynamoDB queries using Swift?
I already made it work for reading and writing text files and images to an S3 Bucket, but now that I am trying to use DynamoDB service something might be missing.
Here is my Podfile contents:
# Uncomment this line to define a global platform for your project
platform :ios, '8.3'
target 'AWSSDKTest' do
source 'https://github.com/CocoaPods/Specs.git'
pod 'AWSCore'
pod 'AWSAutoScaling'
pod 'AWSCloudWatch'
pod 'AWSDynamoDB'
pod 'AWSEC2'
pod 'AWSElasticLoadBalancing'
pod 'AWSKinesis'
pod 'AWSLambda'
pod 'AWSMachineLearning'
pod 'AWSMobileAnalytics'
pod 'AWSS3'
pod 'AWSSES'
pod 'AWSSimpleDB'
pod 'AWSSNS'
pod 'AWSSQS'
pod 'AWSCognito'
end
target 'AWSSDKTestTests' do
end
I had to delete Podfile.lock and Pods folder, deleted Configuration Sets in Project->Info->Configurations, and installed pods again.
Here is my bridging.h file:
#ifndef AWSSDKTest_bridging_h
#define AWSSDKTest_bridging_h
#endif
#import <AWSCore/AWSCore.h>
#import <AWSS3/AWSS3.h>
#import <AWSDynamoDB/AWSDynamoDB.h>
#import <AWSSQS/AWSSQS.h>
#import <AWSSNS/AWSSNS.h>
#import <AWSCognito/AWSCognito.h>
I downloaded the aws-ios-sdk-2.2.0.zip file, unzipped and added to Frameworks all the AWS frameworks.
I am trying to use AWSDynamoDBModel, here is a swift file for implementing the Upload Sample Items Example for using DynamoDB Mapper:
import Foundation
class Forum : AWSDynamoDBModel, AWSDynamoDBModeling {
var name : String = ""
var category : String = ""
var threads : Int = 0
var messages : Int = 0
var views : Int = 0
// override init!() { super.init() }
required init!(coder: NSCoder!) {
fatalError("init(coder:) has not been implemented")
}
class func dynamoDBTableName() -> String! {
return "Demo"
}
class func hashKeyAttribute() -> String! {
return "email"
}
class func rangeKeyAttribute() -> String! {
return "date"
}
/*
override init(dictionary dictionaryValue: [NSObject : AnyObject]!, error: NSErrorPointer) {
super.init(dictionary: dictionaryValue, error: error)
}
override func isEqual(anObject: AnyObject?) -> Bool {
return super.isEqual(anObject)
}
*/
}
I had to comment the lines that caused error because those might be fixed. The errors mentioned that those functions couldnt be overridden and that super.init couldnt be called inside a root method.
After cleaning and building again, the error is at the class declaration line
class Forum : AWSDynamoDBModel, AWSDynamoDBModeling {
The error says: Use of undeclared type 'AWSDynamoDBModel'
If I try writing other AWSDynamoDB classes they don't appear in the list of suggestions and then cause the same error.
Additionally I want to mention that in the developer's guide setup (first link above) the 4th point of the Getting Started with Swift section says: "Import the AWSCore header in the application delegate":
#import <AWSCore/AWSCore.h>
Than can't be done, only in the bridging.h file which is mentioned in the 2nd point.
My first request of assistance is in fixing the error mentioned and making the project recognize the AWSDynamoDB framework.
Then I request your help for any observation about this merge of different tutorials, also any other online tutorial or guide that is more clear than those mentioned.
In case you are using CocoaPods (0.36) with "use_frameworks!", this answer might solve your problem:
"Normally when you’re importing Objective-C code into Swift, you do so by including the header of the file containing that code in the “Bridging Header” for your project. And that is indeed how you include code from a static library (which your pods used to be.)
But it is not how your import Objective-C code from a Framework. To do that you simply type…
import Framework
…inside your Swift file that’s using the Objective-C class (where “Framework” is the name of the actual Framework containing the class.)"
Source here: http://rogueleaderr.com/post/115372471213/unresolved-identifier-in-swift-when-importing
I think the problem is not related to Xcode7Beta, but the installation process of your project. (My sample DynamoDB project runs fine under Xcode7Beta.)
If you installed the AWS Mobile SDK via cocoapods, you neither have to worry about the bridging file nor need to download aws-ios-sdk-2.2.0.zip file since cocoapods already did everything for you.
My suggestion would be:
clean your project, remove all aws related frameworks, bridging files that you manually added,delete Podfile.lock and Pods folder and AWSSDKTest.xcworkspace file, and the re integrate pods by running "pod install"
Open your project using Xcode 6.4, confirm it can be built and run successfully under Xcode 6.
If everything looks good via Xcode 6, reopen it via Xcode7Beta, If it failed to compile, please post the error output so I can take a look.
Thanks

Unable to integrate ZXingObjC in a iOS Swift Project

Im working on an iOS project, which shows the customer number in a barcode. I had installed the framework ZXingObjC with CocoaPods, described in GitHub.
I can compile my Project without errors. I can also use the classes of ZXingObjC in my Objective-C classes, without errors. After than, I have added the import Command #import <ZXingObjC/ZXingObjC.h> to my bridging header file, like my other custom objective-c classes, without compile errors. (I had testet the header file by destroying some import statements and got the expected file not found exception.)
But now, I can't use any class of ZXingObjC in my swift classes. I only got the following compile error: Use of undeclared type '...'. The Xcode autocomplete is not working, too.
e.g.
var test : ZXMultiFormatWriter?
>> Use of undeclared type 'ZXMultiFormatWriter'
I tried:
setup new project, same issue
checked header search path: $(SRCROOT)/Pods/Headers/Public/Adjust
reinstalled the ZXingObjC framework
checked build settings: Enable Modules: YES
checked build settings: Other Linker Flags: $(inherited) -ObjC
-framework "ZXingObjC"
checked linked binaries in the build phases: framework is added
checked import statement in the bridging header file (#import
<ZXingObjC/ZXingObjC.h> and #import "ZXingObjC/ZXingObjC.h" -- no
difference)
Windows style: restarting Xcode and Mac ;-)
I'm using:
Xcode: 6.3.2
CocoaPods: 0.37.2
Project Deployment target: iOS 8.0
SDK: 8.3
Does anyone know the problem? Can anyone help?
How can I make the ZXingObjC framework available in swift?
Actually it is an easy issue:
Podfile
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
use_frameworks!
pod 'ZXingObjC', '~> 3.1'
So, on terminal:
cd workspace
pod install
Then, once opened project on Xcode, you have to edit bridging-header adding ZXingObj:
#import <ZXingObjC/ZXingObjC.h>
Finally, in your swift classes that uses ZXingObjC, you have to import ZXingObjC.
import ZXingObjC
class ZXingObjCWrapper {
func encode() {
let writer = ZXMultiFormatWriter.writer()
....
}
}
The rest of the code for when you need to set an UIImage with this bar code:
func generateDataMatrixQRCode(from string: String) -> UIImage? {
do {
let writer = ZXMultiFormatWriter()
let hints = ZXEncodeHints() as ZXEncodeHints
let result = try writer.encode(string, format: kBarcodeFormatDataMatrix, width: 1000, height: 1000, hints: hints)
if let imageRef = ZXImage.init(matrix: result) {
if let image = imageRef.cgimage {
return UIImage.init(cgImage: image)
}
}
}
catch {
print(error)
}
return nil
}
The header search path was not correct in my project. The right values are:
$(inherited)
"${PODS_ROOT}/Headers/Public"
"${PODS_ROOT}/Headers/Public/ZXingObjC"
The second and third lines were not added by installation with CocoaPods.
EDIT: The installed framework have to be added to "Embedded Binaries" in General tab of the project.
I tried everything on this page to add ZXingObjC as a Pod. My goal was to generate an Aztec barcode.
I checked my Header Search Path. As Reddas said, I had to manually add "${PODS_ROOT}/Headers/Public/ZXingObjC". I also added ZXingObjC as an Embedded Binary (in the General Tab).
I checked my bridging file & all was good. I checked my view controllers where I wanted to generate the barcode. The import ZXingObjC was there.
No compile errors. But I can't declare a variable of ZXingObjC.
No luck. Any more suggestions?
EDIT - I went into the Targets, Build Settings and searched for Header Search Paths. I added in BOTH "${PODS_ROOT}/Headers/Public/ZXingObjC" and "${PODS_ROOT}/Headers/Private/ZXingObjC"
This seemed to unclog whatever broke. It works now. Strangely, I can now even delete those entries and it works.

Resources