1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

FileChooser: Avoid potential issue when viewDidDismiss and file selection callbacks are interleaved

viewDidDisappear may be called when a file is successfully selected.
presentationControllerDidDismiss is only called when the controller is
dismissed manually by the user, e.g. by tapping outside the sheet, or by
dragging it away.

Checking for sheet dismissal is necessary in iOS 15, but not in iOS 17.
In iOS 17, tapping outside the file chooser causes a callback to
documentPickerWasCancelled instead.
This commit is contained in:
reuk 2024-01-02 19:06:23 +00:00
parent 1506bb3454
commit 1e7b91b4d2
No known key found for this signature in database
GPG key ID: FCB43929F012EE5C
2 changed files with 16 additions and 25 deletions

View file

@ -259,15 +259,14 @@ URL FileChooser::getURLResult() const
void FileChooser::finished (const Array<URL>& asyncResults)
{
std::function<void (const FileChooser&)> callback;
std::swap (callback, asyncCallback);
const auto callback = std::exchange (asyncCallback, nullptr);
results = asyncResults;
results = asyncResults;
pimpl.reset();
pimpl.reset();
if (callback)
callback (*this);
if (callback)
callback (*this);
}
#if ! JUCE_ANDROID

View file

@ -27,7 +27,7 @@
- (void) setParent: (FileChooser::Native*) ptr;
@end
@interface FileChooserDelegateClass : NSObject<UIDocumentPickerDelegate>
@interface FileChooserDelegateClass : NSObject<UIDocumentPickerDelegate, UIAdaptivePresentationControllerDelegate>
- (id) initWithOwner: (FileChooser::Native*) owner;
@end
@ -42,7 +42,6 @@ namespace juce
//==============================================================================
class FileChooser::Native final : public FileChooser::Pimpl,
public detail::NativeModalWrapperComponent,
public AsyncUpdater,
public std::enable_shared_from_this<Native>
{
public:
@ -86,16 +85,9 @@ public:
#endif
}
void handleAsyncUpdate() override
{
pickerWasCancelled();
}
//==============================================================================
void didPickDocumentsAtURLs (NSArray<NSURL*>* urls)
{
cancelPendingUpdate();
const auto isWriting = controller.get().documentPickerMode == UIDocumentPickerModeExportToService
|| controller.get().documentPickerMode == UIDocumentPickerModeMoveToService;
const auto accessOptions = isWriting ? 0 : NSFileCoordinatorReadingWithoutChanges;
@ -223,12 +215,14 @@ private:
[controller.get() setDelegate: delegate.get()];
if (auto* pc = [controller.get() presentationController])
[pc setDelegate: delegate.get()];
displayNativeWindowModally (fileChooser.parent);
}
void passResultsToInitiator (Array<URL> urls)
{
cancelPendingUpdate();
exitModalState (0);
// If the caller attempts to show a platform-native dialog box inside the results callback (e.g. in the DialogsDemo)
@ -310,7 +304,7 @@ private:
//==============================================================================
FileChooser& owner;
NSUniquePtr<NSObject<UIDocumentPickerDelegate>> delegate;
NSUniquePtr<NSObject<UIDocumentPickerDelegate, UIAdaptivePresentationControllerDelegate>> delegate;
NSUniquePtr<FileChooserControllerClass> controller;
//==============================================================================
@ -351,14 +345,6 @@ std::shared_ptr<FileChooser::Pimpl> FileChooser::showPlatformDialog (FileChooser
ptr = parent->weak_from_this();
}
- (void) viewDidDisappear: (BOOL) animated
{
[super viewDidDisappear: animated];
if (auto nativeParent = ptr.lock())
nativeParent->triggerAsyncUpdate();
}
@end
@implementation FileChooserDelegateClass
@ -393,4 +379,10 @@ JUCE_END_IGNORE_WARNINGS_GCC_LIKE
owner->pickerWasCancelled();
}
- (void) presentationControllerDidDismiss: (UIPresentationController *) presentationController
{
if (owner != nullptr)
owner->pickerWasCancelled();
}
@end