[shared_preferences] upgraded ios to using pigeon (#4732)
diff --git a/packages/shared_preferences/shared_preferences_ios/CHANGELOG.md b/packages/shared_preferences/shared_preferences_ios/CHANGELOG.md index b2a9f14..a5cc1d3 100644 --- a/packages/shared_preferences/shared_preferences_ios/CHANGELOG.md +++ b/packages/shared_preferences/shared_preferences_ios/CHANGELOG.md
@@ -1,3 +1,7 @@ +## 2.1.0 + +* Upgrades to using Pigeon. + ## 2.0.10 * Switches to an in-package method channel implementation.
diff --git a/packages/shared_preferences/shared_preferences_ios/ios/Classes/FLTSharedPreferencesPlugin.m b/packages/shared_preferences/shared_preferences_ios/ios/Classes/FLTSharedPreferencesPlugin.m index 4d49e3b..bb11da2 100644 --- a/packages/shared_preferences/shared_preferences_ios/ios/Classes/FLTSharedPreferencesPlugin.m +++ b/packages/shared_preferences/shared_preferences_ios/ios/Classes/FLTSharedPreferencesPlugin.m
@@ -3,68 +3,7 @@ // found in the LICENSE file. #import "FLTSharedPreferencesPlugin.h" - -static NSString *const CHANNEL_NAME = @"plugins.flutter.io/shared_preferences_ios"; - -@implementation FLTSharedPreferencesPlugin - -+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar { - FlutterMethodChannel *channel = [FlutterMethodChannel methodChannelWithName:CHANNEL_NAME - binaryMessenger:registrar.messenger]; - [channel setMethodCallHandler:^(FlutterMethodCall *call, FlutterResult result) { - NSString *method = [call method]; - NSDictionary *arguments = [call arguments]; - - if ([method isEqualToString:@"getAll"]) { - result(getAllPrefs()); - } else if ([method isEqualToString:@"setBool"]) { - NSString *key = arguments[@"key"]; - NSNumber *value = arguments[@"value"]; - [[NSUserDefaults standardUserDefaults] setBool:value.boolValue forKey:key]; - result(@YES); - } else if ([method isEqualToString:@"setInt"]) { - NSString *key = arguments[@"key"]; - NSNumber *value = arguments[@"value"]; - // int type in Dart can come to native side in a variety of forms - // It is best to store it as is and send it back when needed. - // Platform channel will handle the conversion. - [[NSUserDefaults standardUserDefaults] setValue:value forKey:key]; - result(@YES); - } else if ([method isEqualToString:@"setDouble"]) { - NSString *key = arguments[@"key"]; - NSNumber *value = arguments[@"value"]; - [[NSUserDefaults standardUserDefaults] setDouble:value.doubleValue forKey:key]; - result(@YES); - } else if ([method isEqualToString:@"setString"]) { - NSString *key = arguments[@"key"]; - NSString *value = arguments[@"value"]; - [[NSUserDefaults standardUserDefaults] setValue:value forKey:key]; - result(@YES); - } else if ([method isEqualToString:@"setStringList"]) { - NSString *key = arguments[@"key"]; - NSArray *value = arguments[@"value"]; - [[NSUserDefaults standardUserDefaults] setValue:value forKey:key]; - result(@YES); - } else if ([method isEqualToString:@"commit"]) { - // synchronize is deprecated. - // "this method is unnecessary and shouldn't be used." - result(@YES); - } else if ([method isEqualToString:@"remove"]) { - [[NSUserDefaults standardUserDefaults] removeObjectForKey:arguments[@"key"]]; - result(@YES); - } else if ([method isEqualToString:@"clear"]) { - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - for (NSString *key in getAllPrefs()) { - [defaults removeObjectForKey:key]; - } - result(@YES); - } else { - result(FlutterMethodNotImplemented); - } - }]; -} - -#pragma mark - Private +#import "messages.g.h" static NSMutableDictionary *getAllPrefs() { NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier]; @@ -80,4 +19,50 @@ return filteredPrefs; } +@interface FLTSharedPreferencesPlugin () <UserDefaultsApi> +@end + +@implementation FLTSharedPreferencesPlugin + ++ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar { + FLTSharedPreferencesPlugin *plugin = [[FLTSharedPreferencesPlugin alloc] init]; + UserDefaultsApiSetup(registrar.messenger, plugin); +} + +// Must not return nil unless "error" is set. +- (nullable NSDictionary<NSString *, id> *)getAllWithError: + (FlutterError *_Nullable __autoreleasing *_Nonnull)error { + return getAllPrefs(); +} + +- (void)clearWithError:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + for (NSString *key in getAllPrefs()) { + [defaults removeObjectForKey:key]; + } +} + +- (void)removeKey:(nonnull NSString *)key + error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { + [[NSUserDefaults standardUserDefaults] removeObjectForKey:key]; +} + +- (void)setBoolKey:(nonnull NSString *)key + value:(nonnull NSNumber *)value + error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { + [[NSUserDefaults standardUserDefaults] setBool:value.boolValue forKey:key]; +} + +- (void)setDoubleKey:(nonnull NSString *)key + value:(nonnull NSNumber *)value + error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { + [[NSUserDefaults standardUserDefaults] setDouble:value.doubleValue forKey:key]; +} + +- (void)setValueKey:(nonnull NSString *)key + value:(nonnull NSString *)value + error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { + [[NSUserDefaults standardUserDefaults] setValue:value forKey:key]; +} + @end
diff --git a/packages/shared_preferences/shared_preferences_ios/ios/Classes/messages.g.h b/packages/shared_preferences/shared_preferences_ios/ios/Classes/messages.g.h new file mode 100644 index 0000000..5924023 --- /dev/null +++ b/packages/shared_preferences/shared_preferences_ios/ios/Classes/messages.g.h
@@ -0,0 +1,33 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v1.0.16), do not edit directly. +// See also: https://pub.dev/packages/pigeon +#import <Foundation/Foundation.h> +@protocol FlutterBinaryMessenger; +@protocol FlutterMessageCodec; +@class FlutterError; +@class FlutterStandardTypedData; + +NS_ASSUME_NONNULL_BEGIN + +/// The codec used by UserDefaultsApi. +NSObject<FlutterMessageCodec> *UserDefaultsApiGetCodec(void); + +@protocol UserDefaultsApi +- (void)removeKey:(NSString *)key error:(FlutterError *_Nullable *_Nonnull)error; +- (void)setBoolKey:(NSString *)key + value:(NSNumber *)value + error:(FlutterError *_Nullable *_Nonnull)error; +- (void)setDoubleKey:(NSString *)key + value:(NSNumber *)value + error:(FlutterError *_Nullable *_Nonnull)error; +- (void)setValueKey:(NSString *)key value:(id)value error:(FlutterError *_Nullable *_Nonnull)error; +- (nullable NSDictionary<NSString *, id> *)getAllWithError:(FlutterError *_Nullable *_Nonnull)error; +- (void)clearWithError:(FlutterError *_Nullable *_Nonnull)error; +@end + +extern void UserDefaultsApiSetup(id<FlutterBinaryMessenger> binaryMessenger, + NSObject<UserDefaultsApi> *_Nullable api); + +NS_ASSUME_NONNULL_END
diff --git a/packages/shared_preferences/shared_preferences_ios/ios/Classes/messages.g.m b/packages/shared_preferences/shared_preferences_ios/ios/Classes/messages.g.m new file mode 100644 index 0000000..ea8c45c --- /dev/null +++ b/packages/shared_preferences/shared_preferences_ios/ios/Classes/messages.g.m
@@ -0,0 +1,178 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v1.0.16), do not edit directly. +// See also: https://pub.dev/packages/pigeon +#import "messages.g.h" +#import <Flutter/Flutter.h> + +#if !__has_feature(objc_arc) +#error File requires ARC to be enabled. +#endif + +static NSDictionary<NSString *, id> *wrapResult(id result, FlutterError *error) { + NSDictionary *errorDict = (NSDictionary *)[NSNull null]; + if (error) { + errorDict = @{ + @"code" : (error.code ? error.code : [NSNull null]), + @"message" : (error.message ? error.message : [NSNull null]), + @"details" : (error.details ? error.details : [NSNull null]), + }; + } + return @{ + @"result" : (result ? result : [NSNull null]), + @"error" : errorDict, + }; +} + +@interface UserDefaultsApiCodecReader : FlutterStandardReader +@end +@implementation UserDefaultsApiCodecReader +@end + +@interface UserDefaultsApiCodecWriter : FlutterStandardWriter +@end +@implementation UserDefaultsApiCodecWriter +@end + +@interface UserDefaultsApiCodecReaderWriter : FlutterStandardReaderWriter +@end +@implementation UserDefaultsApiCodecReaderWriter +- (FlutterStandardWriter *)writerWithData:(NSMutableData *)data { + return [[UserDefaultsApiCodecWriter alloc] initWithData:data]; +} +- (FlutterStandardReader *)readerWithData:(NSData *)data { + return [[UserDefaultsApiCodecReader alloc] initWithData:data]; +} +@end + +NSObject<FlutterMessageCodec> *UserDefaultsApiGetCodec() { + static dispatch_once_t s_pred = 0; + static FlutterStandardMessageCodec *s_sharedObject = nil; + dispatch_once(&s_pred, ^{ + UserDefaultsApiCodecReaderWriter *readerWriter = + [[UserDefaultsApiCodecReaderWriter alloc] init]; + s_sharedObject = [FlutterStandardMessageCodec codecWithReaderWriter:readerWriter]; + }); + return s_sharedObject; +} + +void UserDefaultsApiSetup(id<FlutterBinaryMessenger> binaryMessenger, + NSObject<UserDefaultsApi> *api) { + { + FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel + messageChannelWithName:@"dev.flutter.pigeon.UserDefaultsApi.remove" + binaryMessenger:binaryMessenger + codec:UserDefaultsApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(removeKey:error:)], + @"UserDefaultsApi api (%@) doesn't respond to @selector(removeKey:error:)", api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + NSString *arg_key = args[0]; + FlutterError *error; + [api removeKey:arg_key error:&error]; + callback(wrapResult(nil, error)); + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel + messageChannelWithName:@"dev.flutter.pigeon.UserDefaultsApi.setBool" + binaryMessenger:binaryMessenger + codec:UserDefaultsApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(setBoolKey:value:error:)], + @"UserDefaultsApi api (%@) doesn't respond to @selector(setBoolKey:value:error:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + NSString *arg_key = args[0]; + NSNumber *arg_value = args[1]; + FlutterError *error; + [api setBoolKey:arg_key value:arg_value error:&error]; + callback(wrapResult(nil, error)); + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel + messageChannelWithName:@"dev.flutter.pigeon.UserDefaultsApi.setDouble" + binaryMessenger:binaryMessenger + codec:UserDefaultsApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(setDoubleKey:value:error:)], + @"UserDefaultsApi api (%@) doesn't respond to @selector(setDoubleKey:value:error:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + NSString *arg_key = args[0]; + NSNumber *arg_value = args[1]; + FlutterError *error; + [api setDoubleKey:arg_key value:arg_value error:&error]; + callback(wrapResult(nil, error)); + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel + messageChannelWithName:@"dev.flutter.pigeon.UserDefaultsApi.setValue" + binaryMessenger:binaryMessenger + codec:UserDefaultsApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(setValueKey:value:error:)], + @"UserDefaultsApi api (%@) doesn't respond to @selector(setValueKey:value:error:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + NSString *arg_key = args[0]; + id arg_value = args[1]; + FlutterError *error; + [api setValueKey:arg_key value:arg_value error:&error]; + callback(wrapResult(nil, error)); + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel + messageChannelWithName:@"dev.flutter.pigeon.UserDefaultsApi.getAll" + binaryMessenger:binaryMessenger + codec:UserDefaultsApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(getAllWithError:)], + @"UserDefaultsApi api (%@) doesn't respond to @selector(getAllWithError:)", api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + FlutterError *error; + NSDictionary<NSString *, id> *output = [api getAllWithError:&error]; + callback(wrapResult(output, error)); + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel + messageChannelWithName:@"dev.flutter.pigeon.UserDefaultsApi.clear" + binaryMessenger:binaryMessenger + codec:UserDefaultsApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(clearWithError:)], + @"UserDefaultsApi api (%@) doesn't respond to @selector(clearWithError:)", api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + FlutterError *error; + [api clearWithError:&error]; + callback(wrapResult(nil, error)); + }]; + } else { + [channel setMessageHandler:nil]; + } + } +}
diff --git a/packages/shared_preferences/shared_preferences_ios/lib/messages.g.dart b/packages/shared_preferences/shared_preferences_ios/lib/messages.g.dart new file mode 100644 index 0000000..0e76291 --- /dev/null +++ b/packages/shared_preferences/shared_preferences_ios/lib/messages.g.dart
@@ -0,0 +1,179 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v1.0.16), do not edit directly. +// See also: https://pub.dev/packages/pigeon +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name +// @dart = 2.12 +import 'dart:async'; +import 'dart:typed_data' show Uint8List, Int32List, Int64List, Float64List; + +import 'package:flutter/foundation.dart' show WriteBuffer, ReadBuffer; +import 'package:flutter/services.dart'; + +class _UserDefaultsApiCodec extends StandardMessageCodec { + const _UserDefaultsApiCodec(); +} + +class UserDefaultsApi { + /// Constructor for [UserDefaultsApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + UserDefaultsApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec<Object?> codec = _UserDefaultsApiCodec(); + + Future<void> remove(String arg_key) async { + final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>( + 'dev.flutter.pigeon.UserDefaultsApi.remove', codec, + binaryMessenger: _binaryMessenger); + final Map<Object?, Object?>? replyMap = + await channel.send(<Object>[arg_key]) as Map<Object?, Object?>?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map<Object?, Object?> error = + (replyMap['error'] as Map<Object?, Object?>?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future<void> setBool(String arg_key, bool arg_value) async { + final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>( + 'dev.flutter.pigeon.UserDefaultsApi.setBool', codec, + binaryMessenger: _binaryMessenger); + final Map<Object?, Object?>? replyMap = await channel + .send(<Object>[arg_key, arg_value]) as Map<Object?, Object?>?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map<Object?, Object?> error = + (replyMap['error'] as Map<Object?, Object?>?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future<void> setDouble(String arg_key, double arg_value) async { + final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>( + 'dev.flutter.pigeon.UserDefaultsApi.setDouble', codec, + binaryMessenger: _binaryMessenger); + final Map<Object?, Object?>? replyMap = await channel + .send(<Object>[arg_key, arg_value]) as Map<Object?, Object?>?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map<Object?, Object?> error = + (replyMap['error'] as Map<Object?, Object?>?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future<void> setValue(String arg_key, Object arg_value) async { + final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>( + 'dev.flutter.pigeon.UserDefaultsApi.setValue', codec, + binaryMessenger: _binaryMessenger); + final Map<Object?, Object?>? replyMap = await channel + .send(<Object>[arg_key, arg_value]) as Map<Object?, Object?>?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map<Object?, Object?> error = + (replyMap['error'] as Map<Object?, Object?>?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future<Map<String?, Object?>> getAll() async { + final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>( + 'dev.flutter.pigeon.UserDefaultsApi.getAll', codec, + binaryMessenger: _binaryMessenger); + final Map<Object?, Object?>? replyMap = + await channel.send(null) as Map<Object?, Object?>?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map<Object?, Object?> error = + (replyMap['error'] as Map<Object?, Object?>?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return (replyMap['result'] as Map<Object?, Object?>?)! + .cast<String?, Object?>(); + } + } + + Future<void> clear() async { + final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>( + 'dev.flutter.pigeon.UserDefaultsApi.clear', codec, + binaryMessenger: _binaryMessenger); + final Map<Object?, Object?>? replyMap = + await channel.send(null) as Map<Object?, Object?>?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map<Object?, Object?> error = + (replyMap['error'] as Map<Object?, Object?>?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } +}
diff --git a/packages/shared_preferences/shared_preferences_ios/lib/shared_preferences_ios.dart b/packages/shared_preferences/shared_preferences_ios/lib/shared_preferences_ios.dart index 15f1e2f..1063884 100644 --- a/packages/shared_preferences/shared_preferences_ios/lib/shared_preferences_ios.dart +++ b/packages/shared_preferences/shared_preferences_ios/lib/shared_preferences_ios.dart
@@ -2,52 +2,65 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:async'; - import 'package:flutter/services.dart'; import 'package:shared_preferences_platform_interface/shared_preferences_platform_interface.dart'; +import 'messages.g.dart'; -const MethodChannel _kChannel = - MethodChannel('plugins.flutter.io/shared_preferences_ios'); +typedef _Setter = Future<void> Function(String key, Object value); -/// The macOS implementation of [SharedPreferencesStorePlatform]. -/// -/// This class implements the `package:shared_preferences` functionality for iOS. +/// iOS implementation of shared_preferences. class SharedPreferencesIOS extends SharedPreferencesStorePlatform { - /// Registers this class as the default instance of [SharedPreferencesStorePlatform]. + final UserDefaultsApi _api = UserDefaultsApi(); + late final Map<String, _Setter> _setters = <String, _Setter>{ + 'Bool': (String key, Object value) { + return _api.setBool(key, value as bool); + }, + 'Double': (String key, Object value) { + return _api.setDouble(key, value as double); + }, + 'Int': (String key, Object value) { + return _api.setValue(key, value as int); + }, + 'String': (String key, Object value) { + return _api.setValue(key, value as String); + }, + 'StringList': (String key, Object value) { + return _api.setValue(key, value as List<String?>); + }, + }; + + /// Registers this class as the default instance of [PathProviderPlatform]. static void registerWith() { SharedPreferencesStorePlatform.instance = SharedPreferencesIOS(); } @override - Future<bool> remove(String key) async { - return (await _kChannel.invokeMethod<bool>( - 'remove', - <String, dynamic>{'key': key}, - ))!; - } - - @override - Future<bool> setValue(String valueType, String key, Object value) async { - return (await _kChannel.invokeMethod<bool>( - 'set$valueType', - <String, dynamic>{'key': key, 'value': value}, - ))!; - } - - @override Future<bool> clear() async { - return (await _kChannel.invokeMethod<bool>('clear'))!; + await _api.clear(); + return true; } @override Future<Map<String, Object>> getAll() async { - final Map<String, Object>? preferences = - await _kChannel.invokeMapMethod<String, Object>('getAll'); + final Map<String?, Object?> result = await _api.getAll(); + return result.cast<String, Object>(); + } - if (preferences == null) { - return <String, Object>{}; + @override + Future<bool> remove(String key) async { + await _api.remove(key); + return true; + } + + @override + Future<bool> setValue(String valueType, String key, Object value) async { + final _Setter? setter = _setters[valueType]; + if (setter == null) { + throw PlatformException( + code: 'InvalidOperation', + message: '"$valueType" is not a supported type.'); } - return preferences; + await setter(key, value); + return true; } }
diff --git a/packages/shared_preferences/shared_preferences_ios/pigeons/copyright_header.txt b/packages/shared_preferences/shared_preferences_ios/pigeons/copyright_header.txt new file mode 100644 index 0000000..fb682b1 --- /dev/null +++ b/packages/shared_preferences/shared_preferences_ios/pigeons/copyright_header.txt
@@ -0,0 +1,3 @@ +Copyright 2013 The Flutter Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. \ No newline at end of file
diff --git a/packages/shared_preferences/shared_preferences_ios/pigeons/messages.dart b/packages/shared_preferences/shared_preferences_ios/pigeons/messages.dart new file mode 100644 index 0000000..6b5648f --- /dev/null +++ b/packages/shared_preferences/shared_preferences_ios/pigeons/messages.dart
@@ -0,0 +1,22 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:pigeon/pigeon.dart'; + +@ConfigurePigeon(PigeonOptions( + dartOut: 'lib/messages.g.dart', + dartTestOut: 'test/messages.g.dart', + objcHeaderOut: 'ios/Classes/messages.g.h', + objcSourceOut: 'ios/Classes/messages.g.m', + copyrightHeader: 'pigeons/copyright_header.txt', +)) +@HostApi(dartHostTestHandler: 'TestUserDefaultsApi') +abstract class UserDefaultsApi { + void remove(String key); + void setBool(String key, bool value); + void setDouble(String key, double value); + void setValue(String key, Object value); + Map<String?, Object?> getAll(); + void clear(); +}
diff --git a/packages/shared_preferences/shared_preferences_ios/pubspec.yaml b/packages/shared_preferences/shared_preferences_ios/pubspec.yaml index 68ab035..33bf5ba 100644 --- a/packages/shared_preferences/shared_preferences_ios/pubspec.yaml +++ b/packages/shared_preferences/shared_preferences_ios/pubspec.yaml
@@ -2,7 +2,7 @@ description: iOS implementation of the shared_preferences plugin repository: https://github.com/flutter/plugins/tree/main/packages/shared_preferences/shared_preferences_ios issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+shared_preferences%22 -version: 2.0.10 +version: 2.1.0 environment: sdk: ">=2.14.0 <3.0.0" @@ -13,8 +13,8 @@ implements: shared_preferences platforms: ios: - pluginClass: FLTSharedPreferencesPlugin dartPluginClass: SharedPreferencesIOS + pluginClass: FLTSharedPreferencesPlugin dependencies: flutter: @@ -24,3 +24,4 @@ dev_dependencies: flutter_test: sdk: flutter + pigeon: ^1.0.16
diff --git a/packages/shared_preferences/shared_preferences_ios/test/messages.g.dart b/packages/shared_preferences/shared_preferences_ios/test/messages.g.dart new file mode 100644 index 0000000..12fbc06 --- /dev/null +++ b/packages/shared_preferences/shared_preferences_ios/test/messages.g.dart
@@ -0,0 +1,145 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v1.0.16), do not edit directly. +// See also: https://pub.dev/packages/pigeon +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import +// @dart = 2.12 +import 'dart:async'; +import 'dart:typed_data' show Uint8List, Int32List, Int64List, Float64List; +import 'package:flutter/foundation.dart' show WriteBuffer, ReadBuffer; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:shared_preferences_ios/messages.g.dart'; + +class _TestUserDefaultsApiCodec extends StandardMessageCodec { + const _TestUserDefaultsApiCodec(); +} + +abstract class TestUserDefaultsApi { + static const MessageCodec<Object?> codec = _TestUserDefaultsApiCodec(); + + void remove(String key); + void setBool(String key, bool value); + void setDouble(String key, double value); + void setValue(String key, Object value); + Map<String?, Object?> getAll(); + void clear(); + static void setup(TestUserDefaultsApi? api, + {BinaryMessenger? binaryMessenger}) { + { + final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>( + 'dev.flutter.pigeon.UserDefaultsApi.remove', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.UserDefaultsApi.remove was null.'); + final List<Object?> args = (message as List<Object?>?)!; + final String? arg_key = (args[0] as String?); + assert(arg_key != null, + 'Argument for dev.flutter.pigeon.UserDefaultsApi.remove was null, expected non-null String.'); + api.remove(arg_key!); + return <Object?, Object?>{}; + }); + } + } + { + final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>( + 'dev.flutter.pigeon.UserDefaultsApi.setBool', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.UserDefaultsApi.setBool was null.'); + final List<Object?> args = (message as List<Object?>?)!; + final String? arg_key = (args[0] as String?); + assert(arg_key != null, + 'Argument for dev.flutter.pigeon.UserDefaultsApi.setBool was null, expected non-null String.'); + final bool? arg_value = (args[1] as bool?); + assert(arg_value != null, + 'Argument for dev.flutter.pigeon.UserDefaultsApi.setBool was null, expected non-null bool.'); + api.setBool(arg_key!, arg_value!); + return <Object?, Object?>{}; + }); + } + } + { + final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>( + 'dev.flutter.pigeon.UserDefaultsApi.setDouble', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.UserDefaultsApi.setDouble was null.'); + final List<Object?> args = (message as List<Object?>?)!; + final String? arg_key = (args[0] as String?); + assert(arg_key != null, + 'Argument for dev.flutter.pigeon.UserDefaultsApi.setDouble was null, expected non-null String.'); + final double? arg_value = (args[1] as double?); + assert(arg_value != null, + 'Argument for dev.flutter.pigeon.UserDefaultsApi.setDouble was null, expected non-null double.'); + api.setDouble(arg_key!, arg_value!); + return <Object?, Object?>{}; + }); + } + } + { + final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>( + 'dev.flutter.pigeon.UserDefaultsApi.setValue', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.UserDefaultsApi.setValue was null.'); + final List<Object?> args = (message as List<Object?>?)!; + final String? arg_key = (args[0] as String?); + assert(arg_key != null, + 'Argument for dev.flutter.pigeon.UserDefaultsApi.setValue was null, expected non-null String.'); + final Object? arg_value = (args[1] as Object?); + assert(arg_value != null, + 'Argument for dev.flutter.pigeon.UserDefaultsApi.setValue was null, expected non-null Object.'); + api.setValue(arg_key!, arg_value!); + return <Object?, Object?>{}; + }); + } + } + { + final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>( + 'dev.flutter.pigeon.UserDefaultsApi.getAll', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + // ignore message + final Map<String?, Object?> output = api.getAll(); + return <Object?, Object?>{'result': output}; + }); + } + } + { + final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>( + 'dev.flutter.pigeon.UserDefaultsApi.clear', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + // ignore message + api.clear(); + return <Object?, Object?>{}; + }); + } + } + } +}
diff --git a/packages/shared_preferences/shared_preferences_ios/test/shared_preferences_ios_test.dart b/packages/shared_preferences/shared_preferences_ios/test/shared_preferences_ios_test.dart index 8eb23f2..efafb23 100644 --- a/packages/shared_preferences/shared_preferences_ios/test/shared_preferences_ios_test.dart +++ b/packages/shared_preferences/shared_preferences_ios/test/shared_preferences_ios_test.dart
@@ -5,113 +5,101 @@ import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:shared_preferences_ios/shared_preferences_ios.dart'; -import 'package:shared_preferences_platform_interface/method_channel_shared_preferences.dart'; import 'package:shared_preferences_platform_interface/shared_preferences_platform_interface.dart'; +import 'messages.g.dart'; + +class _MockSharedPreferencesApi implements TestUserDefaultsApi { + final Map<String, Object> items = <String, Object>{}; + + @override + Map<String?, Object?> getAll() { + return items; + } + + @override + void remove(String key) { + items.remove(key); + } + + @override + void setBool(String key, bool value) { + items[key] = value; + } + + @override + void setDouble(String key, double value) { + items[key] = value; + } + + @override + void setValue(String key, Object value) { + items[key] = value; + } + + @override + void clear() { + items.clear(); + } +} + void main() { TestWidgetsFlutterBinding.ensureInitialized(); + _MockSharedPreferencesApi api = _MockSharedPreferencesApi(); + SharedPreferencesIOS plugin = SharedPreferencesIOS(); - group(MethodChannelSharedPreferencesStore, () { - const MethodChannel channel = MethodChannel( - 'plugins.flutter.io/shared_preferences_ios', - ); + setUp(() { + api = _MockSharedPreferencesApi(); + TestUserDefaultsApi.setup(api); + plugin = SharedPreferencesIOS(); + }); - const Map<String, Object> kTestValues = <String, Object>{ - 'flutter.String': 'hello world', - 'flutter.Bool': true, - 'flutter.Int': 42, - 'flutter.Double': 3.14159, - 'flutter.StringList': <String>['foo', 'bar'], - }; - // Create a dummy in-memory implementation to back the mocked method channel - // API to simplify validation of the expected calls. - late InMemorySharedPreferencesStore testData; + test('registerWith', () { + SharedPreferencesIOS.registerWith(); + expect( + SharedPreferencesStorePlatform.instance, isA<SharedPreferencesIOS>()); + }); - final List<MethodCall> log = <MethodCall>[]; - late SharedPreferencesStorePlatform store; + test('remove', () async { + api.items['flutter.hi'] = 'world'; + expect(await plugin.remove('flutter.hi'), isTrue); + expect(api.items.containsKey('flutter.hi'), isFalse); + }); - setUp(() async { - testData = InMemorySharedPreferencesStore.empty(); + test('clear', () async { + api.items['flutter.hi'] = 'world'; + expect(await plugin.clear(), isTrue); + expect(api.items.containsKey('flutter.hi'), isFalse); + }); - channel.setMockMethodCallHandler((MethodCall methodCall) async { - log.add(methodCall); - if (methodCall.method == 'getAll') { - return await testData.getAll(); - } - if (methodCall.method == 'remove') { - final String key = methodCall.arguments['key'] as String; - return await testData.remove(key); - } - if (methodCall.method == 'clear') { - return await testData.clear(); - } - final RegExp setterRegExp = RegExp(r'set(.*)'); - final Match? match = setterRegExp.matchAsPrefix(methodCall.method); - if (match?.groupCount == 1) { - final String valueType = match!.group(1)!; - final String key = methodCall.arguments['key'] as String; - final Object value = methodCall.arguments['value'] as Object; - return await testData.setValue(valueType, key, value); - } - fail('Unexpected method call: ${methodCall.method}'); - }); - log.clear(); - }); + test('getAll', () async { + api.items['flutter.hi'] = 'world'; + api.items['flutter.bye'] = 'dust'; + final Map<String?, Object?> all = await plugin.getAll(); + expect(all.length, 2); + expect(all['flutter.hi'], api.items['flutter.hi']); + expect(all['flutter.bye'], api.items['flutter.bye']); + }); - test('registered instance', () { - SharedPreferencesIOS.registerWith(); - expect( - SharedPreferencesStorePlatform.instance, isA<SharedPreferencesIOS>()); - }); + test('setValue', () async { + expect(await plugin.setValue('Bool', 'flutter.Bool', true), isTrue); + expect(api.items['flutter.Bool'], true); + expect(await plugin.setValue('Double', 'flutter.Double', 1.5), isTrue); + expect(api.items['flutter.Double'], 1.5); + expect(await plugin.setValue('Int', 'flutter.Int', 12), isTrue); + expect(api.items['flutter.Int'], 12); + expect(await plugin.setValue('String', 'flutter.String', 'hi'), isTrue); + expect(api.items['flutter.String'], 'hi'); + expect( + await plugin + .setValue('StringList', 'flutter.StringList', <String>['hi']), + isTrue); + expect(api.items['flutter.StringList'], <String>['hi']); + }); - test('getAll', () async { - store = SharedPreferencesIOS(); - testData = InMemorySharedPreferencesStore.withData(kTestValues); - expect(await store.getAll(), kTestValues); - expect(log.single.method, 'getAll'); - }); - - test('remove', () async { - store = SharedPreferencesIOS(); - testData = InMemorySharedPreferencesStore.withData(kTestValues); - expect(await store.remove('flutter.String'), true); - expect(await store.remove('flutter.Bool'), true); - expect(await store.remove('flutter.Int'), true); - expect(await store.remove('flutter.Double'), true); - expect(await testData.getAll(), <String, dynamic>{ - 'flutter.StringList': <String>['foo', 'bar'], - }); - - expect(log, hasLength(4)); - for (final MethodCall call in log) { - expect(call.method, 'remove'); - } - }); - - test('setValue', () async { - store = SharedPreferencesIOS(); - expect(await testData.getAll(), isEmpty); - for (final String key in kTestValues.keys) { - final Object value = kTestValues[key]!; - expect(await store.setValue(key.split('.').last, key, value), true); - } - expect(await testData.getAll(), kTestValues); - - expect(log, hasLength(5)); - expect(log[0].method, 'setString'); - expect(log[1].method, 'setBool'); - expect(log[2].method, 'setInt'); - expect(log[3].method, 'setDouble'); - expect(log[4].method, 'setStringList'); - }); - - test('clear', () async { - store = SharedPreferencesIOS(); - testData = InMemorySharedPreferencesStore.withData(kTestValues); - expect(await testData.getAll(), isNotEmpty); - expect(await store.clear(), true); - expect(await testData.getAll(), isEmpty); - expect(log.single.method, 'clear'); - }); + test('setValue with unsupported type', () { + expect(() async { + await plugin.setValue('Map', 'flutter.key', <String, String>{}); + }, throwsA(isA<PlatformException>())); }); }