I have an app. In this app, a user can like/unlike something. If the user tap the button like, it would change text to unlike, vice versa.
To make the like/unlike event run seamlessly to user, i change the text first, and then make request to my API, saying that the user like/unlike this. The API decides whether the action is liking or unliking depends on value at database. The API then returns a message stating the action made ("liked"/"unliked"). The app receives it, and then update the UI according to the result, in case the action intended by user fails.
If all runs smoothly, the user won't detect the changes made by API result.
This is the flow of liking something
user like -> button text changes to "unlike"
-> app make a request -> request is queued to operation queue
-> request run -> API decides whether that something is liked/unliked by the user
-> API returns action (in this case, "liked") -> app updates button text ("unlike")
Now my question are:
How do I handle rapid button tap by user?
How do I handle failed requests (internet disconnected, or no signal) while handling the problem no. 1?
nb: I don't want to disable the button (the app has to run seamlessly. Facebook app don't do it either, i just checked). Oh, and I use AFHTTPRequestOperationManager and set its maxConcurrentOperationCount to 1.
I resolved my problem using this answer
with a bit modification. The first time user click the button, I set a request flag to false, so that even if the user click the button many times, request won't be made before the first request is done.
Related
I've just implemented the ATT request in my applications. It appears at the app first opening but I would like to show it again if the user wants to change his preferences from the app settings (internal).
I tried to call the requestTrackingAuthorization method again but it enters immediately to the completion handler. Is there a way to reset the status?
I am using call_number plugin to make a call from my app. I am tracking the AppLifecycleState to take actions. This is the order in which states are changing-
AppLifecycleState.inactive
AppLifecycleState.resumed
AppLifecycleState.inactive
AppLifecycleState.paused
AppLifecycleState.inactive
AppLifecycleState.resumed
Last 4-I understand the flow, but I am unable to understand why is state changing to resumed the first time. According to the documentation - "The application is visible and responding to user input." when it is in resumed state but when I press button, call is directly placed.
I wonder if it is being done by the plugin in background but I don't see my app coming up even for a split second.
I am calling
EasyPush.oneSignal.registerForNotifications();
At a relevant time in my program to initiate the iOS subscribe to push messages dialogue. If the user clicks OK I get a an event confirming acceptance and giving me the token.
However if the user clicks Cancel in the OS dialogue I do not get anything, if the user presses Cancel I wish to respond to this.
Can Cancel be detected?
I think this is the same issues as calling the register when Cancel has been previously pressed, because again nothing happens.
EDIT,
When a user clicks 'Agree' then the registered event occurs
PNOSEvent.TOKEN_REGISTERED
However, when 'Dont Agree' is clicked nothing happens, an event exists called
PNOSEvent.TOKEN_REGISTRATION_FAILED
However this never occurs and I do not know why, but if this event did occurs it would be what I am looking for.
Directly from MilkmanGames themselves:
"Apple actually doesn't give us a notification for this case. What you could do is set a timeout (and/or listen for the next Event.ACTIVATE) and use the EasyPush.areNotificationsEnabled() function."
Some background
I am currently writing a UI Test for a settings pane, and click on buttons to enable certain permissions such as push notifications and location services.
However, if the alert for the permission has been displayed before (regardless of the user allowing or denying access to the permission), the alert will not display again, and will just take the user to the settings app. Unfortunately, these settings do not reset, meaning the first time I run the UI tests, alerts will show; and on all subsequent UI test runs, the buttons will take me to the settings app unless I reset the device before the tests begin.
My issue
Thus, my test needs to know if the app went into the background, and attempt to foreground it to continue the testing:
if app.state == background {
foregroundApp()
}
// continue with other tests
Is there any way to determine if the app is in the background?
What I tried
I researched methods to determine the state of the application (running/background/etc) from a UI test, and was not able to find much. I tried to check whether certain elements exist:
if (app.navigationBars.element.exists) ...
but this gives me runtime errors[1] if the user is taken to the settings page because the app under test is in the background, and the test cannot lookup the navigationBars (or other elements).
I tried using some of the methods from Facebook's private headers for XCUIApplication() and XCUIElement().
XCUIApplication().state always returns 3 no matter what state the app is currently in, and any attempts to call XCUIApplication().resolve() to foreground the app give me the same errors as before[1]
I tried to rewrite the logic to foreground the app before resuming the tests, but methods such as XCUIApplication().launch() kill the app before restarting, which I cannot do. Only siri service seems to work for me, but I cannot access the siri service through the corporate proxy, and modifying proxy permissions is not possible.
Is there any other way to check the app state?
Errors
[1] This error is printed every time I try to do something involving state. I do not call snapshotView anywhere, and thus the suggestion to use afterScreenUpdates is useless.
Failure to get snapshot within 15.0s
Cannot snapshot view (<UIKeyboardImpl: 0x7febcc75d000; frame = (0 0;
414 226); layer = <CALayer: 0x608000625720>>) with
afterScreenUpdates:NO, because the view is not in a window. Use
afterScreenUpdates:YES.`
tl;dr
I need to check whether the app I am UI testing has entered the background (i.e. user pressed the home button). Checking for existence of particular elements such as navigation bars doesn't work, neither do most methods from Facebook's private headers for XCUIApplication/XCUIElement. Foregrounding the app also causes issues, and relaunching the app is not an option; neither is siri service.
You can do this in Swift 4, using XCUIApplication.state, which will give you information about the state of the app - whether it's in the foreground or background etc. however, it's not possible to find this information in Swift 3 and below. Essentially, UI testing in Swift 3 doesn't support leaving the app.
I'm implementing an iOS app that handles a custom protocol.
Writing the method application(openURL:sourceApplication:annotation:) in my AppDelegate was easy but I'm left with a problem: I want that - once the user have done with the request - my app move to the background and send the user back to the caller sourceApplication (e.g. a browser, a QRCode reader, or any another app).
This is just like the difference between "tel:" and "telprompt:" url calls: in the former case the phone app remains active, in the latter case, after the call, the user is send back to the sourceApplication.
In order to let my app handle my custom protocol like "telprompt:" does, the only way I can think about is terminate the app once the user action is completed... but this is against iOS Human Interface Guidelines (they say "Don’t Quit Programmatically") and my app can be rejected by Apple.
On Android it is easy: you respond to an Intent with an Activity and when you call finish() on that activity the user is back to his previous app/browser/whatever.
Anyone knows a good way to achieve this on iOS?
Just to clarify:
my app don't call openUrl, it responds to openUrl requests from browser, QRCode reader, other apps;
I don't have to make phone calls;
when I handle a request I ask the user for some data, contact a server, and that's it: the interaction is finished and it would be very nice to drive the user back to previous app without let him use the home button.
I believe you should call openUrl when you are done, with the source app url in param.
That's what facebook does when you use the "connect with facebook" API.