Skip to content

Commit d52dbe4

Browse files
committed
Support dynamic values/titles in radio groups
1 parent 454a1a6 commit d52dbe4

File tree

11 files changed

+113
-58
lines changed

11 files changed

+113
-58
lines changed

InAppSettingsKit.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = 'InAppSettingsKit'
3-
s.version = '3.6.2'
3+
s.version = '3.7'
44
s.summary = 'This iPhone framework allows settings to be in-app in addition to being in the Settings app.'
55

66
s.description = <<-DESC

InAppSettingsKitSampleApp/Classes/MainViewController.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,14 +193,14 @@ extension MainViewController: IASKSettingsDelegate {
193193
}
194194

195195
func settingsViewController(_ settingsViewController: IASKAppSettingsViewController, valuesFor specifier: IASKSpecifier) -> [Any] {
196-
return specifier.key == "countryCode" ? Locale.isoRegionCodes : []
196+
return specifier.key == "countryCode" ? Locale.isoRegionCodes : ["Chicago", "Seattle", "Miami"]
197197
}
198198

199-
func settingsViewController(_ settingsViewController: IASKAppSettingsViewController, titlesFor specifier: IASKSpecifier) -> [Any] {
199+
func settingsViewController(_ settingsViewController: IASKAppSettingsViewController, titlesFor specifier: IASKSpecifier) -> [String] {
200200
if specifier.key == "countryCode" {
201201
return Locale.isoRegionCodes.map{Locale.current.localizedString(forRegionCode: $0) ?? ""}
202202
}
203-
return []
203+
return ["Chicago", "Seattle", "Miami"]
204204
}
205205

206206
func settingsViewController(_ settingsViewController: IASKAppSettingsViewController, childPaneIsValidFor specifier: IASKSpecifier, contentDictionary: NSMutableDictionary) -> Bool {

InAppSettingsKitSampleApp/Settings.bundle/Complete.plist

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,16 @@
794794
<string>Three</string>
795795
</array>
796796
</dict>
797+
<dict>
798+
<key>Type</key>
799+
<string>PSRadioGroupSpecifier</string>
800+
<key>Title</key>
801+
<string>Radio Group</string>
802+
<key>Key</key>
803+
<string>radiogroup2</string>
804+
<key>DefaultValue</key>
805+
<string>Seattle</string>
806+
</dict>
797807
<dict>
798808
<key>Type</key>
799809
<string>PSGroupSpecifier</string>

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -353,10 +353,10 @@ The callback receives the `IASKTextField` which is a `UITextField` subclass to a
353353
354354
355355
## Dynamic MultiValue Lists
356-
MultiValue lists (`PSMultiValueSpecifier`) can fetch their values and titles dynamically from the delegate instead of the static Plist. Implement these two methods in your `IASKSettingsDelegate`:
356+
MultiValue lists (`PSMultiValueSpecifier`) and radio groups (`PSRadioGroupSpecifier`) can fetch their values and titles dynamically from the delegate instead of the static Plist. Implement these two methods in your `IASKSettingsDelegate`:
357357
358358
- (NSArray*)settingsViewController:(IASKAppSettingsViewController*)sender valuesForSpecifier:(IASKSpecifier*)specifier;
359-
- (NSArray*)settingsViewController:(IASKAppSettingsViewController*)sender titlesForSpecifier:(IASKSpecifier*)specifier;
359+
- (NSArray<NSString*>*)settingsViewController:(IASKAppSettingsViewController*)sender titlesForSpecifier:(IASKSpecifier*)specifier;
360360
361361
The sample app returns a list of all country codes as values and the localized country names as titles.
362362

Sources/InAppSettingsKit/Controllers/IASKAppSettingsViewController.m

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545

4646
CGRect IASKCGRectSwap(CGRect rect);
4747

48-
@interface IASKAppSettingsViewController () <UITextViewDelegate>
48+
@interface IASKAppSettingsViewController () <IASKSettingsReaderDelegate, UITextViewDelegate>
4949

5050
@property (nonatomic, weak) UIViewController *currentChildViewController;
5151
@property (nonatomic, strong) NSMutableDictionary *rowHeights;
@@ -71,7 +71,7 @@ @implementation IASKAppSettingsViewController
7171
- (IASKSettingsReader*)settingsReader {
7272
if (!_settingsReader) {
7373
NSBundle* bundle = _bundle == nil ? NSBundle.mainBundle : _bundle;
74-
_settingsReader = [[IASKSettingsReader alloc] initWithFile:self.file bundle:bundle];
74+
_settingsReader = [[IASKSettingsReader alloc] initWithFile:self.file bundle:bundle delegate:self];
7575
if (self.neverShowPrivacySettings) {
7676
_settingsReader.showPrivacySettings = NO;
7777
}
@@ -111,14 +111,14 @@ - (void)setFile:(NSString *)file {
111111
self.tableView.contentOffset = CGPointMake(0, -self.tableView.contentInset.top);
112112
self.settingsReader = nil; // automatically initializes itself
113113
if (!_reloadDisabled) {
114-
[self.tableView reloadData];
115114
[self createSelections];
115+
[self.tableView reloadData];
116116
}
117117
}
118118

119119
- (void)createSelections {
120120
NSMutableArray *sectionSelection = [NSMutableArray new];
121-
for (int section = 0; section < _settingsReader.numberOfSections; section++) {
121+
for (int section = 0; section < self.settingsReader.numberOfSections; section++) {
122122
IASKSpecifier *specifier = [self.settingsReader headerSpecifierForSection:section];
123123
if ([specifier.type isEqualToString:kIASKPSRadioGroupSpecifier]) {
124124
IASKMultipleValueSelection *selection = [[IASKMultipleValueSelection alloc] initWithSettingsStore:self.settingsStore tableView:self.tableView specifier:specifier section:section];
@@ -368,6 +368,7 @@ - (void)setHiddenKeys:(NSSet*)theHiddenKeys animated:(BOOL)animated {
368368
}
369369
} else {
370370
self.settingsReader.hiddenKeys = theHiddenKeys;
371+
[self createSelections];
371372
if (!_reloadDisabled) [self.tableView reloadData];
372373
}
373374
}
@@ -600,7 +601,7 @@ - (UITableViewCell*)tableView:(UITableView *)tableView newCellForSpecifier:(IASK
600601
}
601602

602603
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
603-
IASKSpecifier *specifier = [self.settingsReader specifierForIndexPath:indexPath];
604+
IASKSpecifier *specifier = [self.settingsReader specifierForIndexPath:indexPath];
604605
if ([specifier.type isEqualToString:kIASKCustomViewSpecifier] && [self.delegate respondsToSelector:@selector(settingsViewController:cellForSpecifier:)]) {
605606
UITableViewCell* cell = [self.delegate settingsViewController:self cellForSpecifier:specifier];
606607
assert(nil != cell && "delegate must return a UITableViewCell for custom cell types");
@@ -1090,6 +1091,31 @@ - (void)presentChildViewController:(UITableViewController<IASKViewController> *)
10901091
}
10911092
}
10921093

1094+
#pragma mark -
1095+
#pragma mark IASKSettingsReaderDelegate
1096+
- (nullable NSArray<NSString*>*)titlesForSpecifier:(IASKSpecifier*)specifier {
1097+
if ([self.delegate respondsToSelector:@selector(settingsViewController:titlesForSpecifier:)]) {
1098+
return [self.delegate settingsViewController:self titlesForSpecifier:specifier];
1099+
}
1100+
return nil;
1101+
}
1102+
1103+
- (NSArray*)valuesForSpecifier:(IASKSpecifier*)specifier {
1104+
if ([self.delegate respondsToSelector:@selector(settingsViewController:valuesForSpecifier:)]) {
1105+
return [self.delegate settingsViewController:self valuesForSpecifier:specifier];
1106+
}
1107+
return nil;
1108+
}
1109+
1110+
- (void)setMultiValuesFromDelegateIfNeeded:(IASKSpecifier *)specifier {
1111+
if (specifier.multipleValues.count == 0) {
1112+
NSArray *titles = [self titlesForSpecifier:specifier];
1113+
NSArray *values = [self valuesForSpecifier:specifier];
1114+
[specifier setMultipleValuesDictValues:values titles:titles];
1115+
[specifier sortIfNeeded];
1116+
}
1117+
}
1118+
10931119
#pragma mark -
10941120
#pragma mark MFMailComposeViewControllerDelegate Function
10951121

@@ -1294,18 +1320,6 @@ - (void)reload {
12941320
[self.tableView performSelector:@selector(reloadData) withObject:nil afterDelay:0.5];
12951321
}
12961322

1297-
- (void)setMultiValuesFromDelegateIfNeeded:(IASKSpecifier *)specifier {
1298-
if (specifier.multipleValues.count == 0) {
1299-
if ([self.delegate respondsToSelector:@selector(settingsViewController:valuesForSpecifier:)] &&
1300-
[self.delegate respondsToSelector:@selector(settingsViewController:titlesForSpecifier:)])
1301-
{
1302-
[specifier setMultipleValuesDictValues:[self.delegate settingsViewController:self valuesForSpecifier:specifier]
1303-
titles:[self.delegate settingsViewController:self titlesForSpecifier:specifier]];
1304-
}
1305-
[specifier sortIfNeeded];
1306-
}
1307-
}
1308-
13091323

13101324
#pragma mark CGRect Utility function
13111325
CGRect IASKCGRectSwap(CGRect rect) {

Sources/InAppSettingsKit/Models/IASKSettingsReader.m

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
//
1616

1717
#import "IASKSettingsReader.h"
18+
#import "IASKAppSettingsViewController.h"
1819
#import "IASKSpecifier.h"
1920
#import "IASKSettingsStore.h"
2021

@@ -27,9 +28,10 @@ - (id)iaskObjectAtIndex:(NSUInteger)index;
2728

2829
@implementation IASKSettingsReader
2930

30-
- (nonnull id)initWithFile:(nonnull NSString*)file bundle:(nonnull NSBundle*)bundle {
31+
- (nonnull id)initWithFile:(nonnull NSString*)file bundle:(nonnull NSBundle*)bundle delegate:(nullable id<IASKSettingsReaderDelegate>)delegate {
3132
if ((self = [super init])) {
3233
_applicationBundle = bundle;
34+
_delegate = delegate;
3335

3436
NSString* plistFilePath = [self locateSettingsFile:file];
3537
NSDictionary *settingsDictionary = [NSDictionary dictionaryWithContentsOfFile:plistFilePath];
@@ -76,7 +78,7 @@ - (nonnull id)initWithFile:(nonnull NSString*)file bundle:(nonnull NSBundle*)bun
7678
}
7779

7880
- (nonnull id)initWithFile:(nonnull NSString*)file {
79-
return [self initWithFile:file bundle:[NSBundle mainBundle]];
81+
return [self initWithFile:file bundle:NSBundle.mainBundle delegate:nil];
8082
}
8183

8284
- (id)init {
@@ -169,19 +171,13 @@ - (void)_reinterpretBundle:(NSDictionary*)settingsBundle {
169171
ignoreItemsInThisSection = NO;
170172

171173
///create a brand new array with the specifier above and an empty array
172-
NSMutableArray *newArray = [NSMutableArray array];
173-
[newArray addObject:newSpecifier];
174-
[dataSource addObject:newArray];
175174

176-
if ([newSpecifier.type isEqualToString:kIASKPSRadioGroupSpecifier]) {
177-
for (NSString *value in newSpecifier.multipleValues) {
178-
IASKSpecifier *valueSpecifier =
179-
[[IASKSpecifier alloc] initWithSpecifier:specifierDictionary radioGroupValue:value];
180-
valueSpecifier.settingsReader = self;
181-
[valueSpecifier sortIfNeeded];
182-
[newArray addObject:valueSpecifier];
183-
}
184-
}
175+
if ([newSpecifier.type isEqualToString:kIASKPSRadioGroupSpecifier] && newSpecifier.multipleValues.count == 0) {
176+
[newSpecifier setMultipleValuesDictValues:[self.delegate valuesForSpecifier:newSpecifier]
177+
titles:[self.delegate titlesForSpecifier:newSpecifier]];
178+
}
179+
[dataSource addObject:newSpecifier.multiValueChildSpecifiers];
180+
185181
} else {
186182
if (ignoreItemsInThisSection || (newSpecifier.key && [self.hiddenKeys containsObject:(id)newSpecifier.key])) {
187183
continue;
@@ -231,6 +227,8 @@ - (NSInteger)numberOfRowsInSection:(NSInteger)section {
231227
numberOfRows++;
232228
}
233229
return numberOfRows;
230+
} else if ([headerSpecifier.type isEqualToString:kIASKPSRadioGroupSpecifier]) {
231+
return headerSpecifier.multipleValuesCount;
234232
}
235233

236234
return ((NSArray*)[self.dataSource iaskObjectAtIndex:section]).count - headingCorrection;
@@ -333,7 +331,7 @@ - (void)gatherDefaultsInDictionary:(NSMutableDictionary*)dictionary limitedToEdi
333331
[dictionary setObject:(id)specifier.defaultValue forKey:(id)specifier.key];
334332
}
335333
if ([specifier.type isEqualToString:kIASKPSChildPaneSpecifier] && specifier.file) {
336-
IASKSettingsReader *childReader = [[IASKSettingsReader alloc] initWithFile:(id)specifier.file bundle:_applicationBundle];
334+
IASKSettingsReader *childReader = [[IASKSettingsReader alloc] initWithFile:(id)specifier.file bundle:_applicationBundle delegate:self.delegate];
337335
childReader.settingsStore = self.settingsStore;
338336
[childReader gatherDefaultsInDictionary:dictionary limitedToEditableFields:limitedToEditableFields apply:apply];
339337
}

Sources/InAppSettingsKit/Models/IASKSpecifier.m

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,8 @@ - (void)setMultipleValuesDictValues:(NSArray*)values titles:(NSArray*)titles {
6767
NSArray *iconNames = [_specifierDict objectForKey:kIASKIconNames];
6868
NSMutableDictionary *multipleValuesDict = [NSMutableDictionary new];
6969

70-
if (values) {
70+
if (values && titles) {
7171
[multipleValuesDict setObject:values forKey:kIASKValues];
72-
}
73-
74-
if (titles) {
7572
[multipleValuesDict setObject:titles forKey:kIASKTitles];
7673
}
7774

@@ -497,6 +494,23 @@ - (NSTextAlignment)textAlignment {
497494
return NSTextAlignmentNatural;
498495
}
499496

497+
- (NSArray<IASKSpecifier*>*)multiValueChildSpecifiers {
498+
NSMutableArray *result = @[self].mutableCopy;
499+
if (!self.multipleValues) return result;
500+
501+
if ([self.type isEqualToString:kIASKPSRadioGroupSpecifier]) {
502+
for (NSString *value in self.multipleValues) {
503+
IASKSpecifier *specifier =
504+
[[IASKSpecifier alloc] initWithSpecifier:self.specifierDict radioGroupValue:value];
505+
specifier.settingsReader = self.settingsReader;
506+
specifier.multipleValuesDict = self.multipleValuesDict;
507+
[specifier sortIfNeeded];
508+
[result addObject:specifier];
509+
}
510+
}
511+
return result;
512+
}
513+
500514
- (NSArray *)userInterfaceIdioms {
501515
NSMutableDictionary *idiomMap = [NSMutableDictionary dictionaryWithDictionary:
502516
@{

Sources/InAppSettingsKit/include/IASKAppSettingsViewController.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,9 @@ shouldPresentMailComposeViewController:(MFMailComposeViewController*)mailCompose
162162
@param specifier the specifier containing the key of the selected element
163163
@return an array of titles
164164
@discussion the returned array overrides any titles specified in the static schema plist
165-
*/
166-
- (NSArray*)settingsViewController:(IASKAppSettingsViewController*)settingsViewController
167-
titlesForSpecifier:(IASKSpecifier*)specifier;
165+
*/
166+
- (NSArray<NSString*>*)settingsViewController:(IASKAppSettingsViewController*)settingsViewController
167+
titlesForSpecifier:(IASKSpecifier*)specifier;
168168

169169
#pragma mark - Button
170170
/** Tells the delegate that the specified button (`IASKButton`) element is now selected.

Sources/InAppSettingsKit/include/IASKSettingsReader.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,11 @@ extern NSString * const IASKSettingChangedNotification;
175175
@class IASKSpecifier;
176176
@protocol IASKSettingsStore;
177177

178+
@protocol IASKSettingsReaderDelegate <NSObject>
179+
- (nullable NSArray<NSString*>*)titlesForSpecifier:(IASKSpecifier*)specifier;
180+
- (nullable NSArray*)valuesForSpecifier:(IASKSpecifier*)specifier;
181+
@end
182+
178183
/** settings reader transform iOS's settings plist files
179184
to the IASKSpecifier model objects.
180185
Besides that, it also hides the complexity of finding
@@ -188,7 +193,7 @@ extern NSString * const IASKSettingChangedNotification;
188193
@param file settings file name without the ".plist" suffix
189194
@param bundle bundle that contains a plist with the specified file
190195
*/
191-
- (id)initWithFile:(NSString*)file bundle:(NSBundle*)bundle;
196+
- (id)initWithFile:(NSString*)file bundle:(NSBundle*)bundle delegate:(nullable id<IASKSettingsReaderDelegate>)delegate;
192197

193198
/** convenience initializer
194199
calls initWithFile where applicationBundle is set to NSBundle.mainBundle
@@ -197,6 +202,7 @@ extern NSString * const IASKSettingChangedNotification;
197202
- (id)initWithFile:(NSString*)file;
198203

199204
@property (nonatomic, readonly) NSInteger numberOfSections;
205+
@property (nonatomic, nullable, weak) id<IASKSettingsReaderDelegate> delegate;
200206
- (NSInteger)numberOfRowsInSection:(NSInteger)section;
201207
- (nullable IASKSpecifier*)specifierForIndexPath:(NSIndexPath*)indexPath;
202208
- (nullable IASKSpecifier*)headerSpecifierForSection:(NSInteger)section;

Sources/InAppSettingsKit/include/IASKSpecifier.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ NS_ASSUME_NONNULL_BEGIN
6262
@property (nullable, nonatomic, strong, readonly) NSArray *userInterfaceIdioms;
6363
@property (nonatomic, readonly) BOOL adjustsFontSizeToFitWidth;
6464
@property (nonatomic, readonly) NSTextAlignment textAlignment;
65+
@property (nonatomic, readonly) NSArray<IASKSpecifier*>* multiValueChildSpecifiers;
6566

6667
- (nullable NSString*)localizedObjectForKey:(NSString*)key;
6768
- (nullable NSString*)titleForCurrentValue:(nullable id)currentValue;

0 commit comments

Comments
 (0)