Firebase iOS SDK crashes when used in Xcode frameworks - ios

I am trying to create a few common functions that read and write to Firestore in an Xcode framework so that they can be shared across a few a different apps. But the app crashes with
The default FIRApp instance must be configured before the default
FIRAuthinstance can be initialized. One way to ensure that is to call
[FIRApp configure]; (FirebaseApp.configure() in Swift) in the App
Delegate's application:didFinishLaunchingWithOptions:
(application(_:didFinishLaunchingWithOptions:) in Swift).'
I am configuring Firebase in the main app with FirebaseApp.configure(). As soon as I move the file off the framework, the crash goes away. Is this expected to work?
Other details that might be relevant.
Xcode 11.2.1
Deployment target iOS 13.0

It looks like it is safe to call FirebaseApp.configure() from within your iOS framework (as long as you only call it once per framework). For example, create a static method inside a framework's class:
open class MyFramework {
public static func configure() {
FirebaseApp.configure()
}
}
Then call it from your App Delegate:
class AppDelegate ... {
func application(_ application: UIApplication, didFinishLaunching...) {
FirebaseApp.configure()
MyFramework.configure()
}
}

Related

Breakpoint not getting hit, nor the Message extension is getting attached in iOS

I am writing a SMS filter extension for iOS. I created a MessageFilterExtension. The extension code is
import IdentityLookup
final class MessageFilterExtension: ILMessageFilterExtension {
var words: [String] = ["deal", "spam", "offer"]
override init() {
print("message filter init")
}
}
extension MessageFilterExtension: ILMessageFilterQueryHandling {
func handle(_ queryRequest: ILMessageFilterQueryRequest, context: ILMessageFilterExtensionContext, completion: #escaping (ILMessageFilterQueryResponse) -> Void) {
//...
}
I had set breakpoints in the container app did launch, in the appex handle and other methods. The appex does not call remote services. Then I choose the appex target, clicked run, in the attach list chose the container app as the likely target which was already mentioned. It then shows "Waiting to attach". Then I choose container app and hit run, it build and runs, and hits the breakpoint. However, the appex is not getting attached or launched. I then send some SMS texts, but it does not filter. No print statements in Xcode or Console.app. I have enabled message filter and set the Container app to filter SMS.
I am testing this on iPhone 7 Plus and iOS 12.1.4. Tested on previous release of iOS, but still did not work.
Methods I tried so far:
How To Debug iOS Appex
Messages App Extension won't hit breakpoints
I do not have the contact name saved. (With some combination, it worked once, but I now I am not able to debug). How do debug message filter extensions?
We can debug an extension by running the extension alone from the Xcode schema menu. In this case the breakpoint will be hit. When running with the main app, the extension breakpoints will not be hit. In general app extension programming seems to work that way.

Problem with adding Firebase Crashlytics to iOS Share Extension

I'm trying to add Firebase to collect analytics events and crashes to iOS Share Extension. Everything works perfect in main app but not in Share Extension. I managed to find this way of initialization:
override func viewDidLoad() {
super.viewDidLoad()
if FirebaseApp.app() == nil {
FirebaseApp.configure()
}
// other code
}
Analytics.logEvent works perfectly, I can see events in firebase console, but crashes are not collected.
In addition, xcode organizer periodically collects the following crashes:
Who can tell what could be the reason and what to do to make Crashlytics collect crashes?
I managed to do it by adding this:
if FirebaseApp.app() == nil {
FirebaseApp.configure()
Fabric.with([Crashlytics.self])
}

Admob and Interstitial Ads with iOS9

Today I registered to adMob and I started working on adMob ads inside my apps.The first one is a game (with viewcontrollers) and i want to show an interstitial ad right after the game over screen, so i want to load the interstitial right after the view with game over loads (this view is accessible only after game over and a game lasts for one minute so it should not appear too often)
I have seen many tutorials, on youtube and on admob website, i had many problems like:
admob framework not found even if I imported it,
i disabled bitcode to avoid linker errors when i build,
but i still can't see the test ad on my app, on the simulator and real devices.
I imported all the frameworks required by admob, and in xcode i have a question mark near GoogleMobileAds framework, what does it mean?
First line about admob is:
import GoogleMobileAds
inside viewcontroller
var interstitial: GADInterstitial!
func createNloadAd () -> GADInterstitial
{
var ad = GADInterstitial(adUnitID: "XXX")
var request = GADRequest()
request.testDevices = [kGADSimulatorID]
ad!.loadRequest(request)
return ad
}
inside viewdidload
self.interstitial = self.createNloadAd()
if(self.interstitial!.isReady)
{
self.interstitial!.presentFromRootViewController(self)
self.interstitial! = self.createNloadAd()
}
in adUnitID I tried the ID of the interstitial i created in admob website, and other strings found inside tutorials, but none worked
in testdevices i added my iphone's UDID after i see the message in output, but i can't see any test ad and i have no error at all
And i didn't touch the storyboard,do I have to create something in the storyboard?
Before submitting the app to appstore i have to remove the testdevices line?And of course put my real AdUnitID
Maybe the code is right but if the app is not published admob won't load, or maybe I have to wait a day before my admob id starts working
Where I can find recent admob IDs for testing?
So i test the app, and if works i change the id and submit
I am using Xcode 7.1, AdMob 7.5.2, and my app deployment target is iOS7 and i tested it on simulator with 9.1 and my old iPhone4 with iOS7, and this should not be a problem because admob supports even iOS6
Another question about admob guidelines, in other apps can i use iAd in a view and Admob in an other?May i be banned for this?only banner ads in lower part of the screen
AdMob framework not found even if I imported it
Remove the framework and import it again. Make sure you're checking "Copy items if needed". Also, check your library search paths under your project settings and build phases to see if the framework is include.
I imported all the frameworks required by AdMob
This is not necessary. The AdMob framework will import the frameworks it needs once you include import GoogleMobileAds.
And I didn't touch the storyboard. Do I have to create something in the storyboard?
No
Before submitting the app to App Store I have to remove the test devices line and put my real AdUnitID?
Yes. Try using your real AdUnitID now to see if your test ID is causing the problem.
Maybe the code is right but if the app is not published AdMob won't load, or maybe I have to wait a day before my AdMob id starts working
No. The application does not have to be published to receive live advertisements.
Where I can find recent AdMob IDs for testing? So I test the app, and if works I change the id and submit
Nowhere. It is not wise to give out your AdUnitID.
Another question about AdMob guidelines, in other apps can I use iAd in a view and AdMob in an other? May I be banned for this? Only banner ads in lower part of the screen
Use as many ad networks in your application as you'd like. There's nothing stating you aren't allowed to.
Sounds like you're on the right track. You should set and include the interstitial's delegate methods though to see if you're getting any error messages. You need to allow arbitrary loads in your .plist too. Check AdMob's iOS 9 Considerations.
Are you calling createNloadAd() before you attempt to present the interstitial in your viewDidLoad? It takes time to download the advertisement.
Make sure the AdUnitID provided by AdMob is identical to the one you're using.
Also, move the presentation from viewDidLoad to viewDidAppear.
Here's an example of creating our interstitial in our AppDelegate.swift and then presenting the interstitial in our ViewController.swift:
AppDelegate.swift
import UIKit
import GoogleMobileAds // Import AdMob
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, GADInterstitialDelegate { // Include delegate
var window: UIWindow?
var myInterstitial : GADInterstitial?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// App launched
// Load interstitial
myInterstitial = createAndLoadInterstitial()
return true
}
func createAndLoadInterstitial()->GADInterstitial {
let interstitial = GADInterstitial(adUnitID: "Your Ad Unit ID")
interstitial.delegate = self
interstitial?.loadRequest(GADRequest())
return interstitial
}
func interstitialDidReceiveAd(ad: GADInterstitial!) {
print("interstitialDidReceiveAd")
}
func interstitial(ad: GADInterstitial!, didFailToReceiveAdWithError error: GADRequestError!) {
print(error.localizedDescription)
}
func interstitialDidDismissScreen(ad: GADInterstitial!) {
print("interstitialDidDismissScreen")
myInterstitial = createAndLoadInterstitial()
}
ViewController.swift (This would be your game over view controller)
import UIKit
class ViewController: UIViewController {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate // Create reference to our app delegate
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(animated: Bool) {
appDelegate.myInterstitial?.presentFromRootViewController(self)
}

How do I force a crash in Swift iOS app with Fabric SDK?

All I can find is Is there a quick way to force a crash? which says to:
[[Crashlytics sharedInstance] crash];
which I think in Swift would be
Crashlytics.sharedInstance.crash()
but this does not seem to exist. (perhaps the docs are out of date and no longer apply since Fabric gobbled up Crashlytics?)
I see that there is a Crashlytics.crash(self:Crashlytics) ...nevermind, friggin XCode's completion is always broken for me. See answer below.
If you are using the new Firebase Crashlytics SDK note that import Crashlytics has been replaced by import FirebaseCrashlytics. The crash() method is no longer available in the new SDK. As recommended by Firebase, simply use:
Swift:
fatalError()
Obj C:
assert(NO);
(if it's in a file other than your AppDelegate, you will need to import Crashlytics, then just do Crashlytics.sharedInstance().crash()
Create a Project and App in firebase
Add a new iOS app in the firebase console if you have existing firebase project or create firebase project and create new app in the firebase console.
Add Firebase to iOS App
Firstly in step 1, register your app by adding the bundle identifier while creating iOS app to firebase. In step 2, Download config file GoogleService-Info.plist add it to your workspace like in the image shown below.
Add Crashlytics SDK via CocoaPods
To get started, add the Crashlytics SDK framework files to your project. For most projects, the easiest way to do that is by adding the Crashlytics CocoaPods.
pod 'Firebase/Core'
pod 'Fabric', '~> 1.7.2'
pod 'Crashlytics', '~> 3.9.3'
Test your implementation
Enable Crashlytics debug mode: In order to enable crashlytics in debug mode we need to set Fabric.sharedSDK().debug mode to true in AppDelegate.swift.
import UIKit
import Firebase
import Crashlytics
import Fabric
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
Fabric.sharedSDK().debug = true
return true
}
Force crash to test implementation: While writing this article, I have one view controller with one button named (Click to crash app) in the middle of the viewController. For the testing purpose, when user click the button app crashed.
And View controller this below code and run once in simulator or device and check in Firebase dashboard .You find all crashes report.
import UIKit
import Crashlytics
class ViewController: UIViewController {
var name:String!
var number:Int!
override func viewDidLoad() {
super.viewDidLoad()
name = "12"
}
#IBAction func crashBtnAction(_ sender: Any) {
//creshreportMethod()
print("name of the value",name)
var myDict = [String:Any]()
myDict = ["name":number!]
print("my dict value",myDict)
}
}
Crashlytics can’t capture crashes if your build attaches a debugger at launch. Adjust your build settings to change the project’s debug information format:
With your project still selected in the Xcode Navigator, open the Build Settings tab.
Click All at the top of the tab to display all build settings.
Search for “debug information format”.
Set the Debug Information Format setting to DWARF with dSYM File.

how to integrate flurry in ios using swift language

I want to integrate flurry in ios using swift language.
I added the flurry sdk's two files : flurrylib.a and flurry.h and then entered my api key in project TestProject4-Bridging-Header.h
#import "Flurry.h"
I had the same issue and adding a bridging header worked for me. Here are the steps I followed.
Note: If you already have a bridging file, skip the steps 2 to 4
I dragged the Flurry folder to my Swift iOS project in XCode.
I created a bridging header file by creating a new Objective-C header file (in XCode menu it's File/New/File/iOS/Source/Header File)
I called the file name "PROJECTNAME-Bridging-Header.h" (replace PROJECTNAME with your XCode project name)
In Project Build Settings, I searched for "Swift Compile - Code Generation" and there in "Objective-C Bridging Header" I entered the name of my new bridging file (PROJECTNAME-Bridging-Header.h) for debug and release values.
Now, back in my bridging header file, I referenced the Flurry header file.
#import "Flurry.h"
In my AppDelegate.swift file, I could then call the Flurry methods using Swift:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// setup Flurry
Flurry.startSession(flurryKey) // replace flurryKey with your own key
Flurry.setCrashReportingEnabled(true) // records app crashing in Flurry
Flurry.logEvent("Start Application") // Example of even logging
Hope it helps someone.
Flurry Integration using Pods in Swift
You need to import Flurry SDK as Follows
import Flurry_iOS_SDK
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
Flurry.startSession("YOUR_API_KEY")
Flurry.logEvent("Started Application")
}
If you are attempting to log events in the 'didFinishLaunchingWithOptions' using Flurry SDK 6.0.0, this is not possible due to a bug in that version of the SDK. It is possible to start a session from this function however. I was told this information by a Flurry support rep, and confirmed it in my own testing.
You need to add a bridging header to your project. In that bridging header you import what you need in Swift and then you don't need to import it anywhere else.
The iBook on using Swift and Obj-C alongside has a very good explanation on this.
Actually, there is an explanation on Apple's Swift blog that says:
To be safe, all components of your app should be built with the same version of Xcode and the Swift compiler to ensure that they work together.
You can find more information here.

Resources