Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

Commit 276cfd4

Browse files
[shared_preferences] Convert macOS to Pigeon (#6914)
* Add Pigeon and update Dart, based on iOS implementation * Update Swift implementation * Update Swift tests * Adjust Dart test and add Pigeon TODOs * Version bump * Format * Update to Pigeon 5.0 for Swift warning fix
1 parent 3a6f63b commit 276cfd4

File tree

11 files changed

+652
-233
lines changed

11 files changed

+652
-233
lines changed

packages/shared_preferences/shared_preferences_macos/CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
## NEXT
1+
## 2.0.5
22

3+
* Converts platform channel to Pigeon.
34
* Updates code for `no_leading_underscores_for_local_identifiers` lint.
45
* Updates minimum Flutter version to 2.10.
56

packages/shared_preferences/shared_preferences_macos/example/macos/RunnerTests/RunnerTests.swift

+35-65
Original file line numberDiff line numberDiff line change
@@ -4,85 +4,55 @@
44

55
import FlutterMacOS
66
import XCTest
7-
import shared_preferences_macos
7+
@testable import shared_preferences_macos
88

99
class RunnerTests: XCTestCase {
10-
func testHandlesCommitNoOp() throws {
10+
func testSetAndGet() throws {
1111
let plugin = SharedPreferencesPlugin()
12-
let call = FlutterMethodCall(methodName: "commit", arguments: nil)
13-
var called = false
14-
plugin.handle(
15-
call,
16-
result: { (result: Any?) -> Void in
17-
called = true
18-
XCTAssert(result as? Bool == true)
19-
})
20-
XCTAssert(called)
12+
13+
plugin.setBool(key: "flutter.aBool", value: true)
14+
plugin.setDouble(key: "flutter.aDouble", value: 3.14)
15+
plugin.setValue(key: "flutter.anInt", value: 42)
16+
plugin.setValue(key: "flutter.aString", value: "hello world")
17+
plugin.setValue(key: "flutter.aStringList", value: ["hello", "world"])
18+
19+
let storedValues = plugin.getAll()
20+
XCTAssertEqual(storedValues["flutter.aBool"] as? Bool, true)
21+
XCTAssertEqual(storedValues["flutter.aDouble"] as! Double, 3.14, accuracy: 0.0001)
22+
XCTAssertEqual(storedValues["flutter.anInt"] as? Int, 42)
23+
XCTAssertEqual(storedValues["flutter.aString"] as? String, "hello world")
24+
XCTAssertEqual(storedValues["flutter.aStringList"] as? Array<String>, ["hello", "world"])
2125
}
2226

23-
func testSetAndGet() throws {
27+
func testRemove() throws {
2428
let plugin = SharedPreferencesPlugin()
25-
let setCall = FlutterMethodCall(
26-
methodName: "setInt",
27-
arguments: [
28-
"key": "flutter.foo",
29-
"value": 42,
30-
])
31-
plugin.handle(
32-
setCall,
33-
result: { (result: Any?) -> Void in
34-
XCTAssert(result as? Bool == true)
35-
})
29+
let testKey = "flutter.foo"
30+
plugin.setValue(key: testKey, value: 42)
31+
32+
// Make sure there is something to remove, so the test can't pass due to a set failure.
33+
let preRemovalValues = plugin.getAll()
34+
XCTAssertEqual(preRemovalValues[testKey] as? Int, 42)
35+
36+
// Then verify that removing it works.
37+
plugin.remove(key: testKey)
3638

37-
var value: Int?
38-
plugin.handle(
39-
FlutterMethodCall(methodName: "getAll", arguments: nil),
40-
result: { (result: Any?) -> Void in
41-
if let prefs = result as? [String: Any] {
42-
value = prefs["flutter.foo"] as? Int
43-
}
44-
})
45-
XCTAssertEqual(value, 42)
39+
let finalValues = plugin.getAll()
40+
XCTAssertNil(finalValues[testKey] as Any?)
4641
}
4742

4843
func testClear() throws {
4944
let plugin = SharedPreferencesPlugin()
50-
let setCall = FlutterMethodCall(
51-
methodName: "setInt",
52-
arguments: [
53-
"key": "flutter.foo",
54-
"value": 42,
55-
])
56-
plugin.handle(setCall, result: { (result: Any?) -> Void in })
45+
let testKey = "flutter.foo"
46+
plugin.setValue(key: testKey, value: 42)
5747

5848
// Make sure there is something to clear, so the test can't pass due to a set failure.
59-
let getCall = FlutterMethodCall(methodName: "getAll", arguments: nil)
60-
var value: Int?
61-
plugin.handle(
62-
getCall,
63-
result: { (result: Any?) -> Void in
64-
if let prefs = result as? [String: Any] {
65-
value = prefs["flutter.foo"] as? Int
66-
}
67-
})
68-
XCTAssertEqual(value, 42)
49+
let preRemovalValues = plugin.getAll()
50+
XCTAssertEqual(preRemovalValues[testKey] as? Int, 42)
6951

70-
// Clear the value.
71-
plugin.handle(
72-
FlutterMethodCall(methodName: "clear", arguments: nil),
73-
result: { (result: Any?) -> Void in
74-
XCTAssert(result as? Bool == true)
75-
})
52+
// Then verify that clearing works.
53+
plugin.clear()
7654

77-
// Get the value again, which should clear |value|.
78-
plugin.handle(
79-
getCall,
80-
result: { (result: Any?) -> Void in
81-
if let prefs = result as? [String: Any] {
82-
value = prefs["flutter.foo"] as? Int
83-
XCTAssert(prefs.isEmpty)
84-
}
85-
})
86-
XCTAssertEqual(value, nil)
55+
let finalValues = plugin.getAll()
56+
XCTAssertNil(finalValues[testKey] as Any?)
8757
}
8858
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
// Autogenerated from Pigeon (v5.0.0), do not edit directly.
5+
// See also: https://pub.dev/packages/pigeon
6+
// 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, unnecessary_import
7+
import 'dart:async';
8+
import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List;
9+
10+
import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer;
11+
import 'package:flutter/services.dart';
12+
13+
class UserDefaultsApi {
14+
/// Constructor for [UserDefaultsApi]. The [binaryMessenger] named argument is
15+
/// available for dependency injection. If it is left null, the default
16+
/// BinaryMessenger will be used which routes to the host platform.
17+
UserDefaultsApi({BinaryMessenger? binaryMessenger})
18+
: _binaryMessenger = binaryMessenger;
19+
final BinaryMessenger? _binaryMessenger;
20+
21+
static const MessageCodec<Object?> codec = StandardMessageCodec();
22+
23+
Future<void> remove(String arg_key) async {
24+
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
25+
'dev.flutter.pigeon.UserDefaultsApi.remove', codec,
26+
binaryMessenger: _binaryMessenger);
27+
final List<Object?>? replyList =
28+
await channel.send(<Object?>[arg_key]) as List<Object?>?;
29+
if (replyList == null) {
30+
throw PlatformException(
31+
code: 'channel-error',
32+
message: 'Unable to establish connection on channel.',
33+
);
34+
} else if (replyList.length > 1) {
35+
throw PlatformException(
36+
code: replyList[0]! as String,
37+
message: replyList[1] as String?,
38+
details: replyList[2],
39+
);
40+
} else {
41+
return;
42+
}
43+
}
44+
45+
Future<void> setBool(String arg_key, bool arg_value) async {
46+
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
47+
'dev.flutter.pigeon.UserDefaultsApi.setBool', codec,
48+
binaryMessenger: _binaryMessenger);
49+
final List<Object?>? replyList =
50+
await channel.send(<Object?>[arg_key, arg_value]) as List<Object?>?;
51+
if (replyList == null) {
52+
throw PlatformException(
53+
code: 'channel-error',
54+
message: 'Unable to establish connection on channel.',
55+
);
56+
} else if (replyList.length > 1) {
57+
throw PlatformException(
58+
code: replyList[0]! as String,
59+
message: replyList[1] as String?,
60+
details: replyList[2],
61+
);
62+
} else {
63+
return;
64+
}
65+
}
66+
67+
Future<void> setDouble(String arg_key, double arg_value) async {
68+
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
69+
'dev.flutter.pigeon.UserDefaultsApi.setDouble', codec,
70+
binaryMessenger: _binaryMessenger);
71+
final List<Object?>? replyList =
72+
await channel.send(<Object?>[arg_key, arg_value]) as List<Object?>?;
73+
if (replyList == null) {
74+
throw PlatformException(
75+
code: 'channel-error',
76+
message: 'Unable to establish connection on channel.',
77+
);
78+
} else if (replyList.length > 1) {
79+
throw PlatformException(
80+
code: replyList[0]! as String,
81+
message: replyList[1] as String?,
82+
details: replyList[2],
83+
);
84+
} else {
85+
return;
86+
}
87+
}
88+
89+
Future<void> setValue(String arg_key, Object arg_value) async {
90+
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
91+
'dev.flutter.pigeon.UserDefaultsApi.setValue', codec,
92+
binaryMessenger: _binaryMessenger);
93+
final List<Object?>? replyList =
94+
await channel.send(<Object?>[arg_key, arg_value]) as List<Object?>?;
95+
if (replyList == null) {
96+
throw PlatformException(
97+
code: 'channel-error',
98+
message: 'Unable to establish connection on channel.',
99+
);
100+
} else if (replyList.length > 1) {
101+
throw PlatformException(
102+
code: replyList[0]! as String,
103+
message: replyList[1] as String?,
104+
details: replyList[2],
105+
);
106+
} else {
107+
return;
108+
}
109+
}
110+
111+
Future<Map<String?, Object?>> getAll() async {
112+
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
113+
'dev.flutter.pigeon.UserDefaultsApi.getAll', codec,
114+
binaryMessenger: _binaryMessenger);
115+
final List<Object?>? replyList = await channel.send(null) as List<Object?>?;
116+
if (replyList == null) {
117+
throw PlatformException(
118+
code: 'channel-error',
119+
message: 'Unable to establish connection on channel.',
120+
);
121+
} else if (replyList.length > 1) {
122+
throw PlatformException(
123+
code: replyList[0]! as String,
124+
message: replyList[1] as String?,
125+
details: replyList[2],
126+
);
127+
} else if (replyList[0] == null) {
128+
throw PlatformException(
129+
code: 'null-error',
130+
message: 'Host platform returned null value for non-null return value.',
131+
);
132+
} else {
133+
return (replyList[0] as Map<Object?, Object?>?)!.cast<String?, Object?>();
134+
}
135+
}
136+
137+
Future<void> clear() async {
138+
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
139+
'dev.flutter.pigeon.UserDefaultsApi.clear', codec,
140+
binaryMessenger: _binaryMessenger);
141+
final List<Object?>? replyList = await channel.send(null) as List<Object?>?;
142+
if (replyList == null) {
143+
throw PlatformException(
144+
code: 'channel-error',
145+
message: 'Unable to establish connection on channel.',
146+
);
147+
} else if (replyList.length > 1) {
148+
throw PlatformException(
149+
code: replyList[0]! as String,
150+
message: replyList[1] as String?,
151+
details: replyList[2],
152+
);
153+
} else {
154+
return;
155+
}
156+
}
157+
}

packages/shared_preferences/shared_preferences_macos/lib/shared_preferences_macos.dart

+41-27
Original file line numberDiff line numberDiff line change
@@ -2,52 +2,66 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
import 'dart:async';
6-
75
import 'package:flutter/services.dart';
86
import 'package:shared_preferences_platform_interface/shared_preferences_platform_interface.dart';
7+
import 'messages.g.dart';
98

10-
const MethodChannel _kChannel =
11-
MethodChannel('plugins.flutter.io/shared_preferences_macos');
9+
typedef _Setter = Future<void> Function(String key, Object value);
1210

13-
/// The macOS implementation of [SharedPreferencesStorePlatform].
14-
///
15-
/// This class implements the `package:shared_preferences` functionality for macOS.
11+
/// macOS implementation of shared_preferences.
1612
class SharedPreferencesMacOS extends SharedPreferencesStorePlatform {
17-
/// Registers this class as the default instance of [SharedPreferencesStorePlatform].
13+
final UserDefaultsApi _api = UserDefaultsApi();
14+
late final Map<String, _Setter> _setters = <String, _Setter>{
15+
'Bool': (String key, Object value) {
16+
return _api.setBool(key, value as bool);
17+
},
18+
'Double': (String key, Object value) {
19+
return _api.setDouble(key, value as double);
20+
},
21+
'Int': (String key, Object value) {
22+
return _api.setValue(key, value as int);
23+
},
24+
'String': (String key, Object value) {
25+
return _api.setValue(key, value as String);
26+
},
27+
'StringList': (String key, Object value) {
28+
return _api.setValue(key, value as List<String?>);
29+
},
30+
};
31+
32+
/// Registers this class as the default instance of
33+
/// [SharedPreferencesStorePlatform].
1834
static void registerWith() {
1935
SharedPreferencesStorePlatform.instance = SharedPreferencesMacOS();
2036
}
2137

2238
@override
23-
Future<bool> remove(String key) async {
24-
return (await _kChannel.invokeMethod<bool>(
25-
'remove',
26-
<String, dynamic>{'key': key},
27-
))!;
39+
Future<bool> clear() async {
40+
await _api.clear();
41+
return true;
2842
}
2943

3044
@override
31-
Future<bool> setValue(String valueType, String key, Object value) async {
32-
return (await _kChannel.invokeMethod<bool>(
33-
'set$valueType',
34-
<String, dynamic>{'key': key, 'value': value},
35-
))!;
45+
Future<Map<String, Object>> getAll() async {
46+
final Map<String?, Object?> result = await _api.getAll();
47+
return result.cast<String, Object>();
3648
}
3749

3850
@override
39-
Future<bool> clear() async {
40-
return (await _kChannel.invokeMethod<bool>('clear'))!;
51+
Future<bool> remove(String key) async {
52+
await _api.remove(key);
53+
return true;
4154
}
4255

4356
@override
44-
Future<Map<String, Object>> getAll() async {
45-
final Map<String, Object>? preferences =
46-
await _kChannel.invokeMapMethod<String, Object>('getAll');
47-
48-
if (preferences == null) {
49-
return <String, Object>{};
57+
Future<bool> setValue(String valueType, String key, Object value) async {
58+
final _Setter? setter = _setters[valueType];
59+
if (setter == null) {
60+
throw PlatformException(
61+
code: 'InvalidOperation',
62+
message: '"$valueType" is not a supported type.');
5063
}
51-
return preferences;
64+
await setter(key, value);
65+
return true;
5266
}
5367
}

0 commit comments

Comments
 (0)