Skip to content

Commit e6f1ede

Browse files
authored
Merge pull request #16
Fix Darwin app group review issues
2 parents 1f86bdf + 9b25ce1 commit e6f1ede

11 files changed

Lines changed: 338 additions & 92 deletions

File tree

.github/workflows/ci.yml

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- main
8+
9+
permissions:
10+
contents: read
11+
12+
concurrency:
13+
group: ci-${{ github.workflow }}-${{ github.ref }}
14+
cancel-in-progress: true
15+
16+
env:
17+
FLUTTER_VERSION: "3.41.5"
18+
19+
jobs:
20+
flutter:
21+
name: Flutter analysis and package checks
22+
runs-on: ubuntu-latest
23+
24+
steps:
25+
- name: Check out repository
26+
uses: actions/checkout@v4
27+
28+
- name: Set up Flutter
29+
uses: subosito/flutter-action@v2
30+
with:
31+
flutter-version: ${{ env.FLUTTER_VERSION }}
32+
channel: stable
33+
cache: true
34+
35+
- name: Install root dependencies
36+
run: flutter pub get
37+
38+
- name: Install example dependencies
39+
working-directory: example
40+
run: flutter pub get
41+
42+
- name: Verify Dart formatting
43+
run: dart format --output=none --set-exit-if-changed .
44+
45+
- name: Analyze
46+
run: flutter analyze
47+
48+
- name: Test
49+
run: flutter test
50+
51+
- name: Validate package publishing
52+
run: flutter pub publish --dry-run
53+
54+
darwin:
55+
name: Darwin integration checks
56+
runs-on: macos-latest
57+
58+
steps:
59+
- name: Check out repository
60+
uses: actions/checkout@v4
61+
62+
- name: Set up Flutter
63+
uses: subosito/flutter-action@v2
64+
with:
65+
flutter-version: ${{ env.FLUTTER_VERSION }}
66+
channel: stable
67+
cache: true
68+
69+
- name: Enable macOS desktop
70+
run: flutter config --enable-macos-desktop
71+
72+
- name: Install dependencies
73+
run: flutter pub get
74+
75+
- name: Install example dependencies
76+
working-directory: example
77+
run: flutter pub get
78+
79+
- name: Validate CocoaPods spec
80+
run: |
81+
pod ipc spec darwin/shared_preference_app_group.podspec > /tmp/shared_preference_app_group.podspec.json
82+
ruby -rjson -e '
83+
spec = JSON.parse(File.read("/tmp/shared_preference_app_group.podspec.json"))
84+
abort("podspec version mismatch") unless spec["version"] == "2.1.0"
85+
abort("missing iOS platform") unless spec.dig("platforms", "ios") == "13.0"
86+
abort("missing macOS platform") unless spec.dig("platforms", "osx") == "10.15"
87+
abort("missing Flutter dependency") unless spec.dig("ios", "dependencies", "Flutter")
88+
abort("missing FlutterMacOS dependency") unless spec.dig("osx", "dependencies", "FlutterMacOS")
89+
'
90+
91+
- name: Validate Swift Package manifest
92+
run: |
93+
mkdir -p darwin/FlutterFramework/Sources/FlutterFramework
94+
cat > darwin/FlutterFramework/Package.swift <<'SWIFT'
95+
// swift-tools-version: 5.9
96+
import PackageDescription
97+
98+
let package = Package(
99+
name: "FlutterFramework",
100+
products: [
101+
.library(name: "FlutterFramework", targets: ["FlutterFramework"]),
102+
],
103+
targets: [
104+
.target(name: "FlutterFramework"),
105+
]
106+
)
107+
SWIFT
108+
touch darwin/FlutterFramework/Sources/FlutterFramework/FlutterFramework.swift
109+
swift package describe --package-path darwin/shared_preference_app_group
110+
111+
- name: Install iOS CocoaPods dependencies
112+
working-directory: example/ios
113+
run: pod install --repo-update
114+
115+
- name: Build iOS example for simulator
116+
working-directory: example
117+
run: flutter build ios --simulator --debug
118+
119+
- name: Generate macOS example project
120+
working-directory: example
121+
run: flutter create --platforms=macos .
122+
123+
- name: Build macOS example
124+
working-directory: example
125+
run: flutter build macos --debug

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
[![pub package](https://img.shields.io/pub/v/shared_preference_app_group.svg)](https://pub.dev/packages/shared_preference_app_group)
44

5-
Shared preference supporting iOS App Group capability (using `-[NSUserDefaults initWithSuiteName:]`)
5+
Shared preferences for iOS and macOS App Groups (using `-[NSUserDefaults initWithSuiteName:]`)
66

77
> Note: Supports iOS and macOS
88
@@ -17,7 +17,7 @@ This plugin currently supports:
1717

1818
The iOS and macOS implementations support both CocoaPods and Swift Package Manager. Swift Package Manager is the default dependency manager for newer Flutter projects, while CocoaPods remains supported for existing projects.
1919

20-
> On macOS, App Groups require the app to use the App Sandbox capability and to list the group identifier under `com.apple.security.application-groups` in its `.entitlements` file. macOS prefixes the suite name with your team identifier.
20+
> On macOS, App Groups require the app to use the App Sandbox capability and to list the group identifier under `com.apple.security.application-groups` in its `.entitlements` file. The value passed to `setAppGroup` must exactly match an identifier in the entitlements file; this plugin does not add a team identifier automatically.
2121
2222
## Usage
2323

darwin/shared_preference_app_group.podspec

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
#
55
Pod::Spec.new do |s|
66
s.name = 'shared_preference_app_group'
7-
s.version = '2.0.0'
8-
s.summary = 'Shared preference supporting iOS App Group capability'
7+
s.version = '2.1.0'
8+
s.summary = 'Shared preferences for iOS and macOS App Groups'
99
s.description = <<-DESC
10-
Shared preference supporting iOS App Group capability
10+
Shared preferences for iOS and macOS App Groups
1111
DESC
1212
s.homepage = 'https://github.com/patrick-fu/flutter_shared_preference_app_group'
1313
s.license = { :file => '../LICENSE' }

darwin/shared_preference_app_group/Sources/shared_preference_app_group/SharedPreferenceAppGroupPlugin.m

Lines changed: 65 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,32 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
4444
#pragma mark - Handle method call
4545

4646
- (void)setAppGroup:(FlutterMethodCall *)call result:(FlutterResult)result {
47-
self.appGroup = call.arguments[@"appGroup"];
48-
self.userDefaults = [[NSUserDefaults alloc] initWithSuiteName:_appGroup];
47+
NSDictionary *arguments = call.arguments;
48+
if (![arguments isKindOfClass:[NSDictionary class]]) {
49+
result([FlutterError errorWithCode:@"INVALID_ARGUMENTS" message:@"`setAppGroup` arguments must be a map" details:nil]);
50+
return;
51+
}
52+
53+
id appGroup = arguments[@"appGroup"];
54+
if (![appGroup isKindOfClass:[NSString class]] || ((NSString *)appGroup).length == 0) {
55+
result([FlutterError errorWithCode:@"INVALID_APP_GROUP" message:@"`appGroup` must be a non-empty string" details:nil]);
56+
return;
57+
}
58+
59+
self.appGroup = appGroup;
60+
self.userDefaults = [[NSUserDefaults alloc] initWithSuiteName:self.appGroup];
61+
if (!self.userDefaults) {
62+
result([FlutterError errorWithCode:@"APP_GROUP_COULD_NOT_BE_OPENED" message:@"Could not open the specified app group" details:nil]);
63+
return;
64+
}
65+
4966
result(nil);
5067
}
5168

5269
- (void)setBool:(FlutterMethodCall *)call result:(FlutterResult)result {
53-
[self checkAppGroup:result];
70+
if (![self checkAppGroup:result]) {
71+
return;
72+
}
5473

5574
NSString *key = call.arguments[@"key"];
5675
NSNumber *value = call.arguments[@"value"];
@@ -59,7 +78,9 @@ - (void)setBool:(FlutterMethodCall *)call result:(FlutterResult)result {
5978
}
6079

6180
- (void)setInt:(FlutterMethodCall *)call result:(FlutterResult)result {
62-
[self checkAppGroup:result];
81+
if (![self checkAppGroup:result]) {
82+
return;
83+
}
6384

6485
NSString *key = call.arguments[@"key"];
6586
NSNumber *value = call.arguments[@"value"];
@@ -71,7 +92,9 @@ - (void)setInt:(FlutterMethodCall *)call result:(FlutterResult)result {
7192
}
7293

7394
- (void)setDouble:(FlutterMethodCall *)call result:(FlutterResult)result {
74-
[self checkAppGroup:result];
95+
if (![self checkAppGroup:result]) {
96+
return;
97+
}
7598

7699
NSString *key = call.arguments[@"key"];
77100
NSNumber *value = call.arguments[@"value"];
@@ -80,7 +103,9 @@ - (void)setDouble:(FlutterMethodCall *)call result:(FlutterResult)result {
80103
}
81104

82105
- (void)setString:(FlutterMethodCall *)call result:(FlutterResult)result {
83-
[self checkAppGroup:result];
106+
if (![self checkAppGroup:result]) {
107+
return;
108+
}
84109

85110
NSString *key = call.arguments[@"key"];
86111
NSString *value = call.arguments[@"value"];
@@ -89,7 +114,9 @@ - (void)setString:(FlutterMethodCall *)call result:(FlutterResult)result {
89114
}
90115

91116
- (void)setStringArray:(FlutterMethodCall *)call result:(FlutterResult)result {
92-
[self checkAppGroup:result];
117+
if (![self checkAppGroup:result]) {
118+
return;
119+
}
93120

94121
NSString *key = call.arguments[@"key"];
95122
NSArray *value = call.arguments[@"value"];
@@ -98,55 +125,69 @@ - (void)setStringArray:(FlutterMethodCall *)call result:(FlutterResult)result {
98125
}
99126

100127
- (void)get:(FlutterMethodCall *)call result:(FlutterResult)result {
101-
[self checkAppGroup:result];
128+
if (![self checkAppGroup:result]) {
129+
return;
130+
}
102131

103132
NSString *key = call.arguments[@"key"];
104133
id value = [self.userDefaults valueForKey:key];
105134
result(value);
106135
}
107136

108137
- (void)getBool:(FlutterMethodCall *)call result:(FlutterResult)result {
109-
[self checkAppGroup:result];
138+
if (![self checkAppGroup:result]) {
139+
return;
140+
}
110141

111142
NSString *key = call.arguments[@"key"];
112143
NSNumber *value = [NSNumber numberWithBool:[self.userDefaults boolForKey:key]];
113144
result(value);
114145
}
115146

116147
- (void)getInt:(FlutterMethodCall *)call result:(FlutterResult)result {
117-
[self checkAppGroup:result];
148+
if (![self checkAppGroup:result]) {
149+
return;
150+
}
118151

119152
NSString *key = call.arguments[@"key"];
120153
NSNumber *value = [NSNumber numberWithLong:[self.userDefaults integerForKey:key]];
121154
result(value);
122155
}
123156

124157
- (void)getDouble:(FlutterMethodCall *)call result:(FlutterResult)result {
125-
[self checkAppGroup:result];
158+
if (![self checkAppGroup:result]) {
159+
return;
160+
}
126161

127162
NSString *key = call.arguments[@"key"];
128163
NSNumber *value = [NSNumber numberWithDouble:[self.userDefaults doubleForKey:key]];
129164
result(value);
130165
}
131166

132167
- (void)getString:(FlutterMethodCall *)call result:(FlutterResult)result {
133-
[self checkAppGroup:result];
168+
if (![self checkAppGroup:result]) {
169+
return;
170+
}
134171

135172
NSString *key = call.arguments[@"key"];
136173
NSString *value = [self.userDefaults stringForKey:key];
137174
result(value);
138175
}
139176

140177
- (void)getStringArray:(FlutterMethodCall *)call result:(FlutterResult)result {
141-
[self checkAppGroup:result];
178+
if (![self checkAppGroup:result]) {
179+
return;
180+
}
142181

143182
NSString *key = call.arguments[@"key"];
144183
NSArray<NSString *> *value = [self.userDefaults stringArrayForKey:key];
145184
result(value);
146185
}
147186

148187
- (void)getAll:(FlutterMethodCall *)call result:(FlutterResult)result {
149-
[self checkAppGroup:result];
188+
if (![self checkAppGroup:result]) {
189+
return;
190+
}
150191

151192
NSDictionary *allPreferences = [self.userDefaults persistentDomainForName:self.appGroup];
152193
if (allPreferences && allPreferences.count > 0) {
@@ -157,15 +198,19 @@ - (void)getAll:(FlutterMethodCall *)call result:(FlutterResult)result {
157198
}
158199

159200
- (void)remove:(FlutterMethodCall *)call result:(FlutterResult)result {
160-
[self checkAppGroup:result];
201+
if (![self checkAppGroup:result]) {
202+
return;
203+
}
161204

162205
NSString *key = call.arguments[@"key"];
163206
[self.userDefaults removeObjectForKey:key];
164207
result(nil);
165208
}
166209

167210
- (void)removeAll:(FlutterMethodCall *)call result:(FlutterResult)result {
168-
[self checkAppGroup:result];
211+
if (![self checkAppGroup:result]) {
212+
return;
213+
}
169214

170215
NSDictionary *allPreferences = [self.userDefaults persistentDomainForName:self.appGroup];
171216
for (NSString *key in allPreferences) {
@@ -176,10 +221,13 @@ - (void)removeAll:(FlutterMethodCall *)call result:(FlutterResult)result {
176221

177222
#pragma mark - Private
178223

179-
- (void)checkAppGroup:(FlutterResult)result {
224+
- (BOOL)checkAppGroup:(FlutterResult)result {
180225
if (!self.appGroup || !self.userDefaults) {
181226
result([FlutterError errorWithCode:@"APP_GROUP_HAS_NOT_BEEN_SET" message:@"You need to call `setAppGroup` before using" details:nil]);
227+
return NO;
182228
}
229+
230+
return YES;
183231
}
184232

185233

example/ios/Podfile.lock

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
PODS:
22
- Flutter (1.0.0)
3-
- shared_preference_app_group (2.0.0):
3+
- shared_preference_app_group (2.1.0):
44
- Flutter
5+
- FlutterMacOS
56

67
DEPENDENCIES:
78
- Flutter (from `Flutter`)
8-
- shared_preference_app_group (from `.symlinks/plugins/shared_preference_app_group/ios`)
9+
- shared_preference_app_group (from `.symlinks/plugins/shared_preference_app_group/darwin`)
910

1011
EXTERNAL SOURCES:
1112
Flutter:
1213
:path: Flutter
1314
shared_preference_app_group:
14-
:path: ".symlinks/plugins/shared_preference_app_group/ios"
15+
:path: ".symlinks/plugins/shared_preference_app_group/darwin"
1516

1617
SPEC CHECKSUMS:
1718
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
18-
shared_preference_app_group: c3dd00bde749c019e2f3dcae8edbe5fd6d5cc998
19+
shared_preference_app_group: 761ef961f5757280c4287c94483dc740235137cd
1920

2021
PODFILE CHECKSUM: 3ce3a3b82c5cf6a622cb22850b0afa4ee279bea6
2122

0 commit comments

Comments
 (0)