Perform segue after notification access has been granted - swift

I would like to know how to perform a modal segue after the remote notification access has been granted from the dialog box. I have set up my remote notification in the app delegate.
func registerANSForApplication(_ application: UIApplication,withBlock block: #escaping (_ granted:Bool) -> (Void)){
InstanceID.instanceID().instanceID { (result, error) in
if let error = error {
print("Error fetching remote instange ID: \(error)")
} else if let result = result {
print("Remote instance ID token: \(result.token)")
AppDelegate.isToken = result.token
}
}
let current = UNUserNotificationCenter.current()
let options : UNAuthorizationOptions = [.sound, .badge, .alert]
current.requestAuthorization(options: options) { (granted, error) in
guard granted else{
return
}
if error != nil{
print(error?.localizedDescription ?? "")
}else{
Messaging.messaging().delegate = self
current.delegate = self
DispatchQueue.main.async {
application.registerForRemoteNotifications()
}
}
}
}
Then, in my view controller, I have this code:
let appDelegate = UIApplication.shared.delegate as!
appDelegate.registerANSForApplication(UIApplication.shared) { (granted) -> (Void) in
self.performSegue(withIdentifier: "MembershipVC", sender: nil)
}
The problem is whether the user allows or denies the access to notification, the segue is not executed.
Thank you for your help.

You have to call the block parameter
Replace
current.requestAuthorization(options: options) { (granted, error) in
guard granted else{
return
}
if error != nil{
print(error?.localizedDescription ?? "")
}else{
Messaging.messaging().delegate = self
current.delegate = self
DispatchQueue.main.async {
application.registerForRemoteNotifications()
}
}
}
with
current.requestAuthorization(options: options) { (granted, error) in
if error != nil {
print(error?.localizedDescription ?? "")
block(false)
} else {
Messaging.messaging().delegate = self
current.delegate = self
DispatchQueue.main.async {
application.registerForRemoteNotifications()
block(granted)
}
}
}

Related

UIButton click, Alamofire POST call, doesnt performSegue with a successful Firebase Login

I have a simple button action
I do verify the email and password before going into this, but this is my Firebase code. When you click on the button, it will get into the VerifyUserInformation function and the response will spit out. Basically, the segue's in VerifyUserInformation will not run for me, the dismiss function doesn't dismiss the modal (present full screen) either.
What can be done to fix this?
Auth.auth().signIn(withEmail: emailOutlet.text!, password: passwordOutlet.text!) { [weak self] user, error in
guard let strongSelf = self else { return }
if let error = error {
self!.displaySnackbar(messageString: "\(error.localizedDescription)")
return
}
self!.preferences.setValue(true, forKey:SHARED_PREF_USER_LOGGED_IN_KEY)
var firstTimeUser = self!.preferences.bool(forKey:FIRST_TIME_USER)
print("\(self!.TAG) FirstTimeUser: \(firstTimeUser)")
if (firstTimeUser) {
print("\(self!.TAG) This is the first time the user is using the application.")
self?.VerifyUserInformation(firebaseId: "\(Auth.auth().currentUser!.uid)")
} else {
print("\(self!.TAG) User can head into the Application.")
self!.performSegue(withIdentifier: "MainScreen", sender: nil)
self?.progressBar.isHidden = true
self!.loginButtonOutlet.isHidden = false
}
}
To verify the user, I run this function.
func VerifyUserInformation(firebaseId: String) {
let urlString = ADD_USER_FOR_ACCOUNT
let param = [
FROM_APP: "true",
USER_FIREBASE_ID: firebaseId,
GET_USER_ACCOUNT_INFORMATION: "true"
] as [String : Any]
AF.request(urlString, method: .post, parameters: param ,encoding: URLEncoding.default).responseJSON {
response in
switch response.result {
case .success:
print("\(self.TAG)\n***Response***\n\(response)\n***END***")
if let result = response.value {
let JSON = result as! NSDictionary
let errorResponse = JSON["error"] as! Int
if (errorResponse == 1) {
print("\(self.TAG) Error verifying the user.")
self.displaySnackbar(messageString: "Error verifying user. Try again.")
} else {
print("\(self.TAG) User is verified")
let messageResponse = JSON["message"] as! String
if (messageResponse == "user has items") {
print("\(self.TAG) User has items, go into MainScreen")
DispatchQueue.main.async {
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
self.performSegue(withIdentifier: "MainScreen", sender: nil)
self.dismiss(animated: false, completion: nil)
self.preferences.setValue(false, forKey:FIRST_TIME_USER)
self.loginButtonOutlet.isHidden = false
self.progressBar.isHidden = true
}
}
} else {
print("\(self.TAG) User has 0 items, go into Second Onboarding")
DispatchQueue.main.async {
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
self.performSegue(withIdentifier: "SecondOnBoarding", sender: nil)
self.dismiss(animated: false, completion: nil)
self.loginButtonOutlet.isHidden = false
self.progressBar.isHidden = true
}
}
}
}
}
break
case .failure(let error):
self.loginButtonOutlet.isHidden = false
self.progressBar.isHidden = true
self.displaySnackbar(messageString: "Error getting user information. Try again.")
print("\(self.TAG) \(error)")
}
}
}
After removing the dismiss(), it started to work.

Cannot share with UICloudSharingController; vanishes with "uploading" message

while presenting the UICloudSharingController on top of a view, it presents the screen and when I select the messages option to send a message to a person whom I want to share with, it gives a spinning wheel with "uploading" message and vanishes - attached.
However when I go to cloudkit dashboard the root record has been shared. But I cannot share it with specific person. Is it because it has shared global? How can I fix it?
self.shareInfraRecord(zoneID: appDelegate.privateContactZoneID, completion: { (status) in
if ( status == false) {
return
}
})
func shareInfraRecord(zoneID: CKRecordZone.ID, completion: #escaping(Bool) -> Void) {
if let rootRecord = self.rootRecord {
if self.rootRecord?.share == nil {
let sharingController = UICloudSharingController { (controller, preparationHandler: #escaping (CKShare?, CKContainer?, Error?) -> Void) in
let shareID = CKRecord.ID(recordName: UUID().uuidString, zoneID: zoneID)
var share = CKShare(rootRecord: rootRecord, shareID: shareID)
share[CKShare.SystemFieldKey.title] = Cloud.ShareInfrastructure.ContactShareTitleKey as CKRecordValue?
share[CKShare.SystemFieldKey.shareType] = Cloud.ShareInfrastructure.ContactShareTypeKey as CKRecordValue?
let modifyRecZoneOp = CKModifyRecordsOperation(recordsToSave:[rootRecord, share], recordIDsToDelete: nil)
modifyRecZoneOp.modifyRecordsCompletionBlock = { (records, recordID, error) in
if error != nil {
if let ckerror = error as? CKError {
if let serverVersion = ckerror.serverRecord as? CKShare {
share = serverVersion
}
completion(false)
}
}
preparationHandler(share, self.defaultContainer, error)
}
self.privateDB?.add(modifyRecZoneOp)
}
sharingController.availablePermissions = [.allowReadOnly, .allowPrivate]
sharingController.delegate = self
sharingController.popoverPresentationController?.sourceView = self.view
self.present(sharingController, animated:true, completion:nil)
} else {
let shareRecordID = rootRecord.share!.recordID
let fetchRecordsOp = CKFetchRecordsOperation(recordIDs: [shareRecordID])
fetchRecordsOp.fetchRecordsCompletionBlock = { recordsByRecordID, error in
guard error == nil, let share = recordsByRecordID?[shareRecordID] as? CKShare else {
if let ckerror = error as? CKError {
self.aErrorHandler.handleCkError(ckerror: ckerror)
//self.saveToCloudKitStatus(recordName: myRecordName, success: false)
}
completion(false)
return
}
DispatchQueue.main.async {
let sharingController = UICloudSharingController(share: share, container: self.defaultContainer!)
completion(true)
//completionHandler(sharingController)
}
}
self.privateDB?.add(fetchRecordsOp)
}
}
}
This might be a bit late but I was running into this issue too, while using NSPersistentCloudKitContainer and it seems the issue was just making sure that my iCloud container name in the Capabilities section of the settings matched my app bundle name ie iCloud.com.goddamnyouryan.MyApp

Push Notification in Swift Firebase

I want to send push notifications to the user if he gets new chat messages or by some other actions I already implemented in a activity feed. All activity messages I receive, I want to duplicate to push notifications if the user is not inside the app.
I already implemented some general stuff in app delegate.swift:
import UserNotifications
import Firebase
import FirebaseInstanceID
import FirebaseMessaging
// The callback to handle data message received via FCM for devices running iOS 10 or above.
func applicationReceivedRemoteMessage(_ remoteMessage: MessagingRemoteMessage) {
print(remoteMessage.appData)
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
if #available(iOS 10.0, *) {
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
// For iOS 10 data message (sent via FCM
Messaging.messaging().delegate = self
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
FirebaseApp.configure()
UITabBar.appearance().tintColor = UIColor.black
UIBarButtonItem.appearance().tintColor = .black
return true
}
This Is my activity feed where I collect all activitys in my network. All This messages I want to send the user as push notification if the user is not inside the app:
func updateView(report: ReportingModel) {
if report.type == "post" {
statusLabel.text = "hat einen neuen Post erstellt"
createTime(report: report)
guard let postId = report.objectId else { return }
PostApi.shared.observePost(withPostId: postId, completion: { (post) in
guard let postImageUrlSting = post.imageURL else { return }
guard let imageUrl = URL(string: postImageUrlSting) else { return }
self.postImageView.sd_setImage(with: imageUrl, completed: { (_, _, _, _) in
})
})
} else if report.type == "comment" {
statusLabel.text = "hat einen neuen Kommentar erstellt"
createTime(report: report)
guard let postId = report.objectId else { return }
PostApi.shared.observePost(withPostId: postId, completion: { (post) in
guard let postImageUrlSting = post.imageURL else { return }
guard let imageUrl = URL(string: postImageUrlSting) else { return }
self.postImageView.sd_setImage(with: imageUrl, completed: { (_, _, _, _) in
})
})
} else if report.type == "like" {
statusLabel.text = "hat deinen Beitrag geliked"
createTime(report: report)
guard let postId = report.objectId else { return }
PostApi.shared.observePost(withPostId: postId, completion: { (post) in
guard let postImageUrlSting = post.imageURL else { return }
guard let imageUrl = URL(string: postImageUrlSting) else { return }
self.postImageView.sd_setImage(with: imageUrl, completed: { (_, _, _, _) in
})
})
} else if report.type == "dislike" {
statusLabel.text = "hat deinen Beitrag gedisliked"
createTime(report: report)
guard let postId = report.objectId else { return }
PostApi.shared.observePost(withPostId: postId, completion: { (post) in
guard let postImageUrlSting = post.imageURL else { return }
guard let imageUrl = URL(string: postImageUrlSting) else { return }
self.postImageView.sd_setImage(with: imageUrl, completed: { (_, _, _, _) in
})
})
}
}
But how to connect the activity feed to my push notifications?
I now receive some manually send push notifications through cloud messaging.
Thanks in advance for your help!

What is the correct way to log in with facebook on firebase? swift

When I log in with a facebook account in a view, I pass it a second view, in the second view I want a fetch query but in the view log I get permission denied and I dont see the info.
I have a normal firebase account, application test facebook.
this is the code view log in
#IBAction func InicioSesionFacebook(_ sender: Any)
{
esperaSesion.isHidden = false
esperaSesion.startAnimating()
let fbLoginManager = FBSDKLoginManager()
fbLoginManager.logIn(withReadPermissions: ["public_profile", "email"], from: self) { (result, error) in
if let error = error {
print("Failed to login: \(error.localizedDescription)")
self.esperaSesion.stopAnimating()
return
}
guard let accessToken = FBSDKAccessToken.current() else {
print("Failed to get access token")
self.esperaSesion.stopAnimating()
return
}
let credential = FacebookAuthProvider.credential(withAccessToken: accessToken.tokenString)
// Perform login by calling Firebase APIs
Auth.auth().signIn(with: credential, completion: { (user, error) in
if let error = error
{
self.esperaSesion.stopAnimating()
print("Login error: \(error.localizedDescription)")
let alertController = UIAlertController(title: "Login Error", message: error.localizedDescription, preferredStyle: .alert)
let okayAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(okayAction)
self.present(alertController, animated: true, completion: nil)
return
}
else
{
let fbloginresult : FBSDKLoginManagerLoginResult = result!
if (result?.isCancelled)!
{
return
}
else
{
// Present the main view
self.esperaSesion.stopAnimating()
if let viewController = self.storyboard?.instantiateViewController(withIdentifier: "NavigationMasterController")
{
UIApplication.shared.keyWindow?.rootViewController = viewController
self.dismiss(animated: true, completion: nil)
}
}
}
})
}
}
this is the code in the second view, a query
import FirebaseAuth
import FirebaseDatabase
import FBSDKLoginKit
var refDB: DatabaseReference!
override func viewDidLoad()
{
super.viewDidLoad()
refDB = Database.database().reference()
CerrarSesion.layer.cornerRadius = 8
imagenPerfil.layer.cornerRadius = imagenPerfil.frame.height/2
imagenPerfil.clipsToBounds = true
verDatos()
// Do any additional setup after loading the view.
}
func verDatos()
{
let userID = Auth.auth().currentUser?.uid
refDB.child("users").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in
// Get user value
let value = snapshot.value as? NSDictionary
let nombre = value?["nombre"] as? String ?? ""
let apellido = value?["apellido"] as? String ?? ""
self.nombreUsuario.text = nombre
self.apellidoUsuario.text = apellido
// ...
}) { (error) in
print(error.localizedDescription)
}
}
and the button log out
#IBAction func CerrarSesion(_ sender: Any)
{
do
{
try Auth.auth().signOut()
self.view.window?.rootViewController?.dismiss(animated: true, completion: borrarUserDefaults)
}
catch let error as NSError
{
print (error.localizedDescription)
}
}
how is the correct form for log out when I logged in with facebook account?
You can check out my YouTube Tutorial on this exact topic !
https://www.youtube.com/watch?v=BfwNf-W-R4U
The version of the Facebook API that you are using is dated. The Login function should look something like this
let loginManager = LoginManager()
loginManager.logIn(readPermissions: [.publicProfile], viewController: self) {loginResult in
switch loginResult {
case .failed(let error):
print("error: \(error)")
case .cancelled:
print("User cancelled login.")
case .success(let grantedPermissions, let declinedPermissions, let accessToken):
print(grantedPermissions)
print(declinedPermissions)
fbAccessToken = accessToken
let credential = FacebookAuthProvider.credential(withAccessToken: (fbAccessToken?.authenticationToken)!)
Auth.auth().signIn(with: credential) { (user, error) in
if let error = error {
print(error)
return
}
currentUser = Auth.auth().currentUser
moveToHomeScreen()
print("Logged in!")
}
}
}
I think that you are getting a permissions error because the parameter name from the AccessToken changed and you are passing the wrong value. (Sorry I cant recall what the change was).
If you are following the Facebook API instructions on the facebook developer portal they are horrendously out of date iOS 9 I think.

how do I perform segue after log in with facebook account?

Currently I am attempting to perform a segue to a second view controller after a user logs in with Facebook using firebase
I was able to sort of get this to work. My problem is I have to actually log-in twice before the Segue is activated. Any suggestions?
see my CODE below
private var fbLoginSuccess = false //This is gobal
override func viewDidAppear(_ animated: Bool) {
if (FBSDKAccessToken.current() != nil && fbLoginSuccess == true)
{
performSegue(withIdentifier: "Home", sender: self)
}
}
#IBAction func facebookLogin(sender: UIButton) {
let facebookLogin = FBSDKLoginManager()
facebookLogin.logIn(withReadPermissions: ["public_profile", "email"], from: self, handler: {
(facebookResult, facebookError) -> Void in
if facebookError != nil {
print("Facebook login failed. Error \(String(describing: facebookError))")
} else if (facebookResult?.isCancelled)! {
print("Facebook login was cancelled.")
} else {
let credential = FacebookAuthProvider.credential(withAccessToken: FBSDKAccessToken.current().tokenString)
Auth.auth().signIn(with: credential) { (user, error) in
if error != nil {
print("Login failed. \(String(describing: error))")
} else {
fbLoginSuccess = true
print("Logged in!")
if (facebookResult?.grantedPermissions.contains("email"))! {
}
}
}
}
})
}
It appears that you're only calling performSegue(withIdentifier:) in viewDidAppear. If you want the segue to occur after signing in, then you need to include it there.
let facebookLogin = FBSDKLoginManager()
facebookLogin.logIn(withReadPermissions: ["public_profile", "email"], from: self, handler: {
(facebookResult, facebookError) -> Void in
if facebookError != nil {
print("Facebook login failed. Error \(String(describing: facebookError))")
} else if (facebookResult?.isCancelled)! {
print("Facebook login was cancelled.")
} else {
let credential = FacebookAuthProvider.credential(withAccessToken: FBSDKAccessToken.current().tokenString)
Auth.auth().signIn(with: credential) { (user, error) in
if error != nil {
print("Login failed. \(String(describing: error))")
} else {
fbLoginSuccess = true
print("Logged in!")
if (facebookResult?.grantedPermissions.contains("email"))! {
}
performSegue(withIdentifier: "Home", sender: self)
}
}
}
})