xmppStreamDidConnect never gets called in Swift - ios

I am trying to connect to my chat server in a Swift app using XMPPFramework, but the didConnect delegate method never gets called.
I have created a basic app in Objective C and I can connect and authenticate in my chat sever without problems.
In the Swift project I tried to connect with the code:
class AppDelegate: UIResponder, UIApplicationDelegate {
var stream:XMPPStream = XMPPStream()
var reconnect:XMPPReconnect = XMPPReconnect()
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
stream.addDelegate(self, delegateQueue: DispatchQueue.main)
stream.myJID = XMPPJID(string: "user#chatserver.net")
reconnect.activate(stream)
do {
try stream.connect(withTimeout: XMPPStreamTimeoutNone)
}
catch let err{
print("error occured in connecting\(String(describing: err.localizedDescription))")
}
return true
}
I’ve debugged XMPPFramework and in the method - (void)handleStreamFeatures a call to the delegate is executed :
[multicastDelegate xmppStreamDidConnect:self];
I’ve watched the multicastDelegateObject and has a node with reference to my delegate, and to OS_dispatch_queue_main, but after execution my xmppStreamDidConnect method isn’t executed.

As it is described in this Github Issue, the problem was the method declaration.
My xmppStreamDidConnect need an underscore, the root problem was that if you don't import the swift extensions the compiler marks that declaration as incorrect, although it works.
So to fix my problem, I need to import the pod 'XMPPFramework/Swift' and change the method declaration to
func xmppStreamDidConnect(_ sender: XMPPStream) {

Related

Running code when app is terminated. Xcode 12

I'm trying to run some code to refresh data and serve a local notification on iOS 14. I'm using Xcode 12 and all the help I find online is based on a structure having an appdelegate.swift swift file with several functions depending on the state of the app.
In Xcode 12 the appdelegate file isn't there anymore. How do I proceed, I don't know where to start. Does anybody know what to do?
Your issue is probably that you set up the project to use SwiftUI. You need to create an AppDelegate object that implements UIApplicationDelegate protocol:
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
print("Your code here")
return true
}
// Implement other methods that you require.
}
On your SwiftUI file, add this line to tell iOS who's gonna be the listener for the AppDelegate's methods:
#main
struct SomeApp: App {
#UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
You can then follow by checking Apple's documentation on how to use background app modes.

The default app has not been configured yet

I'm trying to upgrade my app to the new version of Firebase. I went through the setup guide and edited all of my code to match the new syntax. However, when I run the app, I get these two errors.
The default app has not been configured yet.
Terminating app due to uncaught exception 'MissingDatabaseURL', reason: 'Failed to get FIRDatabase instance: FIRApp object has no databaseURL in its FirebaseOptions object.'
I have FIRApp.configure() in the AppDelegate and I have the GoogleServices-Info.plist imported into my project. The plist has all of the correct info as well. Anyone else running into this or know how to fix it?
Here's the answer to your problem:
To configure Firebase you have to execute FIRApp.configure() somewhere. After this is done you can use let firebaseDatabaseReference = FIRDatabase.database().reference() to get a reference to that database and start using it. The problem isn't with Firebase "per se" but with how Swift behaves.
If you put FIRApp.configure() in your AppDelegate func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool and then in the MyDatabase class you use let firebaseDatabaseReference = FIRDatabase.database().reference() outside of your declared functions sometimes the code FIRDatabase.database().reference() executes before the application didFinishLaunchingWithOptions function is executed.
Essentially your class is trying to get a reference to the Firebase database before it has a chance to configure itself, generating the error in the console "The default app has not been configured yet."
Note: This doesn't happen all the time, sometimes the application is slow to start, in iOS Simulator for example, and it doesn't have a chance to finish before MyDatabase "let" executes and tries to get a reference.
That is why moving the FIRApp.configure() code to override init() in AppDelegate works, essentially it makes sure the configure code gets executed when AppDelegate is initialised (in this and most cases, before MyDatabase is initialised)
override init() {
super.init()
FIRApp.configure()
// not really needed unless you really need it FIRDatabase.database().persistenceEnabled = true
}
Also make sure you super.init() (so you super classes get the "message") so you override doesn't do more harm than good.
I'm also using Fabric and in my case it was the order of Fabric and Firebase initializations. I had to initialize Firebase first.
So changing
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
Fabric.with([Crashlytics.self])
FirebaseApp.configure()
...
}
to:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
Fabric.with([Crashlytics.self])
...
}
fixed the problem.
In AppDelegate.m, outside of didFinishLaunchingWithOptions,
override init() {
FIRApp.configure()
FIRDatabase.database().persistenceEnabled = true
}
Make sure you are having DATABASE_URL key in your GoogleService-Info.plist
Swift 5 - Easy Solution
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
return true
}
//MARK:- This function will auto run and firebase will configure successfully
override init() {
super.init()
FirebaseApp.configure()
// not really needed unless you really need it
FIRDatabase.database().persistenceEnabled = true
}
Happy Coding
iOS 9.2
Swift 2.1.1
Xcode 7.2.1
Mac OSX 10.10.5
Same error here using the following code:
AppDelegate.swift:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
FIRApp.configure()
return true
}
ViewController.swift:
import UIKit
import Firebase
class ViewController: UIViewController {
var db = FIRDatabase.database().reference()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//Create some data in Firebase db:
db.child("key").child("subkey").setValue("hello world")
}
I also added the file GoogleService-Info.plist to my project directory as described in the Firebase Getting Started Guide.
And I made my Firebase db public with the following Rules:
{
"rules": {
".read": true,
".write": true
}
}
Making the following changes to ViewController.swift is what worked for me:
class ViewController: UIViewController {
var db: FIRDatabaseReference!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
db = FIRDatabase.database().reference()
db.child("key").child("subkey").setValue("hello world")
}
Prior to running my app, my Firebase db looked like this:
myiosdata-abc123: null
After running my app, my Firebase db looked like this:
myiosdata-abc123
- key
|
+--- subkey: “hello world”
I had several normal working projects with FIRApp.configure () code in AppDelegate.swift:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
FIRApp.configure()
return true
}
Everything worked great for quite some time, but yesterday and today I opened a Swift 3 project inside my Xcode 7.3.1 (I am still working in Swift 2, but opened Swift 3 project to see what is changed), and suddenly in all my Swift 2 apps and projects that I am still working on, got the same error:
The default app has not been configured yet
Every project now when I open in XCode, getting same error, I didn't know what to do, but after implementing #MichaelWilliams' code, everything works fine again.
I have debug my Xcode (clear and reload console), but nothing works beside this new approach by Michael.
This one resolved my problem:
override init() {
FIRApp.configure()
FIRDatabase.database().persistenceEnabled = true
}
Can this new code somehow make my app's unstable and can I be afraid to see problems with connecting/working with Firebase database now?
Try re-download GoogleService-Info.plist from your console and add it to your project, That worked for me!
If you are using Xcode 9, Swift 4 and Firebase 4 please do the following:
override init() {
FirebaseApp.configure()
Database.database().isPersistenceEnabled = true
}
The cleanest solution to me here is to have lazy properties in case you want to have the db on top of your file. So let's say you have a FirebaseService class where you want to have Firestore.firestore() db constant to use it in all of the functions in that class:
private lazy var db = Firestore.firestore()
Or if you are using Firebase Storage:
private lazy var storage = Storage.storage().reference()
Also keep in mind that if you are referencing the Database/Storage in init() of your classes, you still might have the same problem so avoid that.

AppConnect Error : AppConnect cannot be instantiated directly

I am trying to Access the MDM using AppConnect SDK in swift 1.2 but it is giving following error :
[AppConnect:Error] AppConnect cannot be instantiated directly.
Instead, call +initWithDelegate: and then +sharedInstance.
Code Snippet :
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, AppConnectDelegate {
var window: UIWindow?
var appct = AppConnect()
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
// Initialize the AppConnect library
AppConnect.initWithDelegate(self)
self.appct = AppConnect.sharedInstance()
self.appct.startWithLaunchOptions(launchOptions)
return true
}
}
Application is crashing while accessing the Keys of MobileIron Backend Config file.
Any other way to implement this?
You are initializing AppConnect without delegate
change
var appct = AppConnect();
to
var appct : AppConnect!;
My solution was to set a new key/value in the plist:
Principal class AppConnectUIApplication
or in source mode:
<key>NSPrincipalClass</key>
<string>AppConnectUIApplication</string>
Hope it help you

Chartboost delegate error

I am integrating chartboost into my sprite kit game and have successfully integrated bridging files into my swift code. Now in my app delegate I have the following:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
let kChartboostAppID = "5554c8680d60255c6a0f4af4"
let kChartboostAppSignature = "1d0e271cd054c9a63473d2f1212ca33a2922a19f"
Chartboost.startWithAppId(kChartboostAppID, appSignature: kChartboostAppSignature, delegate: self)
Chartboost.cacheMoreApps(CBLocationHomeScreen)
return true
}
class func showChartboostAds()
{
Chartboost.showInterstitial(CBLocationHomeScreen);
}
func didFailToLoadInterstitial(location: String!, withError error: CBLoadError) {
}
the startWithId line gives me an error that it cant invoke this method with these arguments ( String, String, AppDelegate). This used to work fine on my objective c code.. Anyone knows how to fix this?
class AppDelegate: UIResponder, UIApplicationDelegate, ChartboostDelegate
Edit (from Lalit's comment below)
In startWithAppId the delegate is set to self, so you have to set the class AppDelegate as the delegate, which is done using:
ChartboostDelegate(protocol)

Could not init a PFObject subclass

After upgrading to Xcode 6.3 6D570 (and Swift 1.2), the init of a subclassed object does not compile.
Let's say I have a class called Armor, which inherits from PFObject, PFSubclassing (exactly as Parse documentation says).
When I try to create an instance, like var armor = Armor(), I get the following compile error:
Missing argument for parameter 'className' in call
Then I read in Parse docs that I should use the 'object' class method to init a subclassed object. So I tried to init like this: var armor = Armor.object().
But then I get the following compile error:
'object()' is unavailable: use object construction 'PFObject()'
I'm using Parse SDK version 1.7.1.
I also override the parseClassName method as follows:
class func parseClassName() -> String {
return "Armor"
}
I registered the subclass inside the initialise method and on app delegate before I setup Parse:
override class func initialize() {
var onceToken : dispatch_once_t = 0;
dispatch_once(&onceToken) {
self.registerSubclass()
}
}
How should I properly init a subclassed object?
=========================================================================
THIS HAS BEEN FIXED IN 1.7.3 PARSE SDK
You can download the new version here:
https://parse.com/docs/downloads
=========================================================================
Though docs are not clear on that, using .object() in Swift is not required anymore.
as said here and in the Swift code snippet found here
Now, this is weird but to make Armor() work you need to reference PFUser class somehow in the same file. Maybe it doesn't have to be PFUser but I havent dug deeper into it.
So, this won't work
import UIKit
import Parse
import Bolts
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
Parse.setApplicationId("appID", clientKey: "clientKey")
let myArmor = Armor()
return true
}
}
But this will
import UIKit
import Parse
import Bolts
private let fix = PFUser.hash() // here's the weird trick
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
Parse.setApplicationId("appID", clientKey: "clientKey")
let myArmor = Armor()
return true
}
}
Hope this helps and Parse pushes a fix out soon.
Also reported as a bug
register the class as a subclass in the AppDelegate, but before Parse.initialize is called.
Then you can delete the overwritten function initialize
This would make:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]!) -> Bool {
Armor.registerSubclass()
// Further initialization
return true
}
then just initialize the class by calling the constructor:
var myArmor = Armor()

Resources