Adding new preferences modal.

This commit is contained in:
Samuel Clay 2013-06-21 17:48:06 -07:00
parent 6b249d30ec
commit 361c129fa6
44 changed files with 3428 additions and 18 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -400,7 +400,7 @@
} else {
readFilter = @"";
}
NSString *sql = [NSString stringWithFormat:@"SELECT * FROM stories s %@ WHERE s.story_feed_id IN (%@) ORDER BY s.story_timestamp %@",
NSString *sql = [NSString stringWithFormat:@"SELECT * FROM stories s %@ WHERE s.story_feed_id IN (%@) ORDER BY s.story_timestamp %@ LIMIT 500",
readFilter,
[feedIds componentsJoinedByString:@","],
order];

View file

@ -36,13 +36,15 @@
if ([appDelegate.activeUsername isEqualToString:@"samuel"]) {
self.menuOptions = [[NSArray alloc]
initWithObjects:[@"Find Friends" uppercaseString],
[@"Logout" uppercaseString],
[@"Login as..." uppercaseString],
nil];
initWithObjects:[@"Preferences" uppercaseString],
[@"Find Friends" uppercaseString],
[@"Logout" uppercaseString],
[@"Login as..." uppercaseString],
nil];
} else {
self.menuOptions = [[NSArray alloc]
initWithObjects:[@"Find Friends" uppercaseString],
initWithObjects:[@"Preferences" uppercaseString],
[@"Find Friends" uppercaseString],
[@"Logout" uppercaseString], nil];
}
@ -90,8 +92,10 @@
cell.textLabel.text = [self.menuOptions objectAtIndex:[indexPath row]];
if (indexPath.row == 0) {
cell.imageView.image = [UIImage imageNamed:@"menu_icn_followers.png"];
cell.imageView.image = [UIImage imageNamed:@"menu_icn_preferences.png"];
} else if (indexPath.row == 1) {
cell.imageView.image = [UIImage imageNamed:@"menu_icn_followers.png"];
} else if (indexPath.row == 2) {
cell.imageView.image = [UIImage imageNamed:@"menu_icn_fetch_subscribers.png"];
}
@ -105,10 +109,12 @@
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 0) {
[appDelegate showFindFriends];
[appDelegate showPreferences];
} else if (indexPath.row == 1) {
[appDelegate confirmLogout];
[appDelegate showFindFriends];
} else if (indexPath.row == 2) {
[appDelegate confirmLogout];
} else if (indexPath.row == 3) {
[self showLoginAsDialog];
}

View file

@ -40,6 +40,7 @@
@class OriginalStoryViewController;
@class UserProfileViewController;
@class NBContainerViewController;
@class IASKAppSettingsViewController;
@class UnreadCounts;
@interface NewsBlurAppDelegate : BaseViewController <UIApplicationDelegate, UIAlertViewDelegate, UINavigationControllerDelegate> {
@ -75,7 +76,8 @@
TrainerViewController *trainerViewController;
OriginalStoryViewController *originalStoryViewController;
UserProfileViewController *userProfileViewController;
IASKAppSettingsViewController *preferencesViewController;
NSString * activeUsername;
NSString * activeUserProfileId;
NSString * activeUserProfileName;
@ -162,6 +164,7 @@
@property (nonatomic) IBOutlet ShareViewController *shareViewController;
@property (nonatomic) IBOutlet FontSettingsViewController *fontSettingsViewController;
@property (nonatomic) IBOutlet UserProfileViewController *userProfileViewController;
@property (nonatomic) IBOutlet IASKAppSettingsViewController *preferencesViewController;
@property (nonatomic) IBOutlet FirstTimeUserViewController *firstTimeUserViewController;
@property (nonatomic) IBOutlet FirstTimeUserAddSitesViewController *firstTimeUserAddSitesViewController;
@ -239,6 +242,7 @@
- (void)pushUserProfile;
- (void)hideUserProfileModal;
- (void)showFindFriends;
- (void)showPreferences;
- (void)showMoveSite;
- (void)openTrainSite;

View file

@ -42,6 +42,7 @@
#import "FMDatabaseQueue.h"
#import "FMDatabaseAdditions.h"
#import "JSON.h"
#import "IASKAppSettingsViewController.h"
@implementation NewsBlurAppDelegate
@ -74,6 +75,7 @@
@synthesize trainerViewController;
@synthesize originalStoryViewController;
@synthesize userProfileViewController;
@synthesize preferencesViewController;
@synthesize firstTimeUserViewController;
@synthesize firstTimeUserAddSitesViewController;
@ -348,11 +350,34 @@
}
}
- (void)showPreferences {
if (!preferencesViewController) {
preferencesViewController = [[IASKAppSettingsViewController alloc] init];
}
preferencesViewController.delegate = self.feedsViewController;
preferencesViewController.showDoneButton = YES;
preferencesViewController.showCreditsFooter = NO;
preferencesViewController.title = @"Preferences";
BOOL enabled = [[NSUserDefaults standardUserDefaults] boolForKey:@"offline_allowed"];
preferencesViewController.hiddenKeys = enabled ? nil : [NSSet setWithObjects:@"offline_image_download", @"offline_download_connection", nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:preferencesViewController];
self.modalNavigationController = navController;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
self.modalNavigationController.modalPresentationStyle = UIModalPresentationFormSheet;
[masterContainerViewController presentViewController:modalNavigationController animated:YES completion:nil];
} else {
[navigationController presentViewController:modalNavigationController animated:YES completion:nil];
}
}
- (void)showFindFriends {
FriendsListViewController *friendsBVC = [[FriendsListViewController alloc] init];
UINavigationController *friendsNav = [[UINavigationController alloc] initWithRootViewController:friendsListViewController];
self.friendsListViewController = friendsBVC;
self.friendsListViewController = friendsBVC;
self.modalNavigationController = friendsNav;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {

View file

@ -14,6 +14,7 @@
#import "BaseViewController.h"
#import "WEPopoverController.h"
#import "NBNotifier.h"
#import "IASKAppSettingsViewController.h"
@class NewsBlurAppDelegate;
@ -22,7 +23,8 @@
UIAlertViewDelegate, PullToRefreshViewDelegate,
ASIHTTPRequestDelegate, NSCacheDelegate,
WEPopoverControllerDelegate,
UIPopoverControllerDelegate> {
UIPopoverControllerDelegate,
IASKSettingsDelegate> {
NewsBlurAppDelegate *appDelegate;
NSMutableDictionary * activeFeedLocations;
@ -112,6 +114,9 @@ UIPopoverControllerDelegate> {
- (void)refreshHeaderCounts;
- (void)refreshHeaderCounts:(UIInterfaceOrientation)orientation;
- (void)settingsViewControllerDidEnd:(IASKAppSettingsViewController*)sender;
- (void)settingDidChange:(NSNotification*)notification;
- (void)showSyncingNotifier;
- (void)showSyncingNotifier:(float)progress hoursBack:(int)days;
- (void)showOfflineNotifier;

View file

@ -29,6 +29,8 @@
#import "AddSiteViewController.h"
#import "FMDatabase.h"
#import "FMDatabaseAdditions.h"
#import "IASKAppSettingsViewController.h"
#import "IASKSettingsReader.h"
#define kPhoneTableViewRowHeight 31;
#define kTableViewRowHeight 31;
@ -95,10 +97,12 @@ static const CGFloat kFolderTitleHeight = 28;
selector:@selector(returnToApp)
name:UIApplicationWillEnterForegroundNotification
object:nil];
imageCache = [[NSCache alloc] init];
[imageCache setDelegate:self];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(settingDidChange:) name:kIASKAppSettingChanged object:nil];
[self.intelligenceControl setWidth:36 forSegmentAtIndex:0];
[self.intelligenceControl setWidth:64 forSegmentAtIndex:1];
[self.intelligenceControl setWidth:62 forSegmentAtIndex:2];
@ -829,7 +833,7 @@ static const CGFloat kFolderTitleHeight = 28;
if ([self.popoverController respondsToSelector:@selector(setContainerViewProperties:)]) {
[self.popoverController setContainerViewProperties:[self improvedContainerViewProperties]];
}
[self.popoverController setPopoverContentSize:CGSizeMake(200, 76)];
[self.popoverController setPopoverContentSize:CGSizeMake(200, 114)];
[self.popoverController presentPopoverFromBarButtonItem:self.settingsBarButton
permittedArrowDirections:UIPopoverArrowDirectionDown
animated:YES];
@ -873,6 +877,23 @@ static const CGFloat kFolderTitleHeight = 28;
}
}
- (void)settingsViewControllerDidEnd:(IASKAppSettingsViewController*)sender {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[appDelegate.masterContainerViewController dismissViewControllerAnimated:YES completion:nil];
} else {
[appDelegate.navigationController dismissViewControllerAnimated:YES completion:nil];
}
// your code here to reconfigure the app for changed settings
}
- (void)settingDidChange:(NSNotification*)notification {
if ([notification.object isEqual:@"offline_allowed"]) {
BOOL enabled = (BOOL)[[notification.userInfo objectForKey:@"offline_allowed"] intValue];
[appDelegate.preferencesViewController setHiddenKeys:enabled ? nil : [NSSet setWithObjects:@"offline_image_download", @"offline_download_connection", nil] animated:YES];
}
}
#pragma mark -
#pragma mark Table View - Feed List

View file

@ -451,6 +451,23 @@
FFECD019172B105800D45A62 /* UIActivitySafari.png in Resources */ = {isa = PBXBuildFile; fileRef = FFECD017172B105800D45A62 /* UIActivitySafari.png */; };
FFECD01A172B105800D45A62 /* UIActivitySafari@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FFECD018172B105800D45A62 /* UIActivitySafari@2x.png */; };
FFECD01D172B10BD00D45A62 /* SafariActivityItem.m in Sources */ = {isa = PBXBuildFile; fileRef = FFECD01C172B10BD00D45A62 /* SafariActivityItem.m */; };
FFF1E4B9177504CA00BF59D3 /* IASKAppSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FFF1E49B177504CA00BF59D3 /* IASKAppSettingsViewController.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
FFF1E4BA177504CA00BF59D3 /* IASKAppSettingsWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FFF1E49D177504CA00BF59D3 /* IASKAppSettingsWebViewController.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
FFF1E4BB177504CA00BF59D3 /* IASKSpecifierValuesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FFF1E49F177504CA00BF59D3 /* IASKSpecifierValuesViewController.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
FFF1E4BC177504CA00BF59D3 /* IASKSettingsReader.m in Sources */ = {isa = PBXBuildFile; fileRef = FFF1E4A3177504CA00BF59D3 /* IASKSettingsReader.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
FFF1E4BD177504CA00BF59D3 /* IASKSettingsStore.m in Sources */ = {isa = PBXBuildFile; fileRef = FFF1E4A5177504CA00BF59D3 /* IASKSettingsStore.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
FFF1E4BE177504CA00BF59D3 /* IASKSettingsStoreFile.m in Sources */ = {isa = PBXBuildFile; fileRef = FFF1E4A7177504CA00BF59D3 /* IASKSettingsStoreFile.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
FFF1E4BF177504CA00BF59D3 /* IASKSettingsStoreUserDefaults.m in Sources */ = {isa = PBXBuildFile; fileRef = FFF1E4A9177504CA00BF59D3 /* IASKSettingsStoreUserDefaults.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
FFF1E4C0177504CA00BF59D3 /* IASKSpecifier.m in Sources */ = {isa = PBXBuildFile; fileRef = FFF1E4AB177504CA00BF59D3 /* IASKSpecifier.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
FFF1E4C1177504CA00BF59D3 /* IASKPSSliderSpecifierViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = FFF1E4AE177504CA00BF59D3 /* IASKPSSliderSpecifierViewCell.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
FFF1E4C2177504CA00BF59D3 /* IASKPSTextFieldSpecifierViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = FFF1E4B0177504CA00BF59D3 /* IASKPSTextFieldSpecifierViewCell.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
FFF1E4C3177504CA00BF59D3 /* IASKPSTitleValueSpecifierViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = FFF1E4B2177504CA00BF59D3 /* IASKPSTitleValueSpecifierViewCell.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
FFF1E4C4177504CA00BF59D3 /* IASKSlider.m in Sources */ = {isa = PBXBuildFile; fileRef = FFF1E4B4177504CA00BF59D3 /* IASKSlider.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
FFF1E4C5177504CA00BF59D3 /* IASKSwitch.m in Sources */ = {isa = PBXBuildFile; fileRef = FFF1E4B6177504CA00BF59D3 /* IASKSwitch.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
FFF1E4C6177504CA00BF59D3 /* IASKTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = FFF1E4B8177504CA00BF59D3 /* IASKTextField.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
FFF1E4C817750BDD00BF59D3 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = FFF1E4C717750BDD00BF59D3 /* Settings.bundle */; };
FFF1E4CB17750D2C00BF59D3 /* menu_icn_preferences.png in Resources */ = {isa = PBXBuildFile; fileRef = FFF1E4C917750D2C00BF59D3 /* menu_icn_preferences.png */; };
FFF1E4CC17750D2C00BF59D3 /* menu_icn_preferences@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FFF1E4CA17750D2C00BF59D3 /* menu_icn_preferences@2x.png */; };
FFFC608517165A1D00DC22E2 /* THCircularProgressView.m in Sources */ = {isa = PBXBuildFile; fileRef = FFFC60831716578E00DC22E2 /* THCircularProgressView.m */; };
/* End PBXBuildFile section */
@ -1093,6 +1110,38 @@
FFECD018172B105800D45A62 /* UIActivitySafari@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "UIActivitySafari@2x.png"; sourceTree = "<group>"; };
FFECD01B172B10BD00D45A62 /* SafariActivityItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SafariActivityItem.h; sourceTree = "<group>"; };
FFECD01C172B10BD00D45A62 /* SafariActivityItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SafariActivityItem.m; sourceTree = "<group>"; };
FFF1E49A177504CA00BF59D3 /* IASKAppSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKAppSettingsViewController.h; sourceTree = "<group>"; };
FFF1E49B177504CA00BF59D3 /* IASKAppSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKAppSettingsViewController.m; sourceTree = "<group>"; };
FFF1E49C177504CA00BF59D3 /* IASKAppSettingsWebViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKAppSettingsWebViewController.h; sourceTree = "<group>"; };
FFF1E49D177504CA00BF59D3 /* IASKAppSettingsWebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKAppSettingsWebViewController.m; sourceTree = "<group>"; };
FFF1E49E177504CA00BF59D3 /* IASKSpecifierValuesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSpecifierValuesViewController.h; sourceTree = "<group>"; };
FFF1E49F177504CA00BF59D3 /* IASKSpecifierValuesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSpecifierValuesViewController.m; sourceTree = "<group>"; };
FFF1E4A0177504CA00BF59D3 /* IASKViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKViewController.h; sourceTree = "<group>"; };
FFF1E4A2177504CA00BF59D3 /* IASKSettingsReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSettingsReader.h; sourceTree = "<group>"; };
FFF1E4A3177504CA00BF59D3 /* IASKSettingsReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSettingsReader.m; sourceTree = "<group>"; };
FFF1E4A4177504CA00BF59D3 /* IASKSettingsStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSettingsStore.h; sourceTree = "<group>"; };
FFF1E4A5177504CA00BF59D3 /* IASKSettingsStore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSettingsStore.m; sourceTree = "<group>"; };
FFF1E4A6177504CA00BF59D3 /* IASKSettingsStoreFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSettingsStoreFile.h; sourceTree = "<group>"; };
FFF1E4A7177504CA00BF59D3 /* IASKSettingsStoreFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSettingsStoreFile.m; sourceTree = "<group>"; };
FFF1E4A8177504CA00BF59D3 /* IASKSettingsStoreUserDefaults.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSettingsStoreUserDefaults.h; sourceTree = "<group>"; };
FFF1E4A9177504CA00BF59D3 /* IASKSettingsStoreUserDefaults.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSettingsStoreUserDefaults.m; sourceTree = "<group>"; };
FFF1E4AA177504CA00BF59D3 /* IASKSpecifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSpecifier.h; sourceTree = "<group>"; };
FFF1E4AB177504CA00BF59D3 /* IASKSpecifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSpecifier.m; sourceTree = "<group>"; };
FFF1E4AD177504CA00BF59D3 /* IASKPSSliderSpecifierViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKPSSliderSpecifierViewCell.h; sourceTree = "<group>"; };
FFF1E4AE177504CA00BF59D3 /* IASKPSSliderSpecifierViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKPSSliderSpecifierViewCell.m; sourceTree = "<group>"; };
FFF1E4AF177504CA00BF59D3 /* IASKPSTextFieldSpecifierViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKPSTextFieldSpecifierViewCell.h; sourceTree = "<group>"; };
FFF1E4B0177504CA00BF59D3 /* IASKPSTextFieldSpecifierViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKPSTextFieldSpecifierViewCell.m; sourceTree = "<group>"; };
FFF1E4B1177504CA00BF59D3 /* IASKPSTitleValueSpecifierViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKPSTitleValueSpecifierViewCell.h; sourceTree = "<group>"; };
FFF1E4B2177504CA00BF59D3 /* IASKPSTitleValueSpecifierViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKPSTitleValueSpecifierViewCell.m; sourceTree = "<group>"; };
FFF1E4B3177504CA00BF59D3 /* IASKSlider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSlider.h; sourceTree = "<group>"; };
FFF1E4B4177504CA00BF59D3 /* IASKSlider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSlider.m; sourceTree = "<group>"; };
FFF1E4B5177504CA00BF59D3 /* IASKSwitch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSwitch.h; sourceTree = "<group>"; };
FFF1E4B6177504CA00BF59D3 /* IASKSwitch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSwitch.m; sourceTree = "<group>"; };
FFF1E4B7177504CA00BF59D3 /* IASKTextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKTextField.h; sourceTree = "<group>"; };
FFF1E4B8177504CA00BF59D3 /* IASKTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKTextField.m; sourceTree = "<group>"; };
FFF1E4C717750BDD00BF59D3 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = "<group>"; };
FFF1E4C917750D2C00BF59D3 /* menu_icn_preferences.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = menu_icn_preferences.png; sourceTree = "<group>"; };
FFF1E4CA17750D2C00BF59D3 /* menu_icn_preferences@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "menu_icn_preferences@2x.png"; sourceTree = "<group>"; };
FFFC60821716578E00DC22E2 /* THCircularProgressView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = THCircularProgressView.h; sourceTree = "<group>"; };
FFFC60831716578E00DC22E2 /* THCircularProgressView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = THCircularProgressView.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
@ -1166,6 +1215,7 @@
29B97315FDCFA39411CA2CEA /* Other Sources */ = {
isa = PBXGroup;
children = (
FFF1E498177504CA00BF59D3 /* InAppSettingsKit */,
FF753CC2175858FC00344EC9 /* fmdb */,
FFDC9F9616E8064C000D8E0C /* ShareThis */,
FF22FE5316E53ADC0046165A /* Underscore */,
@ -1240,6 +1290,7 @@
431B857815A132C500DCE497 /* js */,
431B857715A132BE00DCE497 /* css */,
431B857615A132B600DCE497 /* Images */,
FFF1E4C717750BDD00BF59D3 /* Settings.bundle */,
);
path = Resources;
sourceTree = "<group>";
@ -1355,6 +1406,8 @@
431B857615A132B600DCE497 /* Images */ = {
isa = PBXGroup;
children = (
FFF1E4C917750D2C00BF59D3 /* menu_icn_preferences.png */,
FFF1E4CA17750D2C00BF59D3 /* menu_icn_preferences@2x.png */,
FF1104601769695A00502C29 /* g_icn_offline@2x.png */,
FFC518B81768E59F00542719 /* g_icn_offline.png */,
FF8364C41757EC0B008F5C58 /* traverse_background_left.png */,
@ -2071,6 +2124,67 @@
path = "cocoa-oauth";
sourceTree = "<group>";
};
FFF1E498177504CA00BF59D3 /* InAppSettingsKit */ = {
isa = PBXGroup;
children = (
FFF1E499177504CA00BF59D3 /* Controllers */,
FFF1E4A1177504CA00BF59D3 /* Models */,
FFF1E4AC177504CA00BF59D3 /* Views */,
);
name = InAppSettingsKit;
path = "Other Sources/InAppSettingsKit";
sourceTree = "<group>";
};
FFF1E499177504CA00BF59D3 /* Controllers */ = {
isa = PBXGroup;
children = (
FFF1E49A177504CA00BF59D3 /* IASKAppSettingsViewController.h */,
FFF1E49B177504CA00BF59D3 /* IASKAppSettingsViewController.m */,
FFF1E49C177504CA00BF59D3 /* IASKAppSettingsWebViewController.h */,
FFF1E49D177504CA00BF59D3 /* IASKAppSettingsWebViewController.m */,
FFF1E49E177504CA00BF59D3 /* IASKSpecifierValuesViewController.h */,
FFF1E49F177504CA00BF59D3 /* IASKSpecifierValuesViewController.m */,
FFF1E4A0177504CA00BF59D3 /* IASKViewController.h */,
);
path = Controllers;
sourceTree = "<group>";
};
FFF1E4A1177504CA00BF59D3 /* Models */ = {
isa = PBXGroup;
children = (
FFF1E4A2177504CA00BF59D3 /* IASKSettingsReader.h */,
FFF1E4A3177504CA00BF59D3 /* IASKSettingsReader.m */,
FFF1E4A4177504CA00BF59D3 /* IASKSettingsStore.h */,
FFF1E4A5177504CA00BF59D3 /* IASKSettingsStore.m */,
FFF1E4A6177504CA00BF59D3 /* IASKSettingsStoreFile.h */,
FFF1E4A7177504CA00BF59D3 /* IASKSettingsStoreFile.m */,
FFF1E4A8177504CA00BF59D3 /* IASKSettingsStoreUserDefaults.h */,
FFF1E4A9177504CA00BF59D3 /* IASKSettingsStoreUserDefaults.m */,
FFF1E4AA177504CA00BF59D3 /* IASKSpecifier.h */,
FFF1E4AB177504CA00BF59D3 /* IASKSpecifier.m */,
);
path = Models;
sourceTree = "<group>";
};
FFF1E4AC177504CA00BF59D3 /* Views */ = {
isa = PBXGroup;
children = (
FFF1E4AD177504CA00BF59D3 /* IASKPSSliderSpecifierViewCell.h */,
FFF1E4AE177504CA00BF59D3 /* IASKPSSliderSpecifierViewCell.m */,
FFF1E4AF177504CA00BF59D3 /* IASKPSTextFieldSpecifierViewCell.h */,
FFF1E4B0177504CA00BF59D3 /* IASKPSTextFieldSpecifierViewCell.m */,
FFF1E4B1177504CA00BF59D3 /* IASKPSTitleValueSpecifierViewCell.h */,
FFF1E4B2177504CA00BF59D3 /* IASKPSTitleValueSpecifierViewCell.m */,
FFF1E4B3177504CA00BF59D3 /* IASKSlider.h */,
FFF1E4B4177504CA00BF59D3 /* IASKSlider.m */,
FFF1E4B5177504CA00BF59D3 /* IASKSwitch.h */,
FFF1E4B6177504CA00BF59D3 /* IASKSwitch.m */,
FFF1E4B7177504CA00BF59D3 /* IASKTextField.h */,
FFF1E4B8177504CA00BF59D3 /* IASKTextField.m */,
);
path = Views;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -2391,6 +2505,9 @@
FF8364C71757EC0B008F5C58 /* traverse_background_left@2x.png in Resources */,
FFC518B91768E59F00542719 /* g_icn_offline.png in Resources */,
FF1104611769695A00502C29 /* g_icn_offline@2x.png in Resources */,
FFF1E4C817750BDD00BF59D3 /* Settings.bundle in Resources */,
FFF1E4CB17750D2C00BF59D3 /* menu_icn_preferences.png in Resources */,
FFF1E4CC17750D2C00BF59D3 /* menu_icn_preferences@2x.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -2565,6 +2682,20 @@
FF753CD3175858FC00344EC9 /* FMResultSet.m in Sources */,
FF6618C8176184560039913B /* NBNotifier.m in Sources */,
FF11045F176950F900502C29 /* NBLoadingCell.m in Sources */,
FFF1E4B9177504CA00BF59D3 /* IASKAppSettingsViewController.m in Sources */,
FFF1E4BA177504CA00BF59D3 /* IASKAppSettingsWebViewController.m in Sources */,
FFF1E4BB177504CA00BF59D3 /* IASKSpecifierValuesViewController.m in Sources */,
FFF1E4BC177504CA00BF59D3 /* IASKSettingsReader.m in Sources */,
FFF1E4BD177504CA00BF59D3 /* IASKSettingsStore.m in Sources */,
FFF1E4BE177504CA00BF59D3 /* IASKSettingsStoreFile.m in Sources */,
FFF1E4BF177504CA00BF59D3 /* IASKSettingsStoreUserDefaults.m in Sources */,
FFF1E4C0177504CA00BF59D3 /* IASKSpecifier.m in Sources */,
FFF1E4C1177504CA00BF59D3 /* IASKPSSliderSpecifierViewCell.m in Sources */,
FFF1E4C2177504CA00BF59D3 /* IASKPSTextFieldSpecifierViewCell.m in Sources */,
FFF1E4C3177504CA00BF59D3 /* IASKPSTitleValueSpecifierViewCell.m in Sources */,
FFF1E4C4177504CA00BF59D3 /* IASKSlider.m in Sources */,
FFF1E4C5177504CA00BF59D3 /* IASKSwitch.m in Sources */,
FFF1E4C6177504CA00BF59D3 /* IASKTextField.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View file

@ -13,10 +13,10 @@
// #define BACKGROUND_REFRESH_SECONDS -5
#define BACKGROUND_REFRESH_SECONDS -10*60
#define NEWSBLUR_URL [NSString stringWithFormat:@"http://nb.local.com"]
#define NEWSBLUR_HOST [NSString stringWithFormat:@"nb.local.com"]
// #define NEWSBLUR_URL [NSString stringWithFormat:@"https://www.newsblur.com"]
// #define NEWSBLUR_HOST [NSString stringWithFormat:@"www.newsblur.com"]
// #define NEWSBLUR_URL [NSString stringWithFormat:@"http://nb.local.com"]
// #define NEWSBLUR_HOST [NSString stringWithFormat:@"nb.local.com"]
#define NEWSBLUR_URL [NSString stringWithFormat:@"https://www.newsblur.com"]
#define NEWSBLUR_HOST [NSString stringWithFormat:@"www.newsblur.com"]
#define NEWSBLUR_LINK_COLOR 0x405BA8
#define NEWSBLUR_HIGHLIGHT_COLOR 0xd2e6fd

View file

@ -0,0 +1,88 @@
//
// IASKAppSettingsViewController.h
// http://www.inappsettingskit.com
//
// Copyright (c) 2009:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>
#import "IASKSettingsStore.h"
#import "IASKViewController.h"
#import "IASKSpecifier.h"
@class IASKSettingsReader;
@class IASKAppSettingsViewController;
@protocol IASKSettingsDelegate
- (void)settingsViewControllerDidEnd:(IASKAppSettingsViewController*)sender;
@optional
#pragma mark - UITableView header customization
- (CGFloat) settingsViewController:(id<IASKViewController>)settingsViewController
tableView:(UITableView *)tableView
heightForHeaderForSection:(NSInteger)section;
- (UIView *) settingsViewController:(id<IASKViewController>)settingsViewController
tableView:(UITableView *)tableView
viewForHeaderForSection:(NSInteger)section;
#pragma mark - UITableView cell customization
- (CGFloat)tableView:(UITableView*)tableView heightForSpecifier:(IASKSpecifier*)specifier;
- (UITableViewCell*)tableView:(UITableView*)tableView cellForSpecifier:(IASKSpecifier*)specifier;
#pragma mark - mail composing customization
- (NSString*) settingsViewController:(id<IASKViewController>)settingsViewController
mailComposeBodyForSpecifier:(IASKSpecifier*) specifier;
- (UIViewController<MFMailComposeViewControllerDelegate>*) settingsViewController:(id<IASKViewController>)settingsViewController
viewControllerForMailComposeViewForSpecifier:(IASKSpecifier*) specifier;
- (void) settingsViewController:(id<IASKViewController>) settingsViewController
mailComposeController:(MFMailComposeViewController*)controller
didFinishWithResult:(MFMailComposeResult)result
error:(NSError*)error;
#pragma mark - respond to button taps
- (void)settingsViewController:(IASKAppSettingsViewController*)sender buttonTappedForKey:(NSString*)key __attribute__((deprecated)); // use the method below with specifier instead
- (void)settingsViewController:(IASKAppSettingsViewController*)sender buttonTappedForSpecifier:(IASKSpecifier*)specifier;
- (void)settingsViewController:(IASKAppSettingsViewController*)sender tableView:(UITableView *)tableView didSelectCustomViewSpecifier:(IASKSpecifier*)specifier;
@end
@interface IASKAppSettingsViewController : UITableViewController <IASKViewController, UITextFieldDelegate, MFMailComposeViewControllerDelegate> {
id<IASKSettingsDelegate> _delegate;
NSMutableArray *_viewList;
IASKSettingsReader *_settingsReader;
id<IASKSettingsStore> _settingsStore;
NSString *_file;
id _currentFirstResponder;
BOOL _showCreditsFooter;
BOOL _showDoneButton;
NSSet *_hiddenKeys;
}
@property (nonatomic, assign) IBOutlet id delegate;
@property (nonatomic, copy) NSString *file;
@property (nonatomic, assign) BOOL showCreditsFooter;
@property (nonatomic, assign) BOOL showDoneButton;
@property (nonatomic, retain) NSSet *hiddenKeys;
- (void)synchronizeSettings;
- (void)dismiss:(id)sender;
- (void)setHiddenKeys:(NSSet*)hiddenKeys animated:(BOOL)animated;
@end

View file

@ -0,0 +1,914 @@
//
// IASKAppSettingsViewController.m
// http://www.inappsettingskit.com
//
// Copyright (c) 2009-2010:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import "IASKAppSettingsViewController.h"
#import "IASKSettingsReader.h"
#import "IASKSettingsStoreUserDefaults.h"
#import "IASKPSSliderSpecifierViewCell.h"
#import "IASKPSTextFieldSpecifierViewCell.h"
#import "IASKPSTitleValueSpecifierViewCell.h"
#import "IASKSwitch.h"
#import "IASKSlider.h"
#import "IASKSpecifier.h"
#import "IASKSpecifierValuesViewController.h"
#import "IASKTextField.h"
static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.3;
static const CGFloat MINIMUM_SCROLL_FRACTION = 0.2;
static const CGFloat MAXIMUM_SCROLL_FRACTION = 0.8;
static NSString *kIASKCredits = @"Powered by InAppSettingsKit"; // Leave this as-is!!!
#define kIASKSpecifierValuesViewControllerIndex 0
#define kIASKSpecifierChildViewControllerIndex 1
#define kIASKCreditsViewWidth 285
CGRect IASKCGRectSwap(CGRect rect);
@interface IASKAppSettingsViewController ()
@property (nonatomic, retain) NSMutableArray *viewList;
@property (nonatomic, retain) id currentFirstResponder;
- (void)_textChanged:(id)sender;
- (void)synchronizeSettings;
- (void)userDefaultsDidChange;
- (void)reload;
@end
@implementation IASKAppSettingsViewController
@synthesize delegate = _delegate;
@synthesize viewList = _viewList;
@synthesize settingsReader = _settingsReader;
@synthesize file = _file;
@synthesize currentFirstResponder = _currentFirstResponder;
@synthesize showCreditsFooter = _showCreditsFooter;
@synthesize showDoneButton = _showDoneButton;
@synthesize settingsStore = _settingsStore;
@synthesize hiddenKeys = _hiddenKeys;
#pragma mark accessors
- (IASKSettingsReader*)settingsReader {
if (!_settingsReader) {
_settingsReader = [[IASKSettingsReader alloc] initWithFile:self.file];
}
return _settingsReader;
}
- (id<IASKSettingsStore>)settingsStore {
if (!_settingsStore) {
_settingsStore = [[IASKSettingsStoreUserDefaults alloc] init];
}
return _settingsStore;
}
- (NSString*)file {
if (!_file) {
return @"Root";
}
return [[_file retain] autorelease];
}
- (void)setFile:(NSString *)file {
if (file != _file) {
[_file release];
_file = [file copy];
}
self.tableView.contentOffset = CGPointMake(0, 0);
self.settingsReader = nil; // automatically initializes itself
[_hiddenKeys release], _hiddenKeys = nil;
[self.tableView reloadData];
}
- (BOOL)isPad {
BOOL isPad = NO;
#if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 30200)
isPad = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad;
#endif
return isPad;
}
#pragma mark standard view controller methods
- (id)init {
return [self initWithStyle:UITableViewStyleGrouped];
}
- (id)initWithStyle:(UITableViewStyle)style
{
if (style != UITableViewStyleGrouped) {
NSLog(@"only UITableViewStyleGrouped style is supported, forcing it.");
}
self = [super initWithStyle:UITableViewStyleGrouped];
if (self) {
self.tableView.delegate = self;
self.tableView.dataSource = self;
_showDoneButton = YES;
// If set to YES, will display credits for InAppSettingsKit creators
_showCreditsFooter = YES;
}
return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
if (!nibNameOrNil) {
return [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
}
NSLog (@"%@ is now deprecated, we are moving away from nibs.", NSStringFromSelector(_cmd));
return [self initWithStyle:UITableViewStyleGrouped];
}
- (NSMutableArray *)viewList {
if (!_viewList) {
_viewList = [[NSMutableArray alloc] init];
[_viewList addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"IASKSpecifierValuesView", @"ViewName",nil]];
[_viewList addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"IASKAppSettingsView", @"ViewName",nil]];
}
return _viewList;
}
- (void) viewDidLoad {
[super viewDidLoad];
if ([self isPad]) {
self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLineEtched;
}
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapToEndEdit:)];
tapGesture.cancelsTouchesInView = NO;
[self.tableView addGestureRecognizer:tapGesture];
[tapGesture release];
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.view = nil;
self.viewList = nil;
}
- (void)viewWillAppear:(BOOL)animated {
// if there's something selected, the value might have changed
// so reload that row
NSIndexPath *selectedIndexPath = [self.tableView indexPathForSelectedRow];
if(selectedIndexPath) {
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:selectedIndexPath]
withRowAnimation:UITableViewRowAnimationNone];
// and reselect it, so we get the nice default deselect animation from UITableViewController
[self.tableView selectRowAtIndexPath:selectedIndexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
}
self.navigationItem.rightBarButtonItem = nil;
if (_showDoneButton) {
UIBarButtonItem *buttonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:self
action:@selector(dismiss:)];
self.navigationItem.rightBarButtonItem = buttonItem;
[buttonItem release];
}
if (!self.title) {
self.title = NSLocalizedString(@"Settings", @"");
}
if ([self.settingsStore isKindOfClass:[IASKSettingsStoreUserDefaults class]]) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(userDefaultsDidChange)
name:NSUserDefaultsDidChangeNotification
object:[NSUserDefaults standardUserDefaults]];
[self userDefaultsDidChange]; // force update in case of changes while we were hidden
}
[super viewWillAppear:animated];
}
- (CGSize)contentSizeForViewInPopover {
return [[self view] sizeThatFits:CGSizeMake(320, 2000)];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSNotificationCenter *dc = [NSNotificationCenter defaultCenter];
IASK_IF_IOS4_OR_GREATER([dc addObserver:self selector:@selector(synchronizeSettings) name:UIApplicationDidEnterBackgroundNotification object:[UIApplication sharedApplication]];);
IASK_IF_IOS4_OR_GREATER([dc addObserver:self selector:@selector(reload) name:UIApplicationWillEnterForegroundNotification object:[UIApplication sharedApplication]];);
[dc addObserver:self selector:@selector(synchronizeSettings) name:UIApplicationWillTerminateNotification object:[UIApplication sharedApplication]];
}
- (void)viewWillDisappear:(BOOL)animated {
[NSObject cancelPreviousPerformRequestsWithTarget:self];
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated {
[[NSNotificationCenter defaultCenter] removeObserver:self];
// hide the keyboard
[self.currentFirstResponder resignFirstResponder];
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)setHiddenKeys:(NSSet *)theHiddenKeys {
[self setHiddenKeys:theHiddenKeys animated:NO];
}
- (void)setHiddenKeys:(NSSet*)theHiddenKeys animated:(BOOL)animated {
if (_hiddenKeys != theHiddenKeys) {
NSSet *oldHiddenKeys = _hiddenKeys;
_hiddenKeys = [theHiddenKeys retain];
if (animated) {
[self.tableView beginUpdates];
NSMutableSet *showKeys = [NSMutableSet setWithSet:oldHiddenKeys];
[showKeys minusSet:theHiddenKeys];
NSMutableSet *hideKeys = [NSMutableSet setWithSet:theHiddenKeys];
[hideKeys minusSet:oldHiddenKeys];
// calculate rows to be deleted
NSMutableArray *hideIndexPaths = [NSMutableArray array];
for (NSString *key in hideKeys) {
NSIndexPath *indexPath = [self.settingsReader indexPathForKey:key];
if (indexPath) {
[hideIndexPaths addObject:indexPath];
}
}
// calculate sections to be deleted
NSMutableIndexSet *hideSections = [NSMutableIndexSet indexSet];
for (NSInteger section = 0; section < [self numberOfSectionsInTableView:self.tableView ]; section++) {
NSUInteger rowsInSection = 0;
for (NSIndexPath *indexPath in hideIndexPaths) {
if (indexPath.section == section) {
rowsInSection++;
}
}
if (rowsInSection >= [self.settingsReader numberOfRowsForSection:section]) {
[hideSections addIndex:section];
}
}
// set the datasource
self.settingsReader.hiddenKeys = theHiddenKeys;
// calculate rows to be inserted
NSMutableArray *showIndexPaths = [NSMutableArray array];
for (NSString *key in showKeys) {
NSIndexPath *indexPath = [self.settingsReader indexPathForKey:key];
if (indexPath) {
[showIndexPaths addObject:indexPath];
}
}
// calculate sections to be inserted
NSMutableIndexSet *showSections = [NSMutableIndexSet indexSet];
for (NSInteger section = 0; section < [self.settingsReader numberOfSections]; section++) {
NSUInteger rowsInSection = 0;
for (NSIndexPath *indexPath in showIndexPaths) {
if (indexPath.section == section) {
rowsInSection++;
}
}
if (rowsInSection >= [self.settingsReader numberOfRowsForSection:section]) {
[showSections addIndex:section];
}
}
UITableViewRowAnimation animation = animated ? UITableViewRowAnimationTop : UITableViewRowAnimationNone;
[self.tableView deleteSections:hideSections withRowAnimation:animation];
[self.tableView deleteRowsAtIndexPaths:hideIndexPaths withRowAnimation:animation];
[self.tableView insertSections:showSections withRowAnimation:animation];
[self.tableView insertRowsAtIndexPaths:showIndexPaths withRowAnimation:animation];
[self.tableView endUpdates];
} else {
self.settingsReader.hiddenKeys = theHiddenKeys;
[self.tableView reloadData];
}
[oldHiddenKeys release];
}
IASKAppSettingsViewController *childViewController = [[self.viewList objectAtIndex:kIASKSpecifierChildViewControllerIndex] objectForKey:@"viewController"];
if(childViewController) {
[childViewController setHiddenKeys:theHiddenKeys animated:animated];
}
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[_viewList release], _viewList = nil;
[_file release], _file = nil;
[_currentFirstResponder release], _currentFirstResponder = nil;
[_settingsReader release], _settingsReader = nil;
[_settingsStore release], _settingsStore = nil;
[_hiddenKeys release], _hiddenKeys = nil;
_delegate = nil;
[super dealloc];
}
#pragma mark -
#pragma mark Actions
- (void)dismiss:(id)sender {
[self.settingsStore synchronize];
if (self.delegate && [self.delegate conformsToProtocol:@protocol(IASKSettingsDelegate)]) {
[self.delegate settingsViewControllerDidEnd:self];
}
}
- (void)toggledValue:(id)sender {
IASKSwitch *toggle = [[(IASKSwitch*)sender retain] autorelease];
IASKSpecifier *spec = [_settingsReader specifierForKey:[toggle key]];
if ([toggle isOn]) {
if ([spec trueValue] != nil) {
[self.settingsStore setObject:[spec trueValue] forKey:[toggle key]];
}
else {
[self.settingsStore setBool:YES forKey:[toggle key]];
}
}
else {
if ([spec falseValue] != nil) {
[self.settingsStore setObject:[spec falseValue] forKey:[toggle key]];
}
else {
[self.settingsStore setBool:NO forKey:[toggle key]];
}
}
[[NSNotificationCenter defaultCenter] postNotificationName:kIASKAppSettingChanged
object:[toggle key]
userInfo:[NSDictionary dictionaryWithObject:[self.settingsStore objectForKey:[toggle key]]
forKey:[toggle key]]];
}
- (void)sliderChangedValue:(id)sender {
IASKSlider *slider = [[(IASKSlider*)sender retain] autorelease];
[self.settingsStore setFloat:[slider value] forKey:[slider key]];
[[NSNotificationCenter defaultCenter] postNotificationName:kIASKAppSettingChanged
object:[slider key]
userInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:[slider value]]
forKey:[slider key]]];
}
#pragma mark -
#pragma mark UITableView Functions
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [self.settingsReader numberOfSections];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.settingsReader numberOfRowsForSection:section];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
IASKSpecifier *specifier = [self.settingsReader specifierForIndexPath:indexPath];
if ([[specifier type] isEqualToString:kIASKCustomViewSpecifier]) {
if ([self.delegate respondsToSelector:@selector(tableView:heightForSpecifier:)]) {
return [self.delegate tableView:tableView heightForSpecifier:specifier];
} else {
return 0;
}
}
return tableView.rowHeight;
}
- (NSString *)tableView:(UITableView*)tableView titleForHeaderInSection:(NSInteger)section {
NSString *header = [self.settingsReader titleForSection:section];
if (0 == header.length) {
return nil;
}
return header;
}
- (UIView *)tableView:(UITableView*)tableView viewForHeaderInSection:(NSInteger)section {
if ([self.delegate respondsToSelector:@selector(settingsViewController:tableView:viewForHeaderForSection:)]) {
return [self.delegate settingsViewController:self tableView:tableView viewForHeaderForSection:section];
} else {
return nil;
}
}
- (CGFloat)tableView:(UITableView*)tableView heightForHeaderInSection:(NSInteger)section {
if ([self tableView:tableView viewForHeaderInSection:section] && [self.delegate respondsToSelector:@selector(settingsViewController:tableView:heightForHeaderForSection:)]) {
CGFloat result;
if ((result = [self.delegate settingsViewController:self tableView:tableView heightForHeaderForSection:section])) {
return result;
}
}
NSString *title;
if ((title = [self tableView:tableView titleForHeaderInSection:section])) {
CGSize size = [title sizeWithFont:[UIFont boldSystemFontOfSize:[UIFont labelFontSize]]
constrainedToSize:CGSizeMake(tableView.frame.size.width - 2*kIASKHorizontalPaddingGroupTitles, INFINITY)
lineBreakMode:NSLineBreakByWordWrapping];
return size.height+kIASKVerticalPaddingGroupTitles;
}
return 0;
}
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
{
NSString *footerText = [self.settingsReader footerTextForSection:section];
if (_showCreditsFooter && (section == [self.settingsReader numberOfSections]-1)) {
// show credits since this is the last section
if ((footerText == nil) || ([footerText length] == 0)) {
// show the credits on their own
return kIASKCredits;
} else {
// show the credits below the app's FooterText
return [NSString stringWithFormat:@"%@\n\n%@", footerText, kIASKCredits];
}
} else {
if ([footerText length] == 0) {
return nil;
}
return [self.settingsReader footerTextForSection:section];
}
}
- (UITableViewCell*)newCellForIdentifier:(NSString*)identifier {
UITableViewCell *cell = nil;
if ([identifier isEqualToString:kIASKPSToggleSwitchSpecifier]) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kIASKPSToggleSwitchSpecifier];
cell.accessoryView = [[[IASKSwitch alloc] initWithFrame:CGRectMake(0, 0, 79, 27)] autorelease];
[((IASKSwitch*)cell.accessoryView) addTarget:self action:@selector(toggledValue:) forControlEvents:UIControlEventValueChanged];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
else if ([identifier isEqualToString:kIASKPSMultiValueSpecifier] || [identifier isEqualToString:kIASKPSTitleValueSpecifier]) {
cell = [[IASKPSTitleValueSpecifierViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier];
cell.accessoryType = [identifier isEqualToString:kIASKPSMultiValueSpecifier] ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone;
}
else if ([identifier isEqualToString:kIASKPSTextFieldSpecifier]) {
cell = [[IASKPSTextFieldSpecifierViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kIASKPSTextFieldSpecifier];
[((IASKPSTextFieldSpecifierViewCell*)cell).textField addTarget:self action:@selector(_textChanged:) forControlEvents:UIControlEventEditingChanged];
}
else if ([identifier isEqualToString:kIASKPSSliderSpecifier]) {
cell = [[IASKPSSliderSpecifierViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kIASKPSSliderSpecifier];
} else if ([identifier isEqualToString:kIASKPSChildPaneSpecifier]) {
cell = [[IASKPSTitleValueSpecifierViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
} else if ([identifier isEqualToString:kIASKMailComposeSpecifier]) {
cell = [[IASKPSTitleValueSpecifierViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
} else {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
cell.textLabel.minimumFontSize = kIASKMinimumFontSize;
cell.detailTextLabel.minimumFontSize = kIASKMinimumFontSize;
return cell;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
IASKSpecifier *specifier = [self.settingsReader specifierForIndexPath:indexPath];
if ([specifier.type isEqualToString:kIASKCustomViewSpecifier] && [self.delegate respondsToSelector:@selector(tableView:cellForSpecifier:)]) {
UITableViewCell* cell = [self.delegate tableView:tableView cellForSpecifier:specifier];
assert(nil != cell && "delegate must return a UITableViewCell for custom cell types");
return cell;
}
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:specifier.type];
if(nil == cell) {
cell = [[self newCellForIdentifier:specifier.type] autorelease];
}
if ([specifier.type isEqualToString:kIASKPSToggleSwitchSpecifier]) {
cell.textLabel.text = specifier.title;
id currentValue = [self.settingsStore objectForKey:specifier.key];
BOOL toggleState;
if (currentValue) {
if ([currentValue isEqual:specifier.trueValue]) {
toggleState = YES;
} else if ([currentValue isEqual:specifier.falseValue]) {
toggleState = NO;
} else {
toggleState = [currentValue boolValue];
}
} else {
toggleState = specifier.defaultBoolValue;
}
IASKSwitch *toggle = (IASKSwitch*)cell.accessoryView;
toggle.on = toggleState;
toggle.key = specifier.key;
}
else if ([specifier.type isEqualToString:kIASKPSMultiValueSpecifier]) {
cell.textLabel.text = specifier.title;
cell.detailTextLabel.text = [[specifier titleForCurrentValue:[self.settingsStore objectForKey:specifier.key] != nil ?
[self.settingsStore objectForKey:specifier.key] : specifier.defaultValue] description];
}
else if ([specifier.type isEqualToString:kIASKPSTitleValueSpecifier]) {
cell.textLabel.text = specifier.title;
id value = [self.settingsStore objectForKey:specifier.key] ? : specifier.defaultValue;
NSString *stringValue;
if (specifier.multipleValues || specifier.multipleTitles) {
stringValue = [specifier titleForCurrentValue:value];
} else {
stringValue = [value description];
}
cell.detailTextLabel.text = stringValue;
cell.userInteractionEnabled = NO;
}
else if ([specifier.type isEqualToString:kIASKPSTextFieldSpecifier]) {
cell.textLabel.text = specifier.title;
NSString *textValue = [self.settingsStore objectForKey:specifier.key] != nil ? [self.settingsStore objectForKey:specifier.key] : specifier.defaultStringValue;
if (textValue && ![textValue isMemberOfClass:[NSString class]]) {
textValue = [NSString stringWithFormat:@"%@", textValue];
}
IASKTextField *textField = ((IASKPSTextFieldSpecifierViewCell*)cell).textField;
textField.text = textValue;
textField.key = specifier.key;
textField.delegate = self;
textField.secureTextEntry = [specifier isSecure];
textField.keyboardType = specifier.keyboardType;
textField.autocapitalizationType = specifier.autocapitalizationType;
if([specifier isSecure]){
textField.autocorrectionType = UITextAutocorrectionTypeNo;
} else {
textField.autocorrectionType = specifier.autoCorrectionType;
}
textField.textAlignment = specifier.textAlignment;
textField.adjustsFontSizeToFitWidth = specifier.adjustsFontSizeToFitWidth;
}
else if ([specifier.type isEqualToString:kIASKPSSliderSpecifier]) {
if (specifier.minimumValueImage.length > 0) {
((IASKPSSliderSpecifierViewCell*)cell).minImage.image = [UIImage imageWithContentsOfFile:[_settingsReader pathForImageNamed:specifier.minimumValueImage]];
}
if (specifier.maximumValueImage.length > 0) {
((IASKPSSliderSpecifierViewCell*)cell).maxImage.image = [UIImage imageWithContentsOfFile:[_settingsReader pathForImageNamed:specifier.maximumValueImage]];
}
IASKSlider *slider = ((IASKPSSliderSpecifierViewCell*)cell).slider;
slider.minimumValue = specifier.minimumValue;
slider.maximumValue = specifier.maximumValue;
slider.value = [self.settingsStore objectForKey:specifier.key] != nil ? [[self.settingsStore objectForKey:specifier.key] floatValue] : [specifier.defaultValue floatValue];
[slider addTarget:self action:@selector(sliderChangedValue:) forControlEvents:UIControlEventValueChanged];
slider.key = specifier.key;
[cell setNeedsLayout];
}
else if ([specifier.type isEqualToString:kIASKPSChildPaneSpecifier]) {
cell.textLabel.text = specifier.title;
} else if ([specifier.type isEqualToString:kIASKOpenURLSpecifier] || [specifier.type isEqualToString:kIASKMailComposeSpecifier]) {
cell.textLabel.text = specifier.title;
cell.detailTextLabel.text = [specifier.defaultValue description];
} else if ([specifier.type isEqualToString:kIASKButtonSpecifier]) {
NSString *value = [self.settingsStore objectForKey:specifier.key];
cell.textLabel.text = [value isKindOfClass:[NSString class]] ? [self.settingsReader titleForStringId:value] : specifier.title;
} else {
cell.textLabel.text = specifier.title;
}
cell.imageView.image = specifier.cellImage;
cell.imageView.highlightedImage = specifier.highlightedCellImage;
if (![specifier.type isEqualToString:kIASKPSMultiValueSpecifier] && ![specifier.type isEqualToString:kIASKPSTitleValueSpecifier] && ![specifier.type isEqualToString:kIASKPSTextFieldSpecifier]) {
cell.textLabel.textAlignment = specifier.textAlignment;
}
cell.detailTextLabel.textAlignment = specifier.textAlignment;
cell.textLabel.adjustsFontSizeToFitWidth = specifier.adjustsFontSizeToFitWidth;
cell.detailTextLabel.adjustsFontSizeToFitWidth = specifier.adjustsFontSizeToFitWidth;
return cell;
}
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//create a set of specifier types that can't be selected
static NSSet* noSelectionTypes = nil;
if(nil == noSelectionTypes) {
noSelectionTypes = [[NSSet setWithObjects:kIASKPSToggleSwitchSpecifier, kIASKPSSliderSpecifier, nil] retain];
}
IASKSpecifier *specifier = [self.settingsReader specifierForIndexPath:indexPath];
if([noSelectionTypes containsObject:specifier.type]) {
return nil;
} else {
return indexPath;
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
IASKSpecifier *specifier = [self.settingsReader specifierForIndexPath:indexPath];
//switches and sliders can't be selected (should be captured by tableView:willSelectRowAtIndexPath: delegate method)
assert(![[specifier type] isEqualToString:kIASKPSToggleSwitchSpecifier]);
assert(![[specifier type] isEqualToString:kIASKPSSliderSpecifier]);
if ([[specifier type] isEqualToString:kIASKPSMultiValueSpecifier]) {
IASKSpecifierValuesViewController *targetViewController = [[self.viewList objectAtIndex:kIASKSpecifierValuesViewControllerIndex] objectForKey:@"viewController"];
if (targetViewController == nil) {
// the view controller has not been created yet, create it and set it to our viewList array
// create a new dictionary with the new view controller
NSMutableDictionary *newItemDict = [NSMutableDictionary dictionaryWithCapacity:3];
[newItemDict addEntriesFromDictionary: [self.viewList objectAtIndex:kIASKSpecifierValuesViewControllerIndex]]; // copy the title and explain strings
targetViewController = [[IASKSpecifierValuesViewController alloc] init];
// add the new view controller to the dictionary and then to the 'viewList' array
[newItemDict setObject:targetViewController forKey:@"viewController"];
[self.viewList replaceObjectAtIndex:kIASKSpecifierValuesViewControllerIndex withObject:newItemDict];
[targetViewController release];
// load the view controll back in to push it
targetViewController = [[self.viewList objectAtIndex:kIASKSpecifierValuesViewControllerIndex] objectForKey:@"viewController"];
}
[targetViewController setCurrentSpecifier:specifier];
targetViewController.settingsReader = self.settingsReader;
targetViewController.settingsStore = self.settingsStore;
[[self navigationController] pushViewController:targetViewController animated:YES];
}
else if ([[specifier type] isEqualToString:kIASKPSTextFieldSpecifier]) {
IASKPSTextFieldSpecifierViewCell *textFieldCell = (id)[tableView cellForRowAtIndexPath:indexPath];
[textFieldCell.textField becomeFirstResponder];
}
else if ([[specifier type] isEqualToString:kIASKPSChildPaneSpecifier]) {
Class vcClass = [specifier viewControllerClass];
if (vcClass) {
SEL initSelector = [specifier viewControllerSelector];
if (!initSelector) {
initSelector = @selector(init);
}
UIViewController * vc = [vcClass performSelector:@selector(alloc)];
[vc performSelector:initSelector withObject:[specifier file] withObject:[specifier key]];
if ([vc respondsToSelector:@selector(setDelegate:)]) {
[vc performSelector:@selector(setDelegate:) withObject:self.delegate];
}
if ([vc respondsToSelector:@selector(setSettingsStore:)]) {
[vc performSelector:@selector(setSettingsStore:) withObject:self.settingsStore];
}
[self.navigationController pushViewController:vc animated:YES];
[vc performSelector:@selector(release)];
return;
}
if (nil == [specifier file]) {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
return;
}
IASKAppSettingsViewController *targetViewController = [[self.viewList objectAtIndex:kIASKSpecifierChildViewControllerIndex] objectForKey:@"viewController"];
if (targetViewController == nil) {
// the view controller has not been created yet, create it and set it to our viewList array
// create a new dictionary with the new view controller
NSMutableDictionary *newItemDict = [NSMutableDictionary dictionaryWithCapacity:3];
[newItemDict addEntriesFromDictionary: [self.viewList objectAtIndex:kIASKSpecifierChildViewControllerIndex]]; // copy the title and explain strings
targetViewController = [[[self class] alloc] init];
targetViewController.showDoneButton = NO;
targetViewController.settingsStore = self.settingsStore;
targetViewController.delegate = self.delegate;
// add the new view controller to the dictionary and then to the 'viewList' array
[newItemDict setObject:targetViewController forKey:@"viewController"];
[self.viewList replaceObjectAtIndex:kIASKSpecifierChildViewControllerIndex withObject:newItemDict];
[targetViewController release];
// load the view controll back in to push it
targetViewController = [[self.viewList objectAtIndex:kIASKSpecifierChildViewControllerIndex] objectForKey:@"viewController"];
}
targetViewController.file = specifier.file;
targetViewController.hiddenKeys = self.hiddenKeys;
targetViewController.title = specifier.title;
targetViewController.showCreditsFooter = NO;
[[self navigationController] pushViewController:targetViewController animated:YES];
} else if ([[specifier type] isEqualToString:kIASKOpenURLSpecifier]) {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:specifier.file]];
} else if ([[specifier type] isEqualToString:kIASKButtonSpecifier]) {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if ([self.delegate respondsToSelector:@selector(settingsViewController:buttonTappedForSpecifier:)]) {
[self.delegate settingsViewController:self buttonTappedForSpecifier:specifier];
} else if ([self.delegate respondsToSelector:@selector(settingsViewController:buttonTappedForKey:)]) {
// deprecated, provided for backward compatibility
NSLog(@"InAppSettingsKit Warning: -settingsViewController:buttonTappedForKey: is deprecated. Please use -settingsViewController:buttonTappedForSpecifier:");
[self.delegate settingsViewController:self buttonTappedForKey:[specifier key]];
} else {
// legacy code, provided for backward compatibility
// the delegate mechanism above is much cleaner and doesn't leak
Class buttonClass = [specifier buttonClass];
SEL buttonAction = [specifier buttonAction];
if ([buttonClass respondsToSelector:buttonAction]) {
[buttonClass performSelector:buttonAction withObject:self withObject:[specifier key]];
NSLog(@"InAppSettingsKit Warning: Using IASKButtonSpecifier without implementing the delegate method is deprecated");
}
}
} else if ([[specifier type] isEqualToString:kIASKMailComposeSpecifier]) {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if ([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *mailViewController = [[MFMailComposeViewController alloc] init];
mailViewController.navigationBar.barStyle = self.navigationController.navigationBar.barStyle;
mailViewController.navigationBar.tintColor = self.navigationController.navigationBar.tintColor;
if ([specifier localizedObjectForKey:kIASKMailComposeSubject]) {
[mailViewController setSubject:[specifier localizedObjectForKey:kIASKMailComposeSubject]];
}
if ([[specifier specifierDict] objectForKey:kIASKMailComposeToRecipents]) {
[mailViewController setToRecipients:[[specifier specifierDict] objectForKey:kIASKMailComposeToRecipents]];
}
if ([[specifier specifierDict] objectForKey:kIASKMailComposeCcRecipents]) {
[mailViewController setCcRecipients:[[specifier specifierDict] objectForKey:kIASKMailComposeCcRecipents]];
}
if ([[specifier specifierDict] objectForKey:kIASKMailComposeBccRecipents]) {
[mailViewController setBccRecipients:[[specifier specifierDict] objectForKey:kIASKMailComposeBccRecipents]];
}
if ([specifier localizedObjectForKey:kIASKMailComposeBody]) {
BOOL isHTML = NO;
if ([[specifier specifierDict] objectForKey:kIASKMailComposeBodyIsHTML]) {
isHTML = [[[specifier specifierDict] objectForKey:kIASKMailComposeBodyIsHTML] boolValue];
}
if ([self.delegate respondsToSelector:@selector(settingsViewController:mailComposeBodyForSpecifier:)]) {
[mailViewController setMessageBody:[self.delegate settingsViewController:self
mailComposeBodyForSpecifier:specifier] isHTML:isHTML];
}
else {
[mailViewController setMessageBody:[specifier localizedObjectForKey:kIASKMailComposeBody] isHTML:isHTML];
}
}
UIViewController<MFMailComposeViewControllerDelegate> *vc = nil;
if ([self.delegate respondsToSelector:@selector(settingsViewController:viewControllerForMailComposeViewForSpecifier:)]) {
vc = [self.delegate settingsViewController:self viewControllerForMailComposeViewForSpecifier:specifier];
}
if (vc == nil) {
vc = self;
}
mailViewController.mailComposeDelegate = vc;
#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 50000)
#pragma message "Now that we're iOS5 and up, remove this workaround"
#endif
if([vc respondsToSelector:@selector(presentViewController:animated:completion:)]) {
[vc presentViewController:mailViewController
animated:YES
completion:nil];
} else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[vc presentModalViewController:mailViewController animated:YES];
#pragma clang diagnostic pop
}
[mailViewController release];
} else {
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:NSLocalizedString(@"Mail not configured", @"InAppSettingsKit")
message:NSLocalizedString(@"This device is not configured for sending Email. Please configure the Mail settings in the Settings app.", @"InAppSettingsKit")
delegate: nil
cancelButtonTitle:NSLocalizedString(@"OK", @"InAppSettingsKit")
otherButtonTitles:nil];
[alert show];
[alert release];
}
} else if ([[specifier type] isEqualToString:kIASKCustomViewSpecifier] && [self.delegate respondsToSelector:@selector(settingsViewController:tableView:didSelectCustomViewSpecifier:)]) {
[self.delegate settingsViewController:self tableView:tableView didSelectCustomViewSpecifier:specifier];
} else {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
}
}
#pragma mark -
#pragma mark MFMailComposeViewControllerDelegate Function
-(void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
// Forward the mail compose delegate
if ([self.delegate respondsToSelector:@selector(settingsViewController:mailComposeController:didFinishWithResult:error:)]) {
[self.delegate settingsViewController:self
mailComposeController:controller
didFinishWithResult:result
error:error];
}
#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 50000)
#pragma message "Now that we're iOS5 and up, remove this workaround"
#endif
if([self respondsToSelector:@selector(dismissViewControllerAnimated:completion:)]) {
[self dismissViewControllerAnimated:YES
completion:nil];
} else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[self dismissModalViewControllerAnimated:YES];
#pragma clang diagnostic pop
}
}
#pragma mark -
#pragma mark UITextFieldDelegate Functions
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
self.currentFirstResponder = textField;
return YES;
}
- (void)_textChanged:(id)sender {
IASKTextField *text = [[(IASKTextField*)sender retain] autorelease];
[_settingsStore setObject:[text text] forKey:[text key]];
[[NSNotificationCenter defaultCenter] postNotificationName:kIASKAppSettingChanged
object:[text key]
userInfo:[NSDictionary dictionaryWithObject:[text text]
forKey:[text key]]];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
self.currentFirstResponder = nil;
return YES;
}
- (void)singleTapToEndEdit:(UIGestureRecognizer *)sender {
[self.tableView endEditing:NO];
}
#pragma mark Notifications
- (void)synchronizeSettings {
[_settingsStore synchronize];
}
static NSDictionary *oldUserDefaults = nil;
- (void)userDefaultsDidChange {
NSDictionary *currentDict = [NSUserDefaults standardUserDefaults].dictionaryRepresentation;
NSMutableArray *indexPathsToUpdate = [NSMutableArray array];
for (NSString *key in currentDict.allKeys) {
if (![[oldUserDefaults valueForKey:key] isEqual:[currentDict valueForKey:key]]) {
NSIndexPath *path = [self.settingsReader indexPathForKey:key];
if (path && ![[self.settingsReader specifierForKey:key].type isEqualToString:kIASKCustomViewSpecifier]) {
[indexPathsToUpdate addObject:path];
}
}
}
[oldUserDefaults release], oldUserDefaults = [currentDict retain];
for (UITableViewCell *cell in self.tableView.visibleCells) {
if ([cell isKindOfClass:[IASKPSTextFieldSpecifierViewCell class]] && [((IASKPSTextFieldSpecifierViewCell*)cell).textField isFirstResponder]) {
[indexPathsToUpdate removeObject:[self.tableView indexPathForCell:cell]];
}
}
if (indexPathsToUpdate.count) {
[self.tableView reloadRowsAtIndexPaths:indexPathsToUpdate withRowAnimation:UITableViewRowAnimationNone];
}
}
- (void)reload {
// wait 0.5 sec until UI is available after applicationWillEnterForeground
[self.tableView performSelector:@selector(reloadData) withObject:nil afterDelay:0.5];
}
#pragma mark CGRect Utility function
CGRect IASKCGRectSwap(CGRect rect) {
CGRect newRect;
newRect.origin.x = rect.origin.y;
newRect.origin.y = rect.origin.x;
newRect.size.width = rect.size.height;
newRect.size.height = rect.size.width;
return newRect;
}
@end

View file

@ -0,0 +1,30 @@
//
// IASKAppSettingsWebViewController.h
// http://www.inappsettingskit.com
//
// Copyright (c) 2009:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>
@interface IASKAppSettingsWebViewController : UIViewController <UIWebViewDelegate, MFMailComposeViewControllerDelegate> {
UIWebView *webView;
NSURL *url;
}
- (id)initWithFile:(NSString*)htmlFileName key:(NSString*)key;
@property (nonatomic, retain) UIWebView *webView;
@property (nonatomic, retain) NSURL *url;
@end

View file

@ -0,0 +1,180 @@
//
// IASKAppSettingsWebViewController.h
// http://www.inappsettingskit.com
//
// Copyright (c) 2010:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import "IASKAppSettingsWebViewController.h"
@implementation IASKAppSettingsWebViewController
@synthesize url;
@synthesize webView;
- (id)initWithFile:(NSString*)urlString key:(NSString*)key {
self = [super init];
if (self) {
self.url = [NSURL URLWithString:urlString];
if (!self.url || ![self.url scheme]) {
NSString *path = [[NSBundle mainBundle] pathForResource:[urlString stringByDeletingPathExtension] ofType:[urlString pathExtension]];
if(path)
self.url = [NSURL fileURLWithPath:path];
else
self.url = nil;
}
}
return self;
}
- (void)loadView
{
webView = [[UIWebView alloc] init];
webView.autoresizingMask = UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleHeight;
webView.delegate = self;
self.view = webView;
}
- (void)dealloc {
[webView release], webView = nil;
[url release], url = nil;
[super dealloc];
}
- (void)viewWillAppear:(BOOL)animated {
[webView loadRequest:[NSURLRequest requestWithURL:self.url]];
}
- (void)viewDidUnload {
[super viewDidUnload];
self.webView = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
self.navigationItem.title = [self.webView stringByEvaluatingJavaScriptFromString:@"document.title"];
}
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSURL *newURL = [request URL];
// intercept mailto URL and send it to an in-app Mail compose view instead
if ([[newURL scheme] isEqualToString:@"mailto"]) {
NSArray *rawURLparts = [[newURL resourceSpecifier] componentsSeparatedByString:@"?"];
if (rawURLparts.count > 2) {
return NO; // invalid URL
}
MFMailComposeViewController *mailViewController = [[MFMailComposeViewController alloc] init];
mailViewController.mailComposeDelegate = self;
NSMutableArray *toRecipients = [NSMutableArray array];
NSString *defaultRecipient = [rawURLparts objectAtIndex:0];
if (defaultRecipient.length) {
[toRecipients addObject:defaultRecipient];
}
if (rawURLparts.count == 2) {
NSString *queryString = [rawURLparts objectAtIndex:1];
NSArray *params = [queryString componentsSeparatedByString:@"&"];
for (NSString *param in params) {
NSArray *keyValue = [param componentsSeparatedByString:@"="];
if (keyValue.count != 2) {
continue;
}
NSString *key = [[keyValue objectAtIndex:0] lowercaseString];
NSString *value = [keyValue objectAtIndex:1];
value = (NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault,
(CFStringRef)value,
CFSTR(""),
kCFStringEncodingUTF8);
[value autorelease];
if ([key isEqualToString:@"subject"]) {
[mailViewController setSubject:value];
}
if ([key isEqualToString:@"body"]) {
[mailViewController setMessageBody:value isHTML:NO];
}
if ([key isEqualToString:@"to"]) {
[toRecipients addObjectsFromArray:[value componentsSeparatedByString:@","]];
}
if ([key isEqualToString:@"cc"]) {
NSArray *recipients = [value componentsSeparatedByString:@","];
[mailViewController setCcRecipients:recipients];
}
if ([key isEqualToString:@"bcc"]) {
NSArray *recipients = [value componentsSeparatedByString:@","];
[mailViewController setBccRecipients:recipients];
}
}
}
[mailViewController setToRecipients:toRecipients];
#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 50000)
#pragma message "Now that we're iOS5 and up, remove this workaround"
#endif
if([self respondsToSelector:@selector(presentViewController:animated:completion:)]) {
[self presentViewController:mailViewController
animated:YES
completion:nil];
} else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[self presentModalViewController:mailViewController animated:YES];
#pragma clang diagnostic pop
}
[mailViewController release];
return NO;
}
// open inline if host is the same, otherwise, pass to the system
if (![newURL host] || [[newURL host] isEqualToString:[self.url host]]) {
return YES;
}
[[UIApplication sharedApplication] openURL:newURL];
return NO;
}
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 50000)
#pragma message "Now that we're iOS5 and up, remove this workaround"
#endif
if([self respondsToSelector:@selector(dismissViewControllerAnimated:completion:)]) {
[self dismissViewControllerAnimated:YES
completion:nil];
} else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[self dismissModalViewControllerAnimated:YES];
#pragma clang diagnostic pop
}
}
@end

View file

@ -0,0 +1,36 @@
//
// IASKSpecifierValuesViewController.h
// http://www.inappsettingskit.com
//
// Copyright (c) 2009:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import <UIKit/UIKit.h>
#import "IASKSettingsStore.h"
#import "IASKViewController.h"
@class IASKSpecifier;
@class IASKSettingsReader;
@interface IASKSpecifierValuesViewController : UIViewController<IASKViewController,UITableViewDelegate,UITableViewDataSource> {
UITableView *_tableView;
IASKSpecifier *_currentSpecifier;
NSIndexPath *_checkedItem;
IASKSettingsReader *_settingsReader;
id<IASKSettingsStore> _settingsStore;
}
@property (nonatomic, retain) UITableView *tableView;
@property (nonatomic, retain) NSIndexPath *checkedItem;
@property (nonatomic, retain) IASKSpecifier *currentSpecifier;
@end

View file

@ -0,0 +1,211 @@
//
// IASKSpecifierValuesViewController.m
// http://www.inappsettingskit.com
//
// Copyright (c) 2009:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import "IASKSpecifierValuesViewController.h"
#import "IASKSpecifier.h"
#import "IASKSettingsReader.h"
#import "IASKSettingsStoreUserDefaults.h"
#define kCellValue @"kCellValue"
@interface IASKSpecifierValuesViewController()
- (void)userDefaultsDidChange;
@end
@implementation IASKSpecifierValuesViewController
@synthesize tableView=_tableView;
@synthesize currentSpecifier=_currentSpecifier;
@synthesize checkedItem=_checkedItem;
@synthesize settingsReader = _settingsReader;
@synthesize settingsStore = _settingsStore;
- (void) updateCheckedItem {
NSInteger index;
// Find the currently checked item
if([self.settingsStore objectForKey:[_currentSpecifier key]]) {
index = [[_currentSpecifier multipleValues] indexOfObject:[self.settingsStore objectForKey:[_currentSpecifier key]]];
} else {
index = [[_currentSpecifier multipleValues] indexOfObject:[_currentSpecifier defaultValue]];
}
[self setCheckedItem:[NSIndexPath indexPathForRow:index inSection:0]];
}
- (id<IASKSettingsStore>)settingsStore {
if(_settingsStore == nil) {
_settingsStore = [[IASKSettingsStoreUserDefaults alloc] init];
}
return _settingsStore;
}
- (void)loadView
{
_tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
_tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleHeight;
_tableView.delegate = self;
_tableView.dataSource = self;
self.view = _tableView;
}
- (void)viewWillAppear:(BOOL)animated {
if (_currentSpecifier) {
[self setTitle:[_currentSpecifier title]];
[self updateCheckedItem];
}
if (_tableView) {
[_tableView reloadData];
// Make sure the currently checked item is visible
[_tableView scrollToRowAtIndexPath:[self checkedItem] atScrollPosition:UITableViewScrollPositionMiddle animated:NO];
}
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated {
[_tableView flashScrollIndicators];
[super viewDidAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(userDefaultsDidChange)
name:NSUserDefaultsDidChangeNotification
object:[NSUserDefaults standardUserDefaults]];
}
- (void)viewDidDisappear:(BOOL)animated {
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSUserDefaultsDidChangeNotification object:nil];
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.tableView = nil;
}
- (void)dealloc {
[_currentSpecifier release], _currentSpecifier = nil;
[_checkedItem release], _checkedItem = nil;
[_settingsReader release], _settingsReader = nil;
[_settingsStore release], _settingsStore = nil;
[_tableView release], _tableView = nil;
[super dealloc];
}
#pragma mark -
#pragma mark UITableView delegates
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [_currentSpecifier multipleValuesCount];
}
- (void)selectCell:(UITableViewCell *)cell {
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
[[cell textLabel] setTextColor:kIASKgrayBlueColor];
}
- (void)deselectCell:(UITableViewCell *)cell {
[cell setAccessoryType:UITableViewCellAccessoryNone];
[[cell textLabel] setTextColor:[UIColor darkTextColor]];
}
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
return [_currentSpecifier footerText];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellValue];
NSArray *titles = [_currentSpecifier multipleTitles];
if (!cell) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellValue] autorelease];
}
if ([indexPath isEqual:[self checkedItem]]) {
[self selectCell:cell];
} else {
[self deselectCell:cell];
}
@try {
[[cell textLabel] setText:[self.settingsReader titleForStringId:[titles objectAtIndex:indexPath.row]]];
}
@catch (NSException * e) {}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath == [self checkedItem]) {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
return;
}
NSArray *values = [_currentSpecifier multipleValues];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[self deselectCell:[tableView cellForRowAtIndexPath:[self checkedItem]]];
[self selectCell:[tableView cellForRowAtIndexPath:indexPath]];
[self setCheckedItem:indexPath];
[self.settingsStore setObject:[values objectAtIndex:indexPath.row] forKey:[_currentSpecifier key]];
[self.settingsStore synchronize];
[[NSNotificationCenter defaultCenter] postNotificationName:kIASKAppSettingChanged
object:[_currentSpecifier key]
userInfo:[NSDictionary dictionaryWithObject:[values objectAtIndex:indexPath.row]
forKey:[_currentSpecifier key]]];
}
- (CGSize)contentSizeForViewInPopover {
return [[self view] sizeThatFits:CGSizeMake(320, 2000)];
}
#pragma mark Notifications
- (void)userDefaultsDidChange {
NSIndexPath *oldCheckedItem = [[self.checkedItem retain] autorelease];
if(_currentSpecifier) {
[self updateCheckedItem];
}
// only reload the table if it had changed; prevents animation cancellation
if (![self.checkedItem isEqual:oldCheckedItem]) {
[_tableView reloadData];
}
}
@end

View file

@ -0,0 +1,26 @@
//
// IASKAppSettingsViewController.h
// http://www.inappsettingskit.com
//
// Copyright (c) 2009:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
@class IASKSettingsReader;
@protocol IASKSettingsStore;
// protocol all IASK view controllers implement
@protocol IASKViewController <NSObject>
@property (nonatomic, retain) IASKSettingsReader* settingsReader;
@property (nonatomic, retain) id<IASKSettingsStore> settingsStore;
@end

View file

@ -0,0 +1,178 @@
//
// IASKSettingsReader.h
// http://www.inappsettingskit.com
//
// Copyright (c) 2009:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#define kIASKPreferenceSpecifiers @"PreferenceSpecifiers"
#define kIASKCellImage @"IASKCellImage"
#define kIASKType @"Type"
#define kIASKTitle @"Title"
#define kIASKFooterText @"FooterText"
#define kIASKKey @"Key"
#define kIASKFile @"File"
#define kIASKDefaultValue @"DefaultValue"
#define kIASKMinimumValue @"MinimumValue"
#define kIASKMaximumValue @"MaximumValue"
#define kIASKTrueValue @"TrueValue"
#define kIASKFalseValue @"FalseValue"
#define kIASKIsSecure @"IsSecure"
#define KIASKKeyboardType @"KeyboardType"
#define kIASKAutocapitalizationType @"AutocapitalizationType"
#define kIASKAutoCorrectionType @"AutocorrectionType"
#define kIASKValues @"Values"
#define kIASKTitles @"Titles"
#define kIASKViewControllerClass @"IASKViewControllerClass"
#define kIASKViewControllerSelector @"IASKViewControllerSelector"
#define kIASKButtonClass @"IASKButtonClass"
#define kIASKButtonAction @"IASKButtonAction"
#define kIASKMailComposeToRecipents @"IASKMailComposeToRecipents"
#define kIASKMailComposeCcRecipents @"IASKMailComposeCcRecipents"
#define kIASKMailComposeBccRecipents @"IASKMailComposeBccRecipents"
#define kIASKMailComposeSubject @"IASKMailComposeSubject"
#define kIASKMailComposeBody @"IASKMailComposeBody"
#define kIASKMailComposeBodyIsHTML @"IASKMailComposeBodyIsHTML"
#define kIASKKeyboardAlphabet @"Alphabet"
#define kIASKKeyboardNumbersAndPunctuation @"NumbersAndPunctuation"
#define kIASKKeyboardNumberPad @"NumberPad"
#define kIASKKeyboardDecimalPad @"DecimalPad"
#define kIASKKeyboardPhonePad @"PhonePad"
#define kIASKKeyboardNamePhonePad @"NamePhonePad"
#define kIASKKeyboardASCIICapable @"AsciiCapable"
#define KIASKKeyboardURL @"URL"
#define kIASKKeyboardEmailAddress @"EmailAddress"
#define kIASKAutoCapNone @"None"
#define kIASKAutoCapSentences @"Sentences"
#define kIASKAutoCapWords @"Words"
#define kIASKAutoCapAllCharacters @"AllCharacters"
#define kIASKAutoCorrDefault @"Default"
#define kIASKAutoCorrNo @"No"
#define kIASKAutoCorrYes @"Yes"
#define kIASKMinimumValueImage @"MinimumValueImage"
#define kIASKMaximumValueImage @"MaximumValueImage"
#define kIASKAdjustsFontSizeToFitWidth @"IASKAdjustsFontSizeToFitWidth"
#define kIASKTextLabelAlignment @"IASKTextAlignment"
#define kIASKTextLabelAlignmentLeft @"IASKUITextAlignmentLeft"
#define kIASKTextLabelAlignmentCenter @"IASKUITextAlignmentCenter"
#define kIASKTextLabelAlignmentRight @"IASKUITextAlignmentRight"
#define kIASKPSGroupSpecifier @"PSGroupSpecifier"
#define kIASKPSToggleSwitchSpecifier @"PSToggleSwitchSpecifier"
#define kIASKPSMultiValueSpecifier @"PSMultiValueSpecifier"
#define kIASKPSSliderSpecifier @"PSSliderSpecifier"
#define kIASKPSTitleValueSpecifier @"PSTitleValueSpecifier"
#define kIASKPSTextFieldSpecifier @"PSTextFieldSpecifier"
#define kIASKPSChildPaneSpecifier @"PSChildPaneSpecifier"
#define kIASKOpenURLSpecifier @"IASKOpenURLSpecifier"
#define kIASKButtonSpecifier @"IASKButtonSpecifier"
#define kIASKMailComposeSpecifier @"IASKMailComposeSpecifier"
#define kIASKCustomViewSpecifier @"IASKCustomViewSpecifier"
#define kIASKAppSettingChanged @"kAppSettingChanged"
#define kIASKSectionHeaderIndex 0
#define kIASKSliderNoImagesPadding 11
#define kIASKSliderImagesPadding 43
#define kIASKSpacing 5
#define kIASKMinLabelWidth 97
#define kIASKMaxLabelWidth 240
#define kIASKMinValueWidth 35
#define kIASKPaddingLeft 9
#define kIASKPaddingRight 10
#define kIASKHorizontalPaddingGroupTitles 19
#define kIASKVerticalPaddingGroupTitles 15
#define kIASKLabelFontSize 17
#define kIASKgrayBlueColor [UIColor colorWithRed:0.318 green:0.4 blue:0.569 alpha:1.0]
#define kIASKMinimumFontSize 12.0f
#ifndef kCFCoreFoundationVersionNumber_iPhoneOS_4_0
#define kCFCoreFoundationVersionNumber_iPhoneOS_4_0 550.32
#endif
#ifndef kCFCoreFoundationVersionNumber_iPhoneOS_4_1
#define kCFCoreFoundationVersionNumber_iPhoneOS_4_1 550.38
#endif
#define IASK_IF_IOS4_OR_GREATER(...) \
if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iPhoneOS_4_0) \
{ \
__VA_ARGS__ \
}
@class IASKSpecifier;
/** settings reader transform iOS's settings plist files
to the IASKSpecifier model objects.
Besides that, it also hides the complexity of finding
the 'proper' Settings.bundle
*/
@interface IASKSettingsReader : NSObject
/** designated initializer
searches for a settings bundle that contains
a plist with the specified fileName that must
be contained in the given bundle
calls initWithFile where applicationBundle is
set to [NSBundle mainBundle]
*/
- (id) initWithSettingsFileNamed:(NSString*) fileName
applicationBundle:(NSBundle*) bundle;
- (id) initWithFile:(NSString*)file;
- (NSInteger)numberOfSections;
- (NSInteger)numberOfRowsForSection:(NSInteger)section;
- (IASKSpecifier*)specifierForIndexPath:(NSIndexPath*)indexPath;
- (NSIndexPath*)indexPathForKey:(NSString*)key;
- (IASKSpecifier*)specifierForKey:(NSString*)key;
- (NSString*)titleForSection:(NSInteger)section;
- (NSString*)keyForSection:(NSInteger)section;
- (NSString*)footerTextForSection:(NSInteger)section;
- (NSString*)titleForStringId:(NSString*)stringId;
- (NSString*)pathForImageNamed:(NSString*)image;
///the main application bundle. most often [NSBundle mainBundle]
@property (nonatomic, readonly) NSBundle *applicationBundle;
///the actual settings bundle
@property (nonatomic, readonly) NSBundle *settingsBundle;
///the actual settings plist, parsed into a dictionary
@property (nonatomic, readonly) NSDictionary *settingsDictionary;
@property (nonatomic, retain) NSString *localizationTable;
@property (nonatomic, retain) NSArray *dataSource;
@property (nonatomic, retain) NSSet *hiddenKeys;
#pragma mark - internal use. public only for testing
- (NSString *)file:(NSString *)file
withBundle:(NSString *)bundle
suffix:(NSString *)suffix
extension:(NSString *)extension;
- (NSString *)locateSettingsFile:(NSString *)file;
- (NSString *)platformSuffixForInterfaceIdiom:(UIUserInterfaceIdiom) interfaceIdiom;
@end

View file

@ -0,0 +1,286 @@
//
// IASKSettingsReader.m
// http://www.inappsettingskit.com
//
// Copyright (c) 2009:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import "IASKSettingsReader.h"
#import "IASKSpecifier.h"
#pragma mark -
@interface IASKSettingsReader () {
}
@end
@implementation IASKSettingsReader
- (id) initWithSettingsFileNamed:(NSString*) fileName
applicationBundle:(NSBundle*) bundle {
self = [super init];
if (self) {
_applicationBundle = [bundle retain];
NSString* plistFilePath = [self locateSettingsFile: fileName];
_settingsDictionary = [[NSDictionary dictionaryWithContentsOfFile:plistFilePath] retain];
//store the bundle which we'll need later for getting localizations
NSString* settingsBundlePath = [plistFilePath stringByDeletingLastPathComponent];
_settingsBundle = [[NSBundle bundleWithPath:settingsBundlePath] retain];
// Look for localization file
self.localizationTable = [_settingsDictionary objectForKey:@"StringsTable"];
if (!self.localizationTable)
{
// Look for localization file using filename
self.localizationTable = [[[[plistFilePath stringByDeletingPathExtension] // removes '.plist'
stringByDeletingPathExtension] // removes potential '.inApp'
lastPathComponent] // strip absolute path
stringByReplacingOccurrencesOfString:[self platformSuffixForInterfaceIdiom:UI_USER_INTERFACE_IDIOM()] withString:@""]; // removes potential '~device' (~ipad, ~iphone)
if([self.settingsBundle pathForResource:self.localizationTable ofType:@"strings"] == nil){
// Could not find the specified localization: use default
self.localizationTable = @"Root";
}
}
if (self.settingsDictionary) {
[self _reinterpretBundle:self.settingsDictionary];
}
}
return self;
}
- (id)initWithFile:(NSString*)file {
return [self initWithSettingsFileNamed:file applicationBundle:[NSBundle mainBundle]];
}
- (id)init {
return [self initWithFile:@"Root"];
}
- (void)dealloc {
[_localizationTable release], _localizationTable = nil;
[_settingsDictionary release], _settingsDictionary = nil;
[_dataSource release], _dataSource = nil;
[_settingsBundle release], _settingsBundle = nil;
[_hiddenKeys release], _hiddenKeys = nil;
[super dealloc];
}
- (void)setHiddenKeys:(NSSet *)anHiddenKeys {
if (_hiddenKeys != anHiddenKeys) {
id old = _hiddenKeys;
_hiddenKeys = [anHiddenKeys retain];
[old release];
if (self.settingsDictionary) {
[self _reinterpretBundle:self.settingsDictionary];
}
}
}
- (void)_reinterpretBundle:(NSDictionary*)settingsBundle {
NSArray *preferenceSpecifiers = [settingsBundle objectForKey:kIASKPreferenceSpecifiers];
NSInteger sectionCount = -1;
NSMutableArray *dataSource = [[[NSMutableArray alloc] init] autorelease];
for (NSDictionary *specifier in preferenceSpecifiers) {
if ([self.hiddenKeys containsObject:[specifier objectForKey:kIASKKey]]) {
continue;
}
if ([(NSString*)[specifier objectForKey:kIASKType] isEqualToString:kIASKPSGroupSpecifier]) {
NSMutableArray *newArray = [[NSMutableArray alloc] init];
[newArray addObject:specifier];
[dataSource addObject:newArray];
[newArray release];
sectionCount++;
}
else {
if (sectionCount == -1) {
NSMutableArray *newArray = [[NSMutableArray alloc] init];
[dataSource addObject:newArray];
[newArray release];
sectionCount++;
}
IASKSpecifier *newSpecifier = [[IASKSpecifier alloc] initWithSpecifier:specifier];
[(NSMutableArray*)[dataSource objectAtIndex:sectionCount] addObject:newSpecifier];
[newSpecifier release];
}
}
[self setDataSource:dataSource];
}
- (BOOL)_sectionHasHeading:(NSInteger)section {
return [[[[self dataSource] objectAtIndex:section] objectAtIndex:0] isKindOfClass:[NSDictionary class]];
}
- (NSInteger)numberOfSections {
return [[self dataSource] count];
}
- (NSInteger)numberOfRowsForSection:(NSInteger)section {
int headingCorrection = [self _sectionHasHeading:section] ? 1 : 0;
return [(NSArray*)[[self dataSource] objectAtIndex:section] count] - headingCorrection;
}
- (IASKSpecifier*)specifierForIndexPath:(NSIndexPath*)indexPath {
int headingCorrection = [self _sectionHasHeading:indexPath.section] ? 1 : 0;
IASKSpecifier *specifier = [[[self dataSource] objectAtIndex:indexPath.section] objectAtIndex:(indexPath.row+headingCorrection)];
specifier.settingsReader = self;
return specifier;
}
- (NSIndexPath*)indexPathForKey:(NSString *)key {
for (NSUInteger sectionIndex = 0; sectionIndex < self.dataSource.count; sectionIndex++) {
NSArray *section = [self.dataSource objectAtIndex:sectionIndex];
for (NSUInteger rowIndex = 0; rowIndex < section.count; rowIndex++) {
IASKSpecifier *specifier = (IASKSpecifier*)[section objectAtIndex:rowIndex];
if ([specifier isKindOfClass:[IASKSpecifier class]] && [specifier.key isEqualToString:key]) {
NSUInteger correctedRowIndex = rowIndex - [self _sectionHasHeading:sectionIndex];
return [NSIndexPath indexPathForRow:correctedRowIndex inSection:sectionIndex];
}
}
}
return nil;
}
- (IASKSpecifier*)specifierForKey:(NSString*)key {
for (NSArray *specifiers in _dataSource) {
for (id sp in specifiers) {
if ([sp isKindOfClass:[IASKSpecifier class]]) {
if ([[sp key] isEqualToString:key]) {
return sp;
}
}
}
}
return nil;
}
- (NSString*)titleForSection:(NSInteger)section {
if ([self _sectionHasHeading:section]) {
NSDictionary *dict = [[[self dataSource] objectAtIndex:section] objectAtIndex:kIASKSectionHeaderIndex];
return [self titleForStringId:[dict objectForKey:kIASKTitle]];
}
return nil;
}
- (NSString*)keyForSection:(NSInteger)section {
if ([self _sectionHasHeading:section]) {
return [[[[self dataSource] objectAtIndex:section] objectAtIndex:kIASKSectionHeaderIndex] objectForKey:kIASKKey];
}
return nil;
}
- (NSString*)footerTextForSection:(NSInteger)section {
if ([self _sectionHasHeading:section]) {
NSDictionary *dict = [[[self dataSource] objectAtIndex:section] objectAtIndex:kIASKSectionHeaderIndex];
return [self titleForStringId:[dict objectForKey:kIASKFooterText]];
}
return nil;
}
- (NSString*)titleForStringId:(NSString*)stringId {
return [self.settingsBundle localizedStringForKey:stringId value:stringId table:self.localizationTable];
}
- (NSString*)pathForImageNamed:(NSString*)image {
return [[self.settingsBundle bundlePath] stringByAppendingPathComponent:image];
}
- (NSString *)platformSuffixForInterfaceIdiom:(UIUserInterfaceIdiom) interfaceIdiom {
switch (interfaceIdiom) {
case UIUserInterfaceIdiomPad: return @"~ipad";
case UIUserInterfaceIdiomPhone: return @"~iphone";
}
}
- (NSString *)file:(NSString *)file
withBundle:(NSString *)bundle
suffix:(NSString *)suffix
extension:(NSString *)extension {
NSString *appBundlePath = [self.applicationBundle bundlePath];
bundle = [appBundlePath stringByAppendingPathComponent:bundle];
file = [file stringByAppendingFormat:@"%@%@", suffix, extension];
return [bundle stringByAppendingPathComponent:file];
}
- (NSString *)locateSettingsFile: (NSString *)file {
static NSString* const kIASKBundleFolder = @"Settings.bundle";
static NSString* const kIASKBundleFolderAlt = @"InAppSettings.bundle";
static NSString* const kIASKBundleLocaleFolderExtension = @".lproj";
// The file is searched in the following order:
//
// InAppSettings.bundle/FILE~DEVICE.inApp.plist
// InAppSettings.bundle/FILE.inApp.plist
// InAppSettings.bundle/FILE~DEVICE.plist
// InAppSettings.bundle/FILE.plist
// Settings.bundle/FILE~DEVICE.inApp.plist
// Settings.bundle/FILE.inApp.plist
// Settings.bundle/FILE~DEVICE.plist
// Settings.bundle/FILE.plist
//
// where DEVICE is either "iphone" or "ipad" depending on the current
// interface idiom.
//
// Settings.app uses the ~DEVICE suffixes since iOS 4.0. There are some
// differences from this implementation:
// - For an iPhone-only app running on iPad, Settings.app will not use the
// ~iphone suffix. There is no point in using these suffixes outside
// of universal apps anyway.
// - This implementation uses the device suffixes on iOS 3.x as well.
// - also check current locale (short only)
NSArray *settingsBundleNames = @[kIASKBundleFolderAlt, kIASKBundleFolder];
NSArray *extensions = @[@".inApp.plist", @".plist"];
NSArray *plattformSuffixes = @[[self platformSuffixForInterfaceIdiom:UI_USER_INTERFACE_IDIOM()],
@""];
NSArray *languageFolders = @[[[[NSLocale preferredLanguages] objectAtIndex:0] stringByAppendingString:kIASKBundleLocaleFolderExtension],
@""];
NSString *path = nil;
NSFileManager *fileManager = [NSFileManager defaultManager];
for (NSString *settingsBundleName in settingsBundleNames) {
for (NSString *extension in extensions) {
for (NSString *platformSuffix in plattformSuffixes) {
for (NSString *languageFolder in languageFolders) {
path = [self file:file
withBundle:[settingsBundleName stringByAppendingPathComponent:languageFolder]
suffix:platformSuffix
extension:extension];
if ([fileManager fileExistsAtPath:path]) {
goto exitFromNestedLoop;
}
}
}
}
}
exitFromNestedLoop:
return path;
}
@end

View file

@ -0,0 +1,59 @@
//
// IASKSettingsStore.h
// http://www.inappsettingskit.com
//
// Copyright (c) 2010:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// Marc-Etienne M.Léveillé, Edovia Inc., http://www.edovia.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import <Foundation/Foundation.h>
/** protocol that needs to be implemented from a settings store
*/
@protocol IASKSettingsStore <NSObject>
@required
- (void)setBool:(BOOL)value forKey:(NSString*)key;
- (void)setFloat:(float)value forKey:(NSString*)key;
- (void)setDouble:(double)value forKey:(NSString*)key;
- (void)setInteger:(int)value forKey:(NSString*)key;
- (void)setObject:(id)value forKey:(NSString*)key;
- (BOOL)boolForKey:(NSString*)key;
- (float)floatForKey:(NSString*)key;
- (double)doubleForKey:(NSString*)key;
- (int)integerForKey:(NSString*)key;
- (id)objectForKey:(NSString*)key;
- (BOOL)synchronize; // Write settings to a permanant storage. Returns YES on success, NO otherwise
@end
/** abstract default implementation of IASKSettingsStore protocol
helper to implement a store which maps all methods to setObject:forKey:
and objectForKey:. Those 2 methods need to be overwritten.
*/
@interface IASKAbstractSettingsStore : NSObject <IASKSettingsStore>
/** default implementation raises an exception
must be overridden by subclasses
*/
- (void)setObject:(id)value forKey:(NSString*)key;
/** default implementation raises an exception
must be overridden by subclasses
*/
- (id)objectForKey:(NSString*)key;
/** default implementation does nothing and returns NO
*/
- (BOOL)synchronize;
@end

View file

@ -0,0 +1,68 @@
//
// IASKSettingsStore.m
// http://www.inappsettingskit.com
//
// Copyright (c) 2010:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// Marc-Etienne M.Léveillé, Edovia Inc., http://www.edovia.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import "IASKSettingsStore.h"
@implementation IASKAbstractSettingsStore
- (void)setObject:(id)value forKey:(NSString*)key {
[NSException raise:@"Unimplemented"
format:@"setObject:forKey: must be implemented in subclasses of IASKAbstractSettingsStore"];
}
- (id)objectForKey:(NSString*)key {
[NSException raise:@"Unimplemented"
format:@"objectForKey: must be implemented in subclasses of IASKAbstractSettingsStore"];
return nil;
}
- (void)setBool:(BOOL)value forKey:(NSString*)key {
[self setObject:[NSNumber numberWithBool:value] forKey:key];
}
- (void)setFloat:(float)value forKey:(NSString*)key {
[self setObject:[NSNumber numberWithFloat:value] forKey:key];
}
- (void)setInteger:(int)value forKey:(NSString*)key {
[self setObject:[NSNumber numberWithInt:value] forKey:key];
}
- (void)setDouble:(double)value forKey:(NSString*)key {
[self setObject:[NSNumber numberWithDouble:value] forKey:key];
}
- (BOOL)boolForKey:(NSString*)key {
return [[self objectForKey:key] boolValue];
}
- (float)floatForKey:(NSString*)key {
return [[self objectForKey:key] floatValue];
}
- (int)integerForKey:(NSString*)key {
return [[self objectForKey:key] intValue];
}
- (double)doubleForKey:(NSString*)key {
return [[self objectForKey:key] doubleValue];
}
- (BOOL)synchronize {
return NO;
}
@end

View file

@ -0,0 +1,36 @@
//
// IASKSettingsStoreFile.h
// http://www.inappsettingskit.com
//
// Copyright (c) 2010:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// Marc-Etienne M.Léveillé, Edovia Inc., http://www.edovia.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import <Foundation/Foundation.h>
#import "IASKSettingsStore.h"
/** file-based implementation of IASKAbstractSettingsStore
uses an NSDictionary + its read/write to file support to store
settings in a file at the specified path
*/
@interface IASKSettingsStoreFile : IASKAbstractSettingsStore
/** designated initializer
@param path absolute file-path to store settings dictionary
*/
- (id)initWithPath:(NSString*)path;
@property (nonatomic, retain, readonly) NSString* filePath;
@end

View file

@ -0,0 +1,60 @@
//
// IASKSettingsStoreFile.m
// http://www.inappsettingskit.com
//
// Copyright (c) 2010:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// Marc-Etienne M.Léveillé, Edovia Inc., http://www.edovia.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import "IASKSettingsStoreFile.h"
@interface IASKSettingsStoreFile() {
NSMutableDictionary * _dict;
}
@property (nonatomic, retain, readwrite) NSString* filePath;
@end
@implementation IASKSettingsStoreFile
- (id)initWithPath:(NSString*)path {
if((self = [super init])) {
_filePath = [path retain];
_dict = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
if(_dict == nil) {
_dict = [[NSMutableDictionary alloc] init];
}
}
return self;
}
- (void)dealloc {
[_dict release], _dict = nil;
[_filePath release], _filePath = nil;
[super dealloc];
}
- (void)setObject:(id)value forKey:(NSString *)key {
[_dict setObject:value forKey:key];
}
- (id)objectForKey:(NSString *)key {
return [_dict objectForKey:key];
}
- (BOOL)synchronize {
return [_dict writeToFile:_filePath atomically:YES];
}
@end

View file

@ -0,0 +1,33 @@
//
// IASKSettingsStoreUserDefaults.h
// http://www.inappsettingskit.com
//
// Copyright (c) 2010:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// Marc-Etienne M.Léveillé, Edovia Inc., http://www.edovia.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import <Foundation/Foundation.h>
#import "IASKSettingsStore.h"
/** implementation of IASKSettingsStore that uses NSUserDefaults
*/
@interface IASKSettingsStoreUserDefaults : NSObject<IASKSettingsStore>
///designated initializer
- (id) initWithUserDefaults:(NSUserDefaults*) defaults;
///calls initWithUserDefaults: with [NSUserDefaults standardUserDefaults]
- (id) init;
@property (nonatomic, retain, readonly) NSUserDefaults* defaults;
@end

View file

@ -0,0 +1,89 @@
//
// IASKSettingsStoreUserDefaults.m
// http://www.inappsettingskit.com
//
// Copyright (c) 2010:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// Marc-Etienne M.Léveillé, Edovia Inc., http://www.edovia.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import "IASKSettingsStoreUserDefaults.h"
@interface IASKSettingsStoreUserDefaults ()
@property (nonatomic, retain, readwrite) NSUserDefaults* defaults;
@end
@implementation IASKSettingsStoreUserDefaults
- (void)dealloc {
[_defaults release];
[super dealloc];
}
- (id)initWithUserDefaults:(NSUserDefaults *)defaults {
self = [super init];
if( self ) {
_defaults = [defaults retain];
}
return self;
}
- (id)init {
return [self initWithUserDefaults:[NSUserDefaults standardUserDefaults]];
}
- (void)setBool:(BOOL)value forKey:(NSString*)key {
[self.defaults setBool:value forKey:key];
}
- (void)setFloat:(float)value forKey:(NSString*)key {
[self.defaults setFloat:value forKey:key];
}
- (void)setDouble:(double)value forKey:(NSString*)key {
[self.defaults setDouble:value forKey:key];
}
- (void)setInteger:(int)value forKey:(NSString*)key {
[self.defaults setInteger:value forKey:key];
}
- (void)setObject:(id)value forKey:(NSString*)key {
[self.defaults setObject:value forKey:key];
}
- (BOOL)boolForKey:(NSString*)key {
return [self.defaults boolForKey:key];
}
- (float)floatForKey:(NSString*)key {
return [self.defaults floatForKey:key];
}
- (double)doubleForKey:(NSString*)key {
return [self.defaults doubleForKey:key];
}
- (int)integerForKey:(NSString*)key {
return [self.defaults integerForKey:key];
}
- (id)objectForKey:(NSString*)key {
return [self.defaults objectForKey:key];
}
- (BOOL)synchronize {
return [self.defaults synchronize];
}
@end

View file

@ -0,0 +1,62 @@
//
// IASKSpecifier.h
// http://www.inappsettingskit.com
//
// Copyright (c) 2009:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@class IASKSettingsReader;
@interface IASKSpecifier : NSObject {
NSDictionary *_specifierDict;
NSDictionary *_multipleValuesDict;
IASKSettingsReader *_settingsReader;
}
@property (nonatomic, retain) NSDictionary *specifierDict;
@property (nonatomic, assign) IASKSettingsReader *settingsReader;
- (id)initWithSpecifier:(NSDictionary*)specifier;
- (NSString*)localizedObjectForKey:(NSString*)key;
- (NSString*)title;
- (NSString*)key;
- (NSString*)type;
- (NSString*)titleForCurrentValue:(id)currentValue;
- (NSInteger)multipleValuesCount;
- (NSArray*)multipleValues;
- (NSArray*)multipleTitles;
- (NSString*)file;
- (id)defaultValue;
- (id)defaultStringValue;
- (BOOL)defaultBoolValue;
- (id)trueValue;
- (id)falseValue;
- (float)minimumValue;
- (float)maximumValue;
- (NSString*)minimumValueImage;
- (NSString*)maximumValueImage;
- (BOOL)isSecure;
- (UIKeyboardType)keyboardType;
- (UITextAutocapitalizationType)autocapitalizationType;
- (UITextAutocorrectionType)autoCorrectionType;
- (NSString*)footerText;
- (Class)viewControllerClass;
- (SEL)viewControllerSelector;
-(Class)buttonClass;
-(SEL)buttonAction;
- (UIImage *)cellImage;
- (UIImage *)highlightedCellImage;
- (BOOL)adjustsFontSizeToFitWidth;
- (UITextAlignment)textAlignment;
@end

View file

@ -0,0 +1,280 @@
//
// IASKSpecifier.m
// http://www.inappsettingskit.com
//
// Copyright (c) 2009:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import "IASKSpecifier.h"
#import "IASKSettingsReader.h"
@interface IASKSpecifier ()
@property (nonatomic, retain) NSDictionary *multipleValuesDict;
- (void)_reinterpretValues:(NSDictionary*)specifierDict;
@end
@implementation IASKSpecifier
@synthesize specifierDict=_specifierDict;
@synthesize multipleValuesDict=_multipleValuesDict;
@synthesize settingsReader = _settingsReader;
- (id)initWithSpecifier:(NSDictionary*)specifier {
if ((self = [super init])) {
[self setSpecifierDict:specifier];
if ([[self type] isEqualToString:kIASKPSMultiValueSpecifier] ||
[[self type] isEqualToString:kIASKPSTitleValueSpecifier]) {
[self _reinterpretValues:[self specifierDict]];
}
}
return self;
}
- (void)dealloc {
[_specifierDict release], _specifierDict = nil;
[_multipleValuesDict release], _multipleValuesDict = nil;
_settingsReader = nil;
[super dealloc];
}
- (void)_reinterpretValues:(NSDictionary*)specifierDict {
NSArray *values = [_specifierDict objectForKey:kIASKValues];
NSArray *titles = [_specifierDict objectForKey:kIASKTitles];
NSMutableDictionary *multipleValuesDict = [[[NSMutableDictionary alloc] init] autorelease];
if (values) {
[multipleValuesDict setObject:values forKey:kIASKValues];
}
if (titles) {
[multipleValuesDict setObject:titles forKey:kIASKTitles];
}
[self setMultipleValuesDict:multipleValuesDict];
}
- (NSString*)localizedObjectForKey:(NSString*)key {
return [self.settingsReader titleForStringId:[_specifierDict objectForKey:key]];
}
- (NSString*)title {
return [self localizedObjectForKey:kIASKTitle];
}
- (NSString*)footerText {
return [self localizedObjectForKey:kIASKFooterText];
}
-(Class) viewControllerClass {
return NSClassFromString([_specifierDict objectForKey:kIASKViewControllerClass]);
}
-(SEL) viewControllerSelector {
return NSSelectorFromString([_specifierDict objectForKey:kIASKViewControllerSelector]);
}
-(Class)buttonClass {
return NSClassFromString([_specifierDict objectForKey:kIASKButtonClass]);
}
-(SEL)buttonAction {
return NSSelectorFromString([_specifierDict objectForKey:kIASKButtonAction]);
}
- (NSString*)key {
return [_specifierDict objectForKey:kIASKKey];
}
- (NSString*)type {
return [_specifierDict objectForKey:kIASKType];
}
- (NSString*)titleForCurrentValue:(id)currentValue {
NSArray *values = [self multipleValues];
NSArray *titles = [self multipleTitles];
if (values.count != titles.count) {
return nil;
}
NSInteger keyIndex = [values indexOfObject:currentValue];
if (keyIndex == NSNotFound) {
return nil;
}
@try {
return [self.settingsReader titleForStringId:[titles objectAtIndex:keyIndex]];
}
@catch (NSException * e) {}
return nil;
}
- (NSInteger)multipleValuesCount {
return [[_multipleValuesDict objectForKey:kIASKValues] count];
}
- (NSArray*)multipleValues {
return [_multipleValuesDict objectForKey:kIASKValues];
}
- (NSArray*)multipleTitles {
return [_multipleValuesDict objectForKey:kIASKTitles];
}
- (NSString*)file {
return [_specifierDict objectForKey:kIASKFile];
}
- (id)defaultValue {
return [_specifierDict objectForKey:kIASKDefaultValue];
}
- (id)defaultStringValue {
return [[_specifierDict objectForKey:kIASKDefaultValue] description];
}
- (BOOL)defaultBoolValue {
id defaultValue = [self defaultValue];
if ([defaultValue isEqual:[self trueValue]]) {
return YES;
}
if ([defaultValue isEqual:[self falseValue]]) {
return NO;
}
return [defaultValue boolValue];
}
- (id)trueValue {
return [_specifierDict objectForKey:kIASKTrueValue];
}
- (id)falseValue {
return [_specifierDict objectForKey:kIASKFalseValue];
}
- (float)minimumValue {
return [[_specifierDict objectForKey:kIASKMinimumValue] floatValue];
}
- (float)maximumValue {
return [[_specifierDict objectForKey:kIASKMaximumValue] floatValue];
}
- (NSString*)minimumValueImage {
return [_specifierDict objectForKey:kIASKMinimumValueImage];
}
- (NSString*)maximumValueImage {
return [_specifierDict objectForKey:kIASKMaximumValueImage];
}
- (BOOL)isSecure {
return [[_specifierDict objectForKey:kIASKIsSecure] boolValue];
}
- (UIKeyboardType)keyboardType {
if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardAlphabet]) {
return UIKeyboardTypeDefault;
}
else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardNumbersAndPunctuation]) {
return UIKeyboardTypeNumbersAndPunctuation;
}
else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardNumberPad]) {
return UIKeyboardTypeNumberPad;
}
else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardPhonePad]) {
return UIKeyboardTypePhonePad;
}
else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardNamePhonePad]) {
return UIKeyboardTypeNamePhonePad;
}
else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardASCIICapable]) {
return UIKeyboardTypeASCIICapable;
}
else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardDecimalPad]) {
if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iPhoneOS_4_1) {
return UIKeyboardTypeDecimalPad;
}
else {
return UIKeyboardTypeNumbersAndPunctuation;
}
}
else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:KIASKKeyboardURL]) {
return UIKeyboardTypeURL;
}
else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardEmailAddress]) {
return UIKeyboardTypeEmailAddress;
}
return UIKeyboardTypeDefault;
}
- (UITextAutocapitalizationType)autocapitalizationType {
if ([[_specifierDict objectForKey:kIASKAutocapitalizationType] isEqualToString:kIASKAutoCapNone]) {
return UITextAutocapitalizationTypeNone;
}
else if ([[_specifierDict objectForKey:kIASKAutocapitalizationType] isEqualToString:kIASKAutoCapSentences]) {
return UITextAutocapitalizationTypeSentences;
}
else if ([[_specifierDict objectForKey:kIASKAutocapitalizationType] isEqualToString:kIASKAutoCapWords]) {
return UITextAutocapitalizationTypeWords;
}
else if ([[_specifierDict objectForKey:kIASKAutocapitalizationType] isEqualToString:kIASKAutoCapAllCharacters]) {
return UITextAutocapitalizationTypeAllCharacters;
}
return UITextAutocapitalizationTypeNone;
}
- (UITextAutocorrectionType)autoCorrectionType {
if ([[_specifierDict objectForKey:kIASKAutoCorrectionType] isEqualToString:kIASKAutoCorrDefault]) {
return UITextAutocorrectionTypeDefault;
}
else if ([[_specifierDict objectForKey:kIASKAutoCorrectionType] isEqualToString:kIASKAutoCorrNo]) {
return UITextAutocorrectionTypeNo;
}
else if ([[_specifierDict objectForKey:kIASKAutoCorrectionType] isEqualToString:kIASKAutoCorrYes]) {
return UITextAutocorrectionTypeYes;
}
return UITextAutocorrectionTypeDefault;
}
- (UIImage *)cellImage
{
return [UIImage imageNamed:[_specifierDict objectForKey:kIASKCellImage]];
}
- (UIImage *)highlightedCellImage
{
return [UIImage imageNamed:[[_specifierDict objectForKey:kIASKCellImage ] stringByAppendingString:@"Highlighted"]];
}
- (BOOL)adjustsFontSizeToFitWidth {
NSNumber *boxedResult = [_specifierDict objectForKey:kIASKAdjustsFontSizeToFitWidth];
return !boxedResult || [boxedResult boolValue];
}
- (UITextAlignment)textAlignment
{
if ([[_specifierDict objectForKey:kIASKTextLabelAlignment] isEqualToString:kIASKTextLabelAlignmentLeft]) {
return NSTextAlignmentLeft;
} else if ([[_specifierDict objectForKey:kIASKTextLabelAlignment] isEqualToString:kIASKTextLabelAlignmentCenter]) {
return NSTextAlignmentCenter;
} else if ([[_specifierDict objectForKey:kIASKTextLabelAlignment] isEqualToString:kIASKTextLabelAlignmentRight]) {
return NSTextAlignmentRight;
}
if ([self.type isEqualToString:kIASKButtonSpecifier] && !self.cellImage) {
return NSTextAlignmentCenter;
} else if ([self.type isEqualToString:kIASKPSMultiValueSpecifier] || [self.type isEqualToString:kIASKPSTitleValueSpecifier]) {
return NSTextAlignmentRight;
}
return NSTextAlignmentLeft;
}
@end

View file

@ -0,0 +1,31 @@
//
// IASKPSSliderSpecifierViewCell.h
// http://www.inappsettingskit.com
//
// Copyright (c) 2009:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import <UIKit/UIKit.h>
@class IASKSlider;
@interface IASKPSSliderSpecifierViewCell : UITableViewCell {
IASKSlider *_slider;
UIImageView *_minImage;
UIImageView *_maxImage;
}
@property (nonatomic, assign) IASKSlider *slider;
@property (nonatomic, assign) UIImageView *minImage;
@property (nonatomic, assign) UIImageView *maxImage;
@end

View file

@ -0,0 +1,100 @@
//
// IASKPSSliderSpecifierViewCell.m
// http://www.inappsettingskit.com
//
// Copyright (c) 2009-2010:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import "IASKPSSliderSpecifierViewCell.h"
#import "IASKSlider.h"
#import "IASKSettingsReader.h"
@implementation IASKPSSliderSpecifierViewCell
@synthesize slider=_slider,
minImage=_minImage,
maxImage=_maxImage;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Setting only frame data that will not be overwritten by layoutSubviews
// Slider
_slider = [[[IASKSlider alloc] initWithFrame:CGRectMake(0, 0, 0, 23)] autorelease];
_slider.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin |
UIViewAutoresizingFlexibleWidth;
_slider.continuous = NO;
[self.contentView addSubview:_slider];
// MinImage
_minImage = [[[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 21, 21)] autorelease];
_minImage.autoresizingMask = UIViewAutoresizingFlexibleRightMargin |
UIViewAutoresizingFlexibleBottomMargin;
[self.contentView addSubview:_minImage];
// MaxImage
_maxImage = [[[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 21, 21)] autorelease];
_maxImage.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleBottomMargin;
[self.contentView addSubview:_maxImage];
self.selectionStyle = UITableViewCellSelectionStyleNone;
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
CGRect sliderBounds = _slider.bounds;
CGPoint sliderCenter = _slider.center;
const double superViewWidth = _slider.superview.frame.size.width;
sliderCenter.x = superViewWidth / 2;
sliderCenter.y = self.contentView.center.y;
sliderBounds.size.width = superViewWidth - kIASKSliderNoImagesPadding * 2;
_minImage.hidden = YES;
_maxImage.hidden = YES;
// Check if there are min and max images. If so, change the layout accordingly.
if (_minImage.image) {
// Min image
_minImage.hidden = NO;
sliderCenter.x += (kIASKSliderImagesPadding - kIASKSliderNoImagesPadding) / 2;
sliderBounds.size.width -= (kIASKSliderImagesPadding - kIASKSliderNoImagesPadding);
_minImage.center = CGPointMake(_minImage.frame.size.width / 2 + kIASKPaddingLeft,
self.contentView.center.y);
}
if (_maxImage.image) {
// Max image
_maxImage.hidden = NO;
sliderCenter.x -= (kIASKSliderImagesPadding - kIASKSliderNoImagesPadding) / 2;
sliderBounds.size.width -= (kIASKSliderImagesPadding - kIASKSliderNoImagesPadding);
_maxImage.center = CGPointMake(self.contentView.bounds.size.width - _maxImage.frame.size.width / 2 - kIASKPaddingRight,
self.contentView.center.y);
}
_slider.bounds = sliderBounds;
_slider.center = sliderCenter;
}
- (void)dealloc {
_minImage.image = nil;
_maxImage.image = nil;
[super dealloc];
}
- (void)prepareForReuse {
_minImage.image = nil;
_maxImage.image = nil;
}
@end

View file

@ -0,0 +1,27 @@
//
// IASKPSTextFieldSpecifierViewCell.h
// http://www.inappsettingskit.com
//
// Copyright (c) 2009:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import <UIKit/UIKit.h>
@class IASKTextField;
@interface IASKPSTextFieldSpecifierViewCell : UITableViewCell {
IASKTextField *_textField;
}
@property (nonatomic, assign) IASKTextField *textField;
@end

View file

@ -0,0 +1,77 @@
//
// IASKPSTextFieldSpecifierViewCell.m
// http://www.inappsettingskit.com
//
// Copyright (c) 2009-2010:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import "IASKPSTextFieldSpecifierViewCell.h"
#import "IASKTextField.h"
#import "IASKSettingsReader.h"
@implementation IASKPSTextFieldSpecifierViewCell
@synthesize textField=_textField;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.textLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin;
// TextField
_textField = [[[IASKTextField alloc] initWithFrame:CGRectMake(0, 0, 200, 21)] autorelease];
_textField.autoresizingMask = UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleBottomMargin |
UIViewAutoresizingFlexibleLeftMargin;
_textField.font = [UIFont systemFontOfSize:17.0f];
_textField.minimumFontSize = kIASKMinimumFontSize;
_textField.textColor = [UIColor colorWithRed:0.275 green:0.376 blue:0.522 alpha:1.000];
[self.contentView addSubview:_textField];
self.selectionStyle = UITableViewCellSelectionStyleNone;
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
// Label
CGFloat imageOffset = self.imageView.image ? self.imageView.bounds.size.width + kIASKPaddingLeft : 0;
CGSize labelSize = [self.textLabel sizeThatFits:CGSizeZero];
labelSize.width = MAX(labelSize.width, kIASKMinLabelWidth - imageOffset);
self.textLabel.frame = (CGRect){self.textLabel.frame.origin, {MIN(kIASKMaxLabelWidth, labelSize.width), self.textLabel.frame.size.height}} ;
// TextField
_textField.center = CGPointMake(_textField.center.x, self.contentView.center.y);
CGRect textFieldFrame = _textField.frame;
textFieldFrame.origin.x = self.textLabel.frame.origin.x + MAX(kIASKMinLabelWidth - imageOffset, self.textLabel.frame.size.width) + kIASKSpacing;
textFieldFrame.size.width = _textField.superview.frame.size.width - textFieldFrame.origin.x - kIASKPaddingRight;
if (!self.textLabel.text.length) {
textFieldFrame.origin.x = kIASKPaddingLeft + imageOffset;
textFieldFrame.size.width = self.contentView.bounds.size.width - 2* kIASKPaddingLeft - imageOffset;
} else if (_textField.textAlignment == NSTextAlignmentRight) {
textFieldFrame.origin.x = self.textLabel.frame.origin.x + labelSize.width + kIASKSpacing;
textFieldFrame.size.width = _textField.superview.frame.size.width - textFieldFrame.origin.x - kIASKPaddingRight;
}
_textField.frame = textFieldFrame;
}
- (void)dealloc {
[super dealloc];
}
@end

View file

@ -0,0 +1,22 @@
//
// IASKPSTitleValueSpecifierViewCell.h
// http://www.inappsettingskit.com
//
// Copyright (c) 2010:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import <UIKit/UIKit.h>
@interface IASKPSTitleValueSpecifierViewCell : UITableViewCell
@end

View file

@ -0,0 +1,53 @@
//
// IASKPSTitleValueSpecifierViewCell.m
// http://www.inappsettingskit.com
//
// Copyright (c) 2010:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import "IASKPSTitleValueSpecifierViewCell.h"
#import "IASKSettingsReader.h"
@implementation IASKPSTitleValueSpecifierViewCell
- (void)layoutSubviews {
[super layoutSubviews];
CGSize viewSize = [self.textLabel superview].frame.size;
// if there's an image, make room for it
CGFloat imageOffset = floor(self.imageView.image ? self.imageView.bounds.size.width + self.imageView.frame.origin.x : 0);
// set the left title label frame
CGFloat labelWidth = [self.textLabel sizeThatFits:CGSizeZero].width;
CGFloat minValueWidth = (self.detailTextLabel.text.length) ? kIASKMinValueWidth + kIASKSpacing : 0;
labelWidth = MIN(labelWidth, viewSize.width - minValueWidth - kIASKPaddingLeft -kIASKPaddingRight - imageOffset);
CGRect labelFrame = CGRectMake(kIASKPaddingLeft + imageOffset, 0, labelWidth, viewSize.height -2);
if (!self.detailTextLabel.text.length) {
labelFrame = CGRectMake(kIASKPaddingLeft + imageOffset, 0, viewSize.width - kIASKPaddingLeft - kIASKPaddingRight - imageOffset, viewSize.height -2);
}
self.textLabel.frame = labelFrame;
// set the right value label frame
if (!self.textLabel.text.length) {
viewSize = [self.detailTextLabel superview].frame.size;
self.detailTextLabel.frame = CGRectMake(kIASKPaddingLeft + imageOffset, 0, viewSize.width - kIASKPaddingLeft - kIASKPaddingRight - imageOffset, viewSize.height -2);
} else if (self.detailTextLabel.textAlignment == NSTextAlignmentLeft) {
CGRect valueFrame = self.detailTextLabel.frame;
valueFrame.origin.x = labelFrame.origin.x + MAX(kIASKMinLabelWidth - imageOffset, labelWidth) + kIASKSpacing;
valueFrame.size.width = self.detailTextLabel.superview.frame.size.width - valueFrame.origin.x - kIASKPaddingRight;
self.detailTextLabel.frame = valueFrame;
}
}
@end

View file

@ -0,0 +1,26 @@
//
// IASKSlider.h
// http://www.inappsettingskit.com
//
// Copyright (c) 2009:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import <UIKit/UIKit.h>
@interface IASKSlider : UISlider {
NSString *_key;
}
@property (nonatomic, retain) NSString *key;
@end

View file

@ -0,0 +1,30 @@
//
// IASKSlider.m
// http://www.inappsettingskit.com
//
// Copyright (c) 2009:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import "IASKSlider.h"
@implementation IASKSlider
@synthesize key=_key;
- (void)dealloc {
[_key release], _key = nil;
[super dealloc];
}
@end

View file

@ -0,0 +1,26 @@
//
// IASKSwitch.h
// http://www.inappsettingskit.com
//
// Copyright (c) 2009:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import <UIKit/UIKit.h>
@interface IASKSwitch : UISwitch {
NSString *_key;
}
@property (nonatomic, retain) NSString *key;
@end

View file

@ -0,0 +1,31 @@
//
// IASKSwitch.m
// http://www.inappsettingskit.com
//
// Copyright (c) 2009:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import "IASKSwitch.h"
@implementation IASKSwitch
@synthesize key=_key;
- (void)dealloc {
[_key release], _key = nil;
[super dealloc];
}
@end

View file

@ -0,0 +1,26 @@
//
// IASKTextField.h
// http://www.inappsettingskit.com
//
// Copyright (c) 2009:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import <UIKit/UIKit.h>
@interface IASKTextField : UITextField {
NSString *_key;
}
@property (nonatomic, retain) NSString *key;
@end

View file

@ -0,0 +1,30 @@
//
// IASKTextField.m
// http://www.inappsettingskit.com
//
// Copyright (c) 2009:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import "IASKTextField.h"
@implementation IASKTextField
@synthesize key=_key;
- (void)dealloc {
[_key release], _key = nil;
[super dealloc];
}
@end

View file

@ -0,0 +1,103 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>Title</key>
<string>Story list</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Story order</string>
<key>Titles</key>
<array>
<string>Newest first</string>
<string>Oldest first</string>
</array>
<key>DefaultValue</key>
<string>newest</string>
<key>Values</key>
<array>
<string>newest</string>
<string>oldest</string>
</array>
<key>Key</key>
<string>default_order</string>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Show stories</string>
<key>Titles</key>
<array>
<string>All stories</string>
<string>Unread only</string>
</array>
<key>DefaultValue</key>
<string>all</string>
<key>Values</key>
<array>
<string>all</string>
<string>unread</string>
</array>
<key>Key</key>
<string>default_read_filter</string>
</dict>
<dict>
<key>Title</key>
<string>Offline stories</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>Download stories</string>
<key>Key</key>
<string>offline_allowed</string>
<key>DefaultValue</key>
<true/>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>Download images</string>
<key>Key</key>
<string>offline_image_download</string>
<key>DefaultValue</key>
<true/>
</dict>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>Download using</string>
<key>Titles</key>
<array>
<string>Wifi + Cellular</string>
<string>Wifi only</string>
</array>
<key>DefaultValue</key>
<string>cellular</string>
<key>Values</key>
<array>
<string>cellular</string>
<string>wifi</string>
</array>
<key>Key</key>
<string>offline_download_connection</string>
</dict>
</array>
<key>StringsTable</key>
<string>Root</string>
</dict>
</plist>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 465 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 B