Skip to content

Commit

Permalink
🐛 Access PMProgressHandler more safely (#1174)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexV525 authored Aug 7, 2024
1 parent 044ee31 commit 344689e
Show file tree
Hide file tree
Showing 7 changed files with 26 additions and 83 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ To know more about breaking changes, see the [Migration Guide][].

## Unreleased

### Fixes

- Access `PMProgressHandler` more safely on iOS/macOS to avoid crashes and unfinished results.

## 3.2.2

### Fixes
Expand Down
33 changes: 1 addition & 32 deletions example/ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -27,42 +27,11 @@ require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelpe

flutter_ios_podfile_setup

def install_plugin_pods(application_path = nil, relative_symlink_dir, platform)
# defined_in_file is set by CocoaPods and is a Pathname to the Podfile.
application_path ||= File.dirname(defined_in_file.realpath) if self.respond_to?(:defined_in_file)
raise 'Could not find application path' unless application_path

# Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
# referring to absolute paths on developers' machines.

symlink_dir = File.expand_path(relative_symlink_dir, application_path)
system('rm', '-rf', symlink_dir) # Avoid the complication of dependencies like FileUtils.

symlink_plugins_dir = File.expand_path('plugins', symlink_dir)
system('mkdir', '-p', symlink_plugins_dir)

plugins_file = File.join(application_path, '..', '.flutter-plugins-dependencies')
plugin_pods = flutter_parse_plugins_file(plugins_file, platform)
plugin_pods.each do |plugin_hash|
plugin_name = plugin_hash['name']
plugin_path = plugin_hash['path']
# iOS and macOS code can be shared in "darwin" directory, otherwise
# respectively in "ios" or "macos" directories.
shared_darwin_source = plugin_hash.fetch('shared_darwin_source', false)
platform_directory = shared_darwin_source ? 'darwin' : platform
if (plugin_name && plugin_path)
specPath = "#{plugin_path}/#{platform_directory}/#{plugin_name}.podspec"
pod plugin_name, :path => specPath
end
end
end

target 'Runner' do
use_frameworks!
use_modular_headers!

flutter_install_ios_engine_pod(File.dirname(File.realpath(__FILE__)))
install_plugin_pods(File.dirname(File.realpath(__FILE__)), '.symlinks', 'ios')
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end

post_install do |installer|
Expand Down
33 changes: 1 addition & 32 deletions example/macos/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -26,42 +26,11 @@ require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelpe

flutter_macos_podfile_setup

def install_plugin_pods(application_path = nil, relative_symlink_dir, platform)
# defined_in_file is set by CocoaPods and is a Pathname to the Podfile.
application_path ||= File.dirname(defined_in_file.realpath) if self.respond_to?(:defined_in_file)
raise 'Could not find application path' unless application_path

# Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
# referring to absolute paths on developers' machines.

symlink_dir = File.expand_path(relative_symlink_dir, application_path)
system('rm', '-rf', symlink_dir) # Avoid the complication of dependencies like FileUtils.

symlink_plugins_dir = File.expand_path('plugins', symlink_dir)
system('mkdir', '-p', symlink_plugins_dir)

plugins_file = File.join(application_path, '..', '.flutter-plugins-dependencies')
plugin_pods = flutter_parse_plugins_file(plugins_file, platform)
plugin_pods.each do |plugin_hash|
plugin_name = plugin_hash['name']
plugin_path = plugin_hash['path']
# iOS and macOS code can be shared in "darwin" directory, otherwise
# respectively in "ios" or "macos" directories.
shared_darwin_source = plugin_hash.fetch('shared_darwin_source', false)
platform_directory = shared_darwin_source ? 'darwin' : platform
if (plugin_name && plugin_path)
specPath = "#{plugin_path}/#{platform_directory}/#{plugin_name}.podspec"
pod plugin_name, :path => specPath
end
end
end

target 'Runner' do
use_frameworks!
use_modular_headers!

flutter_install_macos_engine_pod(File.dirname(File.realpath(__FILE__)))
install_plugin_pods(File.dirname(File.realpath(__FILE__)), '.symlinks', 'macos')
flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
end

post_install do |installer|
Expand Down
2 changes: 0 additions & 2 deletions ios/Classes/PMProgressHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ NS_ASSUME_NONNULL_BEGIN

- (void)register:(NSObject <FlutterPluginRegistrar> *)registrar channelIndex:(int)index;

- (void)deinit;

@end

NS_ASSUME_NONNULL_END
30 changes: 20 additions & 10 deletions ios/Classes/PMProgressHandler.m
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,32 @@ - (void)notify:(double)progress state:(PMProgressState)state {
@"progress": @(progress),
};

if (channel) {
// Use the main thread to invoke the method.
dispatch_async(dispatch_get_main_queue(), ^{
[channel invokeMethod:@"notifyProgress" arguments:dict];
});
if (!channel) {
return;
}


// Use the main thread to invoke the method.
dispatch_async(dispatch_get_main_queue(), ^{
@try {
FlutterMethodChannel *channel = self->channel;
if (!channel) {
return;
}
// Try to invoke the channel in the thread, regardless if it's available.
[channel invokeMethod:@"notifyProgress" arguments:dict];
} @catch (NSException *exception) {
// Do nothing when it throws.
} @finally {
if (state == PMProgressStateSuccess || state == PMProgressStateFailed) {
self->channel = nil;
}
}
});
}

- (void)register:(NSObject <FlutterPluginRegistrar> *)registrar channelIndex:(int)index {
NSString *name = [NSString stringWithFormat:@"com.fluttercandies/photo_manager/progress/%d", index];
channel = [FlutterMethodChannel methodChannelWithName:name binaryMessenger:registrar.messenger];
}

- (void)deinit {
channel = nil;
}

@end
5 changes: 0 additions & 5 deletions ios/Classes/core/PMManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,6 @@ - (void)fetchThumb:(PHAsset *)asset option:(PMThumbLoadOption *)option resultHan
NSDictionary *info) {
if (error) {
[self notifyProgress:progressHandler progress:progress state:PMProgressStateFailed];
[progressHandler deinit];
return;
}
if (progress != 1) {
Expand Down Expand Up @@ -609,7 +608,6 @@ - (void)fetchFullSizeVideo:(PHAsset *)asset
[options setProgressHandler:^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
if (error) {
[self notifyProgress:progressHandler progress:progress state:PMProgressStateFailed];
[progressHandler deinit];
return;
}
if (progress != 1) {
Expand Down Expand Up @@ -697,7 +695,6 @@ - (void)fetchFullSizeVideo:(PHAsset *)asset
} else if (exportSession.status == AVAssetExportSessionStatusFailed ||
exportSession.status == AVAssetExportSessionStatusCancelled) {
[self notifyProgress:progressHandler progress:1.0 state:PMProgressStateFailed];
[progressHandler deinit];
[handler replyError:[NSString stringWithFormat:@"%@", exportSession.error]];
}
}];
Expand Down Expand Up @@ -812,7 +809,6 @@ - (void)fetchFullSizeImageFile:(PHAsset *)asset resultHandler:(NSObject <PMResul
NSDictionary *info) {
if (error) {
[self notifyProgress:progressHandler progress:progress state:PMProgressStateFailed];
[progressHandler deinit];
return;
}
if (progress != 1) {
Expand Down Expand Up @@ -1477,7 +1473,6 @@ - (void)notifyProgress:(NSObject <PMProgressHandlerProtocol> *)handler progress:

- (void)notifySuccess:(NSObject <PMProgressHandlerProtocol> *)handler {
[self notifyProgress:handler progress:1 state:PMProgressStateSuccess];
[handler deinit];
}


Expand Down
2 changes: 0 additions & 2 deletions ios/Classes/core/PMProgressHandlerProtocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,4 @@ typedef enum PMProgressState{

- (void)notify:(double)progress state:(PMProgressState)state;

- (void)deinit;

@end

0 comments on commit 344689e

Please sign in to comment.