Browse Source

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.
v7.0.12
reuk 1 year ago
parent
commit
1e7b91b4d2
No known key found for this signature in database GPG Key ID: FCB43929F012EE5C
2 changed files with 16 additions and 25 deletions
  1. +5
    -6
      modules/juce_gui_basics/filebrowser/juce_FileChooser.cpp
  2. +11
    -19
      modules/juce_gui_basics/native/juce_FileChooser_ios.mm

+ 5
- 6
modules/juce_gui_basics/filebrowser/juce_FileChooser.cpp View File

@@ -259,15 +259,14 @@ URL FileChooser::getURLResult() const
void FileChooser::finished (const Array<URL>& asyncResults) 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 #if ! JUCE_ANDROID


+ 11
- 19
modules/juce_gui_basics/native/juce_FileChooser_ios.mm View File

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

Loading…
Cancel
Save