I had added share extension to upload file.
But i want to stop open share extension when user is not logged in application and show alert similar like Messenger application from facebook.
Facebook messenger app
How can i do this
Note : I know how to do check is User logged in or not using app groups. But I want to check before open the share extension and show alert. in my case its first open the share extension and then i am showing alert. I want to check before open the share extension
Rather than directly open your custom view for share extension you could use alert first to check if user logged in or not, then if user has logged in, you can proceed to present your custom view with animation.
you can do this by adding below method on ShareViewController: SLComposeServiceViewController.
override func viewDidLoad() {
// check if user logged in or not here and if not below code will be executed.
self.loginAlertController = UIAlertController(title: "Please launch application from the home screen before continuing.", message: nil, preferredStyle: .alert)
let onOk = UIAlertAction(title: "OK", style: .destructive) { alert in
self.extensionContext?.cancelRequest(withError: NSError(domain: "loging", code: 0, userInfo: nil))
}
loginAlertController!.addAction(onOk)
present(loginAlertController!, animated: true, completion: nil)
}
You should make use of App groups to communicate between the main app and extension app.(Sharing Data: NSUserDefaults and App Groups
)
You can add data in main app like this :-
let mySharedDefaults = UserDefaults(suiteName: "group.yourValue")
mySharedDefaults?.set(false, forKey: "isLoggedIn")
Then you can get data like this in your extension
let mySharedDefaults = UserDefaults(suiteName: "group.yourValue")
if let isLoggedIn = mySharedDefaults?.value(forKey: "isLoggedIn") as? Bool {
if !isLoggedIn {
showAlert()
}
}
Refer this for implementing app groups
Related
need your support I've been struggling with this for days. I'll appreciate any help
hi
I'm trying to learn IOS Development & No SQL Database
using Firebase
by creating a Chat app using Firebase real time database & swift
my problem is UI is not updated unless i rebuild The App
sum up
-the log out functionality will not work unless i rebuild the App again ( if i sign out i can login but i cant see the Chat Messages unless i rebuild the App)
if i want to login (to see the Chat Messages) this is my Process
A- log out from the APP
B -login to the APP (here i need to be logged in ) i rebuild the App again
so every time i add a message i need to rebuild because so the signin method will get activates
the Login Method
extension FCViewController : FUIAuthDelegate
{
func authUI(_ authUI: FUIAuth, didSignInWith authDataResult: AuthDataResult?, error: Error?)
{
if (error != nil)
{
return
}
login()
}
}
func login(
let authUI = FUIAuth.defaultAuthUI()
let googleAuthProvider = FUIGoogleAuth(authUI: authUI!)
let provider : [FUIAuthProvider] = [googleAuthProvider , FUIEmailAuth()]
authUI?.providers = provider
_authHandle = Auth.auth().addStateDidChangeListener
{
(auth : Auth , user : User?) in
self.messages.removeAll(keepingCapacity: false)
self.messagesTable.reloadData()
if let activeUser = user
{
if (self.user != activeUser)
{
self.user = activeUser
self.signedInStatus(isSignedIn: true)
let name = user!.email?.components(separatedBy: "#")[0]
self.displayName = name!
print("The first call",Auth.auth().currentUser as Any)
}
else
{
// user must Sign in
self.signedInStatus(isSignedIn: false
self.loginSession()
}
}
}
}
the library
import UIKit
import Firebase
import FirebaseEmailAuthUI
import FirebaseAuthUI
import FirebaseGoogleAuthUI
the signout Method
#IBAction func signOut
try Auth.auth().signOut()
the UI
func showAlert(title: String, message: String) {
DispatchQueue.main.async {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
let dismissAction = UIAlertAction(title: "Dismiss", style: .destructive, handler: nil)
alert.addAction(dismissAction)
self.present(alert, animated: true, completion: nil)
}
}
When I tap the "signOut" button, the method gets called and gets executed. after the try Auth.auth().signOut() line of code gets executed, the current user is nil
(lldb) po Auth.auth().currentUser
nil
And if i login again
the Message will not Appear unless i rebuild the App
A really small UI test fails when trying to tap an alert button, what step am I missing?
I'm trying to tap the "Continue" button in the alert displayed below with the following code (that I get from recording my steps).
let app = XCUIApplication()
let salesforceloginbuttonButton = app.buttons["salesforceLoginButton"]
salesforceloginbuttonButton.tap()
let posWantsToUseSalesforceComToSignInAlert = app.alerts["“POS” Wants to Use “salesforce.com” to Sign In"]
let continueButton = posWantsToUseSalesforceComToSignInAlert.buttons["Continue"]
continueButton.tap()
When I run the test it fails at the last line (i.e: continueButton.tap()) with the error No matches found for Find: Descendants matching type Alert from input.
Notes:
I already tried waiting a few seconds before tapping the continue button with the same result.
When the test is ran, the app launches and the alert gets displayed after tapping the salesforceloginbuttonButton
I think your alert is not recognized, maybe because of the double quotation marks
You can try and explicitly set the identifier of your alert like this:
let alert = UIAlertController(title: "Alert", message: "msg", preferredStyle: .alert)
alert.view.accessibilityIdentifier = "myAlert"
Then in your tests:
let alert = app.alerts["myAlert"]
let button = alert.buttons["Continue"]
button.tap()
Had a similar issue but I could solve it by using addUIInterruptionMonitor. In your XCTestCase add an override setUp like this. One caveat is that it's a little flakey... Will update the answer if I find a better solution.
class ExamplelUITests: XCTestCase {
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
continueAfterFailure = false
addUIInterruptionMonitor(withDescription: "Login Dialog") {
(alert) -> Bool in
let okButton = alert.buttons["Continue"]
okButton.tap()
return true
}
app.launch()
}
func testExample() throws {
app.buttons["Login"].tap()
app.tap() // This one is needed in order for the InteruptionMonitor to work
}
}
I have an app with push notifications using PHP EasyAPNS notification working fine on Swift 3, iOS 10. But one thing I can't understand is why the badge on TabItem is works fine when I launch the app from the notification alert but not when I open the app direct from the app icon (with the red Badge)
So here is the code that I use on AppDelegate:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [String:Any])
{
print("Message details \(userInfo)")
if let aps = userInfo["aps"] as? NSDictionary
{
if let alertMessage = aps["alert"] as? String {
let rootViewController = self.window?.rootViewController as! UITabBarController!
let tabArray = rootViewController?.tabBar.items as NSArray!
let tabItem = tabArray?.object(at: 3) as! UITabBarItem
tabItem.badgeValue = "1"
let myAlert = UIAlertController(title: "Message", message: alertMessage, preferredStyle: UIAlertControllerStyle.alert)
let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil)
myAlert.addAction(okAction)
self.window?.rootViewController?.present(myAlert, animated: true, completion: nil)
}
}
}
So, when I click in the alert to open my app, the badge is fine like this:
But when I open the app using the icon itself, the badge is not showing up:
Anyone have any idea what I'm doing wrong?
Please let me know if I can improve the question!
You should be using the application(_:didReceiveRemoteNotification:fetchCompletionHandler:) method to handle notifications. As mentioned in the docs (found here), this method is called whether the app is in the foreground or background.
Also worth noting from the docs for application(_:didReceiveRemoteNotification:)
If the app is not running when a remote notification arrives, the
method launches the app and provides the appropriate information in
the launch options dictionary. The app does not call this method to
handle that remote notification.
Note, if the app was not running and the user taps on the icon, the app will call application(_:didFinishLaunchingWithOptions:). There will be appropriate launchOption key-value pairs if the app had a remote notification which needs handling.
I have a view that:
Creates an observer for UIApplicationDidBecomeActiveNotification with invokes a selector
Sequentially asks the user for permissions to: use the camera, location & receiving push notifications.
The view has three UIButtons with state depending on each permission state, which navigate the user to settings if permissions for anything were rejected
Tapping a button which represents a permission with rejected state navigates the user to settings
Once each alert hides, using the observer action, next alert is triggered and all button states are updated to reflect any changes
Once all permissions are granted it pushes next view with the rest of the signup/in flow.
The problem is: on some devices, when running the app from a clean state (app removed and reinstalled), permissions for location & notifications are set to rejected by default, as if the user was presented an alert that was rejected.
I couldn't pinpoint any rational issue behind this, except for leftover settings from some outdated build that don't get deleted when installing a new one. This view seems to be the only place that can possibly trigger these alerts.
Did anyone have a similar issue and can suggest anything?
I would suggest you to try to check for states of location services and notification services before asking user to use it. Since if user is going to disable these the moment you ask him for permission, he will need to go to the settings and enable it there. You should try to detect if user has disabled location/notification/camera.
For camera use:
func accessToCamera(granted: #escaping (() -> Void)) {
if UIImagePickerController.isSourceTypeAvailable(.camera) {
let status = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeAudio)
if status == .authorized {
granted()
} else if status == .denied {
self.cameraPermissionAlert()
} else if status == .notDetermined {
AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo, completionHandler: { (accessAllowed) in
if accessAllowed {
granted()
} else {
self.cameraPermissionAlert()
}
})
} else if status == .restricted {
self.cameraPermissionAlert()
}
} else {
print("Camera not available on this device")
}
}
func cameraPermissionAlert() {
let alert = UIAlertController(title: "Access to camera not available", message: "Please enable access to camera in order to use this feature", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Settings", style: .default, handler: { (action) in
if let url = URL(string: UIApplicationOpenSettingsURLString) {
if UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
}
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .default, handler: nil))
if let top = UIApplication.topViewController() { // This is extension to UIApplication that finds top view controller and displays it
top.present(alert, animated: true, completion: nil)
}
}
For remote notifications you can use something like this:
Determine on iPhone if user has enabled push notifications
And for location services:
Check if location services are enabled
In both of these cases you can detect if this is disabled or not by user and present user with alert controller that has open settings functionality.
I am having various ViewControllers in my app. On one of them I want a alert to be displayed on load of the VC once to the user.
I have followed the instructions to set a glob var under the import section:
var disalert:Bool = true
and in the function I got:
if disalert {
let actionSheetController: UIAlertController = UIAlertController(title: "How-to use Holiday List", message: "message here", preferredStyle: .Alert)
//Create and add the Cancel action
//Create and an option action
let nextAction: UIAlertAction = UIAlertAction(title: "OK", style: .Default) { action -> Void in
}
actionSheetController.addAction(nextAction)
//Add a text field
//Present the AlertController
self.presentViewController(actionSheetController, animated: true, completion: nil)
disalert = false
}
The alert is not presented whilst the app is open. When I restart the phone or quit the app completely its again there.
Thank you!
If I am reading your question properly, my suggestion would be to user NSUserDefaults to save a key when the user first opens the view. Then just use an IF statement to decide whether an alertView should be displayed.
Before showing the alert, wherever you want to show it, check the value against the "disalert" key in your userDefaults with this statement:
var disalert: Bool = NSUserDefaults.standardUserDefaults.boolForKey("disalert");
if disalert {
// The alert has already been shown so no need to show it again
}
else
{
// The alert hasn't been shown yet. Show it now and save in the userDefaults
// After showing the alert write this line of code
NSUserDefaults.standardUserDefaults.setBool(true, forKey: "disalert")
}
Adeel's code worked for me, with a slight improvement:
var disalert: Bool =
NSUserDefaults.standardUserDefaults().boolForKey("disalert");
if disalert {
// The alert has already been shown so no need to show it again
}
else
{
// The alert hasn't been shown yet. Show it now and save in the userDefaults
// After showing the alert write this line of code
NSUserDefaults.standardUserDefaults.setBool(true, forKey: "disalert")
}
NSUserDefaults cried for the following: NSUserDefaults.standardUserDefaults()