Perform action after coming from a closed state - SwiftUI - swift

I currently have this:
.onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in
...
}
and that works when I don't quit the app, it simply is in the background, but when I quit it, the code inside there that is suppoused to check for a time, doesn't work.
I also tried putting it in
.onAppear() {
but that doesn't workout either :/
How can I once the app has been closed, then opened, as soon as it opens run an action?

you could try adding the following code to perform an action when your app starts:
.onReceive(NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification)) { _ in
// do your action here
....
}

Related

How can I get permanent access to files in macOS?

I am working in app that tells the count of folders and files exist on Desktop in macOS, for making things easier to my issue get solved I made a simple and small project that re create the problem. At first time of lunching the app I am asking the user to select the Desktop, after I am using the selected path for later use case when the app get killed, I do not want ask user each time to select the Desktop each time, it would be very bothering! currently sometimes macOS allows my app to get access to Desktop without showing the permission dialog but sometimes it goes ask each single time, I am trying to make my app authorized for such permission via user and use that permission for later use case in app. For example as you can see Terminal has such permission in the picture:
So here is my code with disabling sandbox:
struct ContentView: View {
#State private var contents: [String]? = nil
var body: some View {
VStack(spacing: 10.0) {
Text("Count of contents of Desktop is:")
Text(contents != nil ? String(contents!.count) : "Unknown").bold()
}
.frame(width: 200.0, height: 200.0)
.padding()
.onAppear {
contents = directoryContentsReader(folderLocation: "/Users/myNameHere/Desktop")
}
}
}
func directoryContentsReader(folderLocation: String) -> [String]? {
do {
return try FileManager.default.contentsOfDirectory(atPath: folderLocation)
}
catch(let error) {
print(error.localizedDescription)
return nil
}
}
And as said before most of the time and randomly I get this below dialog from macOS, I want make this kind permission done one time and for ever when the user use my app, and not bothering user with this dialog any more. How can I get this permission for my app?

Ionic 4 intercept android back button for navigation

so in ionic 3 there was registerBackButton() but in ionic 4 this option is no longer there and has been sitting on the shelf for quite some time now.
I have read the post here that tries to solve the solution I am looking for, however, the back button still performs as it wants to.
this SO answer shows another way but it is the same idea of intercepting and navigating, however, I am just, for now, trying to dismiss the top modal in the stack.
scenario: users open a search modal(modal1) which then they click on a users profile modal(modal2). The person wants to go back to the search modal(modal1) but instead of clicking the nice button that allows them to do that, they use the hardware back button.
result: all modals(modal1 and modal2) are closed.
desired effect: using the hardware back button will allow for custom navigation based on logic in place.
attempted code:
this.platform.backButton.subscribeWithPriority(0, (): void => {
this.modalCtrl.getTop().then(
async (value: HTMLIonModalElement): Promise<void> => {
if (!!value) {
await this.modalCtrl.dismiss();
} else {
this.navCtrl.navigateRoot('/home');
}
},
);
});
also have tried :
// registering back, if there is a view on top, close it, don't go to home.
this.platform.backButton.subscribeWithPriority(0, async (): Promise<void>=> {
try {
console.log('try');
const element = await this.modalCtrl.getTop();
if (element) {
console.log('in true');
await element.dismiss();
}
} catch (error) {
console.log('error closing modal', error);
}
});
note when pressing the back button I never see ANY of the console logs... maybe things have changed a lot more? since the previous Stack overflow questions.
UPDATE:
If you are having this same issue then know you are not alone!
This, and many others are well known, see here for a list they are tracking the issues. Nothing else to do... but wait... I guess...
I will update this when there is a change

addUIInterruptionMonitor is not getting called on macOS

I want to test my macOS application. It uses your Macbook's camera, and want to handle this in my UITest. However I cannot get it working. Here is my NOT working code. This code triggers to notification, and I'm presented an alert to allow access to my camera, but the closure is not getting called. Thanks fo any help.
There are many solutions for iOS, but I need it on macOS.
let alertHandler = addUIInterruptionMonitor(withDescription: "Camera Permission Alert") { (alert) -> Bool in
if alert.buttons.matching(identifier: "OK").count > 0 {
alert.buttons["OK"].click()
self.app.click()
return true
} else {
return false
}
}
XCTAssertTrue(startButton.waitForExistence(timeout: 1.0))
startButton.click()
XCTAssertTrue(recordButton.waitForExistence(timeout: 20.0))
recordButton.click()
wait(for: 8)
recordButton.click()
removeUIInterruptionMonitor(alertHandler)
}
I managed to make interruption monitor work on macOS by adding an extra interaction after the interaction that triggers the system dialog (be it camera access or else). So in your example I would add an action after startButton.click() (if that is what triggers the camera access dialog).
Example:
func testCamera() {
let alertHandler = addUIInterruptionMonitor(withDescription: "Camera Permission Alert") { (alert) -> Bool in
if alert.buttons.matching(identifier: "OK").count > 0 {
alert.buttons["OK"].click()
self.app.click()
return true
} else {
return false
}
}
useCameraButton.click()
// try to interact with the app by clicking on the app's window
app.windows.first().click()
// at this point the handler should intercept the system interruption
// and blocks further execution until handler does return
// try to use the camera again
useCameraButton.click()
removeUIInterruptionMonitor(alertHandler)
}
Hint about this behaviour in Apple's documentation:
When an alert or other modal UI is an expected part of the
test workflow, don't write a UI interruption monitor. The test won’t
use the monitor because the modal UI isn’t blocking the test. A UI
test only tries its UI interruption monitors if the elements it needs
to interact with to complete the test are blocked by an interruption
from an unrelated UI.
https://developer.apple.com/documentation/xctest/xctestcase/handling_ui_interruptions

button back to my app in the background and when you resume it starts again

I am developing an app in Xamarin.Forms, before I was trying to make a master detail page to become my MainPage when I logged in to my app, this I have already achieved. Now I have the problem that when I use the button behind the phone my app is miimiza and goes to the background which is the behavior I hope, but when I return to my app does not continue showing my master detail page, but returns to my LginPage.
It is as if my app was running twice or at least there were two instances of LoginPage existing at the same time, this is because in my LoginPage I trigger some DisplayAlert according to some messages that my page is listening through the MessaginCenter and they are they shoot twice.
Can someone tell me how I can return the same to my app on the master detail page and not restart in the strange way described?
LoginView.xaml.cs:
public partial class LogonView : ContentPage
{
LogonViewModel contexto = new LogonViewModel();
public LogonView ()
{
InitializeComponent ();
BindingContext = contexto;
MessagingCenter.Subscribe<LogonViewModel>(this, "ErrorCredentials", async (sender) =>
{
await DisplayAlert("Error", "Email or password is incorrect.", "Ok");
}
);
}
protected override void OnDisappearing()
{
base.OnDisappearing();
MessagingCenter.Unsubscribe<LogonViewModel>(this, "ErrorCredentials");
}
}
Part of my ViewModel:
if (Loged)
{
App.token = token;
Application.Current.MainPage = new RootView();
}
else
{
MessagingCenter.Send(this, "ErrorCredentials");
}
Thanks.
I hope this is in Android. All you can do is, you can override the backbuttonpressed method in MainActivity for not closing on back button pressed of the entry page. like below, you can add some conditions as well.
public override void OnBackPressed()
{
Page currentPage = Xamarin.Forms.Application.Current.MainPage.Navigation.NavigationStack.LastOrDefault();
if (currentPage != null)
{
if (currentPage.GetType().Name == "HomePage" || currentPage.GetType().Name == "LoginPage")
{
return;
}
}
base.OnBackPressed();
}
When you press the Home button, the application is paused and the
current state is saved, and finally the application is frozen in
whatever state it is. After this, when you start the app, it is
resumed from the last point it was saved with.
However, when you use the Back button, you keep traversing back in
the activity stack, closing one activity after another. in the end,
when you close the first activity that you opened, your application
exits. This is why whenever you close your application like this, it
gets restarted when you open it again.
Answer taken from this answer. The original question asks about the native Android platform, but it still applies here.
It means you have to Use Setting Plugin or save data in Application properties.
You have to add below code in App.xaml.cs file:
if (SettingClass.UserName == null)
MainPage = new LoginPage();
else
MainPage = new MasterDetailPage();
For Setting Plugin you can refer this link.

How to cancel progress monitor eclipse4.4

I have below code written in xtend :
void doMyMethod(IProgressMonitor monitor, Collection myCollection) {
val subMonitor = SubMonitor.convert(monitor, myCollection.size());
subMonitor.setTaskName("My Task Name...");
myCollection.forEach [ element |
if(subMonitor.canceled || monitor.canceled)
{
throw new OperationCanceledException
}
subMonitor.worked(1)]
}
Meant to stop the progress monitor when user cancels the progress monitor from UI. But is not working. I am following Using prograess monitor, which says can't use monitor.split in eclipse 4.6.
Strangely though if I put a debug point #subMonitor.worked(1) and run the eclipse in debug mode it is working as expected and cancels the monitor if cancels from UI but not working if the debug point is removed. Any idea would be much helpful because I am running short of ideas if debug mode works it should also work without it as well!
I could able to cancel the progress monitor by changing to :
void doMyMethod(IProgressMonitor monitor, Collection myCollection) {
monitor.beginTask(("My Task Name...", myCollection.size());
myCollection.forEach [ element |
if(subMonitor.canceled || monitor.canceled)
{
throw new OperationCanceledException
}
subMonitor.worked(1)] }
thanks