├── .gitattributes ├── IndexSet-Backed-Table ├── en.lproj │ ├── InfoPlist.strings │ ├── MainStoryboard_iPhone.storyboard │ └── MainStoryboard_iPad.storyboard ├── Default.png ├── Default@2x.png ├── Default-568h@2x.png ├── SDAppDelegate.h ├── SDCalendarTableViewController.h ├── main.m ├── IndexSet-Backed-Table-Prefix.pch ├── SDDetailViewController.h ├── IndexSet-Backed-Table-Info.plist ├── SDDetailViewController.m ├── SDAppDelegate.m └── SDCalendarTableViewController.m ├── IndexSet-Backed-Table.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── Sean.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── WorkspaceSettings.xcsettings ├── xcuserdata │ └── Sean.xcuserdatad │ │ ├── xcschemes │ │ ├── xcschememanagement.plist │ │ └── IndexSet-Backed-Table.xcscheme │ │ └── xcdebugger │ │ ├── Breakpoints.xcbkptlist │ │ └── Breakpoints_v2.xcbkptlist └── project.pbxproj ├── .gitignore └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj binary merge=union -------------------------------------------------------------------------------- /IndexSet-Backed-Table/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /IndexSet-Backed-Table/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steam/IndexSet-Backed-Table/master/IndexSet-Backed-Table/Default.png -------------------------------------------------------------------------------- /IndexSet-Backed-Table/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steam/IndexSet-Backed-Table/master/IndexSet-Backed-Table/Default@2x.png -------------------------------------------------------------------------------- /IndexSet-Backed-Table/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steam/IndexSet-Backed-Table/master/IndexSet-Backed-Table/Default-568h@2x.png -------------------------------------------------------------------------------- /IndexSet-Backed-Table.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /IndexSet-Backed-Table.xcodeproj/project.xcworkspace/xcuserdata/Sean.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steam/IndexSet-Backed-Table/master/IndexSet-Backed-Table.xcodeproj/project.xcworkspace/xcuserdata/Sean.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /IndexSet-Backed-Table/SDAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDAppDelegate.h 3 | // IndexSet-Backed-Table 4 | // 5 | // Created by Sean Dougherty on 7/8/13. 6 | 7 | #import 8 | 9 | @interface SDAppDelegate : UIResponder 10 | 11 | @property (strong, nonatomic) UIWindow *window; 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /IndexSet-Backed-Table/SDCalendarTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDCalendarTableViewController.h 3 | // IndexSet-Backed-Table 4 | // 5 | // Created by Sean Dougherty on 7/8/13. 6 | 7 | #import 8 | 9 | @class SDDetailViewController; 10 | 11 | @interface SDCalendarTableViewController : UITableViewController 12 | 13 | @property (strong, nonatomic) SDDetailViewController *detailViewController; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /IndexSet-Backed-Table/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // IndexSet-Backed-Table 4 | // 5 | // Created by Sean on 7/8/13. 6 | // Copyright (c) 2013 Sean Dougherty. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "SDAppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([SDAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /IndexSet-Backed-Table/IndexSet-Backed-Table-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'IndexSet-Backed-Table' target in the 'IndexSet-Backed-Table' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_5_0 8 | #warning "This project uses features only available in iOS SDK 5.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /IndexSet-Backed-Table.xcodeproj/project.xcworkspace/xcuserdata/Sean.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 6 | 7 | SnapshotAutomaticallyBeforeSignificantChanges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X Finder 2 | .DS_Store 3 | 4 | # Xcode per-user config 5 | *.mode1 6 | *.mode1v3 7 | *.mode2v3 8 | *.perspective 9 | *.perspectivev3 10 | *.pbxuser 11 | xcuserdata 12 | 13 | # Build products 14 | build/ 15 | *.o 16 | *.LinkFileList 17 | *.hmap 18 | Frank/frankified_build/ 19 | test-reports/* 20 | *.ipa 21 | *.dSYM.zip 22 | 23 | # Automatic backup files 24 | *~.nib/ 25 | *.swp 26 | *~ 27 | *.dat 28 | *.dep 29 | 30 | # pods 31 | Pods/* 32 | 33 | # screenshots 34 | screenshots 35 | -------------------------------------------------------------------------------- /IndexSet-Backed-Table/SDDetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDDetailViewController.h 3 | // IndexSet-Backed-Table 4 | // 5 | // Created by Sean Dougherty on 7/8/13. 6 | 7 | #import 8 | 9 | @interface SDDetailViewController : UIViewController 10 | 11 | @property (nonatomic, strong) NSDate *date; 12 | @property (nonatomic, weak) IBOutlet UILabel *dateLabel; 13 | 14 | // weakly held because the Calendar Table View holds onto it 15 | @property (nonatomic, weak) NSDateFormatter *dateFormatter; 16 | 17 | 18 | - (void)configureView; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /IndexSet-Backed-Table.xcodeproj/xcuserdata/Sean.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | IndexSet-Backed-Table.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 14373456178BA05700F0910D 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /IndexSet-Backed-Table.xcodeproj/xcuserdata/Sean.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /IndexSet-Backed-Table.xcodeproj/xcuserdata/Sean.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | IndexSet-Backed-Table 2 | ===================== 3 | 4 | Example of a NSIndexSet backed UITableView for large sets of data. Super fast. 5 | 6 | Using an NSIndexSet, or a collection of NSIndexSets can be very fast. When your backing datasource for UITable is complex and quite large it often makes sense to ditch the first option of using an array to represent the table's model. 7 | 8 | While working on complex calendaring component for a client, Ryan Boyajian and I decided to take a different approach. Our problem was that we needed to display an unpredictable number of rows representing ranges of time over a large duration. Working with NSDate, NSDateFormatter and NSCalendar objects can be expensive. We needed to find a solution that minimized the number of date objects and calculations that were performed. We decided to go with NSIndexSets and the results surprised us. We saw drastically improved performance by drawing rows with indexes and delaying the expensive date calculations until they were needed. 9 | 10 | This project is not meant to be a plug and play component for use in your projects but rather an example that demonstrates the concepts behind using NSIndexSet(s) as your primary UITableView datasource. Checkout the blog post ##### for a more detailed discussion of the approach. 11 | 12 | First, a few disclaimers. 13 | 14 | 1. This is not production ready code. The goal of this example app is to demonstrate the speed of using NSIndexSets to represent the backing model of a UITableView. You should still follow best practices when making a real production app. 15 | 2. There are no unit tests, you should have unit tests. This example has no unit tests in order to stay focused on the example. 16 | 3. The UITableView controller subclass SDCalendarTableViewController is the datasource and delegate for the table. A production app should not be written this way. You should use a separate object as your datasource. Your code will be cleaner and easier to test. 17 | -------------------------------------------------------------------------------- /IndexSet-Backed-Table/IndexSet-Backed-Table-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.seancdougherty.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIMainStoryboardFile 28 | MainStoryboard_iPhone 29 | UIMainStoryboardFile~ipad 30 | MainStoryboard_iPad 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UIStatusBarTintParameters 36 | 37 | UINavigationBar 38 | 39 | Style 40 | UIBarStyleDefault 41 | Translucent 42 | 43 | 44 | 45 | UISupportedInterfaceOrientations 46 | 47 | UIInterfaceOrientationPortrait 48 | UIInterfaceOrientationLandscapeLeft 49 | UIInterfaceOrientationLandscapeRight 50 | 51 | UISupportedInterfaceOrientations~ipad 52 | 53 | UIInterfaceOrientationPortrait 54 | UIInterfaceOrientationPortraitUpsideDown 55 | UIInterfaceOrientationLandscapeLeft 56 | UIInterfaceOrientationLandscapeRight 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /IndexSet-Backed-Table/SDDetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDDetailViewController.m 3 | // IndexSet-Backed-Table 4 | // 5 | // Created by Sean Dougherty on 7/8/13. 6 | 7 | #import "SDDetailViewController.h" 8 | 9 | @interface SDDetailViewController () 10 | @property (strong, nonatomic) UIPopoverController *masterPopoverController; 11 | @end 12 | 13 | @implementation SDDetailViewController 14 | 15 | #pragma mark - View Lifecycle 16 | 17 | - (void)viewDidLoad 18 | { 19 | [super viewDidLoad]; 20 | [self configureView]; 21 | } 22 | 23 | 24 | #pragma mark - Split view 25 | 26 | - (void)splitViewController:(UISplitViewController *)splitController 27 | willHideViewController:(UIViewController *)viewController 28 | withBarButtonItem:(UIBarButtonItem *)barButtonItem 29 | forPopoverController:(UIPopoverController *)popoverController 30 | { 31 | barButtonItem.title = NSLocalizedString(@"Days", @"Days"); 32 | [self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES]; 33 | self.masterPopoverController = popoverController; 34 | } 35 | 36 | - (void)splitViewController:(UISplitViewController *)splitController 37 | willShowViewController:(UIViewController *)viewController 38 | invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem 39 | { 40 | [self.navigationItem setLeftBarButtonItem:nil animated:YES]; 41 | self.masterPopoverController = nil; 42 | } 43 | 44 | #pragma mark - Public Mehtods 45 | 46 | - (void)configureView 47 | { 48 | if (self.date && self.dateFormatter) 49 | { 50 | self.dateFormatter.dateFormat = @"dd"; 51 | self.dateLabel.text = [self.dateFormatter stringFromDate:self.date]; 52 | self.dateFormatter.dateFormat = @"EEEE MMMM d, y"; 53 | self.title = [self.dateFormatter stringFromDate:self.date]; 54 | } 55 | } 56 | 57 | #pragma mark - Getters / Setters 58 | 59 | - (void)setDate:(NSDate *)date 60 | { 61 | if (_date != date) 62 | { 63 | _date = date; 64 | } 65 | 66 | if (self.masterPopoverController != nil) 67 | { 68 | [self.masterPopoverController dismissPopoverAnimated:YES]; 69 | } 70 | } 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /IndexSet-Backed-Table/SDAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDAppDelegate.m 3 | // IndexSet-Backed-Table 4 | // 5 | // Created by Sean Dougherty on 7/8/13. 6 | 7 | #import "SDAppDelegate.h" 8 | 9 | @implementation SDAppDelegate 10 | 11 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 12 | { 13 | // Override point for customization after application launch. 14 | if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { 15 | UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController; 16 | UINavigationController *navigationController = [splitViewController.viewControllers lastObject]; 17 | splitViewController.delegate = (id)navigationController.topViewController; 18 | } 19 | return YES; 20 | } 21 | 22 | - (void)applicationWillResignActive:(UIApplication *)application 23 | { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application 29 | { 30 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 31 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 32 | } 33 | 34 | - (void)applicationWillEnterForeground:(UIApplication *)application 35 | { 36 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 37 | } 38 | 39 | - (void)applicationDidBecomeActive:(UIApplication *)application 40 | { 41 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 42 | } 43 | 44 | - (void)applicationWillTerminate:(UIApplication *)application 45 | { 46 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /IndexSet-Backed-Table.xcodeproj/xcuserdata/Sean.xcuserdatad/xcschemes/IndexSet-Backed-Table.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /IndexSet-Backed-Table/SDCalendarTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDCalendarTableViewController.m 3 | // IndexSet-Backed-Table 4 | // 5 | // Created by Sean Dougherty on 7/8/13. 6 | 7 | #import "SDCalendarTableViewController.h" 8 | #import "SDDetailViewController.h" 9 | 10 | #define kNumberOfMonths 360 11 | #define kDayDateFormat @"EEE MMM d" 12 | #define kMonthDateFormat @"MMMM y" 13 | 14 | @interface SDCalendarTableViewController () 15 | @property(nonatomic, strong) NSIndexSet *days; 16 | @property(nonatomic, strong) NSDate *beginningOfThisMonth; 17 | @property(nonatomic, strong) NSDateFormatter *formatter; 18 | @property(nonatomic, strong) NSDateFormatter *detailFormatter; 19 | @property(nonatomic, strong) NSDateComponents *components; 20 | @property(nonatomic, strong) NSDateComponents *components2; 21 | @end 22 | 23 | @implementation SDCalendarTableViewController 24 | 25 | - (void)awakeFromNib 26 | { 27 | if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) 28 | { 29 | self.clearsSelectionOnViewWillAppear = NO; 30 | self.contentSizeForViewInPopover = CGSizeMake(320.0, 600.0); 31 | } 32 | [super awakeFromNib]; 33 | } 34 | 35 | - (void)viewDidLoad 36 | { 37 | [super viewDidLoad]; 38 | 39 | self.title = NSLocalizedString(@"30 Years of Days", @"30 Years of Days"); 40 | 41 | // date formatter i.e. "Mon Jul 08, 2013" 42 | self.formatter = [[NSDateFormatter alloc] init]; 43 | self.formatter.timeZone = [NSTimeZone localTimeZone]; 44 | self.formatter.dateFormat = @"EEE MMM dd, y"; 45 | 46 | // use a single date formatter for details to save on overhead, date formatters are expensive 47 | self.detailFormatter = [[NSDateFormatter alloc] init]; 48 | self.detailFormatter.timeZone = [NSTimeZone localTimeZone]; 49 | 50 | // date components for day incrementing 51 | self.components = [[NSCalendar currentCalendar] components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:[NSDate date]]; 52 | self.components.day = 1; 53 | 54 | // beginningOfThisMonth, the only date created at launch (dates are created as needed) 55 | self.beginningOfThisMonth = [[NSCalendar currentCalendar] dateFromComponents:self.components]; 56 | 57 | // reset the date components 58 | self.components = [[NSDateComponents alloc] init]; 59 | 60 | self.detailViewController = (SDDetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController]; 61 | } 62 | 63 | 64 | #pragma mark - Table View 65 | 66 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 67 | { 68 | return kNumberOfMonths; 69 | } 70 | 71 | - (NSInteger)tableView:(UITableView *)tableView 72 | numberOfRowsInSection:(NSInteger)section 73 | { 74 | return [self numberOfDaysInSection:section]; 75 | } 76 | 77 | - (NSString *)tableView:(UITableView *)tableView 78 | titleForHeaderInSection:(NSInteger)section 79 | { 80 | self.formatter.dateFormat = kMonthDateFormat; 81 | return [self.formatter stringFromDate:[self dateForIndexPath:[NSIndexPath indexPathForItem:0 inSection:section]]]; 82 | } 83 | 84 | - (UITableViewCell *)tableView:(UITableView *)tableView 85 | cellForRowAtIndexPath:(NSIndexPath *)indexPath 86 | { 87 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; 88 | self.formatter.dateFormat = kDayDateFormat; 89 | cell.textLabel.text = [self.formatter stringFromDate:[self dateForIndexPath:indexPath]]; 90 | return cell; 91 | } 92 | 93 | - (void)tableView:(UITableView *)tableView 94 | didSelectRowAtIndexPath:(NSIndexPath *)indexPath 95 | { 96 | if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) 97 | { 98 | self.detailViewController.date = [self dateForIndexPath:indexPath]; 99 | self.detailViewController.dateFormatter = self.detailFormatter; 100 | [self.detailViewController configureView]; 101 | } 102 | } 103 | 104 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 105 | { 106 | if ([[segue identifier] isEqualToString:@"showDetail"]) 107 | { 108 | NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; 109 | [[segue destinationViewController] setDate:[self dateForIndexPath:indexPath]]; 110 | [[segue destinationViewController] setDateFormatter:self.detailFormatter]; 111 | [[segue destinationViewController] configureView]; 112 | } 113 | } 114 | 115 | 116 | #pragma mark - Private Methods 117 | 118 | - (NSDate*)dateForIndexPath:(NSIndexPath*)indexPath 119 | { 120 | self.components.month = indexPath.section; 121 | self.components.day = indexPath.row; 122 | return [[NSCalendar currentCalendar] dateByAddingComponents:self.components toDate:self.beginningOfThisMonth options:0]; 123 | } 124 | 125 | - (NSUInteger)numberOfDaysInSection:(NSUInteger)section 126 | { 127 | NSDate *date = [self dateForIndexPath:[NSIndexPath indexPathForItem:0 inSection:section]]; 128 | NSRange range = [[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit inUnit:NSMonthCalendarUnit forDate:date]; 129 | return range.length; 130 | } 131 | 132 | #pragma mark - Getters / Setters 133 | 134 | - (NSIndexSet*)days 135 | { 136 | if (_days == nil) 137 | { 138 | NSMutableIndexSet *days = [NSMutableIndexSet indexSet]; 139 | 140 | // 30 years of days 141 | NSUInteger indexCounter = 0; 142 | for (NSUInteger i = 0; i < kNumberOfMonths; i++) 143 | { 144 | NSUInteger daysInMonth = [self numberOfDaysInSection:i]; 145 | [days addIndexesInRange:NSMakeRange(indexCounter, daysInMonth)]; 146 | indexCounter += daysInMonth; 147 | } 148 | 149 | _days = [days copy]; 150 | } 151 | 152 | return _days; 153 | } 154 | 155 | 156 | @end 157 | -------------------------------------------------------------------------------- /IndexSet-Backed-Table/en.lproj/MainStoryboard_iPhone.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /IndexSet-Backed-Table/en.lproj/MainStoryboard_iPad.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /IndexSet-Backed-Table.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1437345B178BA05700F0910D /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1437345A178BA05700F0910D /* UIKit.framework */; }; 11 | 1437345D178BA05700F0910D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1437345C178BA05700F0910D /* Foundation.framework */; }; 12 | 1437345F178BA05700F0910D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1437345E178BA05700F0910D /* CoreGraphics.framework */; }; 13 | 14373465178BA05700F0910D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 14373463178BA05700F0910D /* InfoPlist.strings */; }; 14 | 14373467178BA05700F0910D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 14373466178BA05700F0910D /* main.m */; }; 15 | 1437346B178BA05700F0910D /* SDAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1437346A178BA05700F0910D /* SDAppDelegate.m */; }; 16 | 1437346D178BA05700F0910D /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 1437346C178BA05700F0910D /* Default.png */; }; 17 | 1437346F178BA05700F0910D /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1437346E178BA05700F0910D /* Default@2x.png */; }; 18 | 14373471178BA05700F0910D /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 14373470178BA05700F0910D /* Default-568h@2x.png */; }; 19 | 14373474178BA05700F0910D /* MainStoryboard_iPhone.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 14373472178BA05700F0910D /* MainStoryboard_iPhone.storyboard */; }; 20 | 14373477178BA05700F0910D /* MainStoryboard_iPad.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 14373475178BA05700F0910D /* MainStoryboard_iPad.storyboard */; }; 21 | 1437347A178BA05700F0910D /* SDCalendarTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 14373479178BA05700F0910D /* SDCalendarTableViewController.m */; }; 22 | 1437347D178BA05700F0910D /* SDDetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1437347C178BA05700F0910D /* SDDetailViewController.m */; }; 23 | /* End PBXBuildFile section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | 14373457178BA05700F0910D /* IndexSet-Backed-Table.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "IndexSet-Backed-Table.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | 1437345A178BA05700F0910D /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 28 | 1437345C178BA05700F0910D /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 29 | 1437345E178BA05700F0910D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 30 | 14373462178BA05700F0910D /* IndexSet-Backed-Table-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "IndexSet-Backed-Table-Info.plist"; sourceTree = ""; }; 31 | 14373464178BA05700F0910D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 32 | 14373466178BA05700F0910D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 33 | 14373468178BA05700F0910D /* IndexSet-Backed-Table-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "IndexSet-Backed-Table-Prefix.pch"; sourceTree = ""; }; 34 | 14373469178BA05700F0910D /* SDAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDAppDelegate.h; sourceTree = ""; }; 35 | 1437346A178BA05700F0910D /* SDAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDAppDelegate.m; sourceTree = ""; }; 36 | 1437346C178BA05700F0910D /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; 37 | 1437346E178BA05700F0910D /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; 38 | 14373470178BA05700F0910D /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 39 | 14373473178BA05700F0910D /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/MainStoryboard_iPhone.storyboard; sourceTree = ""; }; 40 | 14373476178BA05700F0910D /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/MainStoryboard_iPad.storyboard; sourceTree = ""; }; 41 | 14373478178BA05700F0910D /* SDCalendarTableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDCalendarTableViewController.h; sourceTree = ""; }; 42 | 14373479178BA05700F0910D /* SDCalendarTableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDCalendarTableViewController.m; sourceTree = ""; }; 43 | 1437347B178BA05700F0910D /* SDDetailViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDDetailViewController.h; sourceTree = ""; }; 44 | 1437347C178BA05700F0910D /* SDDetailViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDDetailViewController.m; sourceTree = ""; }; 45 | /* End PBXFileReference section */ 46 | 47 | /* Begin PBXFrameworksBuildPhase section */ 48 | 14373454178BA05700F0910D /* Frameworks */ = { 49 | isa = PBXFrameworksBuildPhase; 50 | buildActionMask = 2147483647; 51 | files = ( 52 | 1437345B178BA05700F0910D /* UIKit.framework in Frameworks */, 53 | 1437345D178BA05700F0910D /* Foundation.framework in Frameworks */, 54 | 1437345F178BA05700F0910D /* CoreGraphics.framework in Frameworks */, 55 | ); 56 | runOnlyForDeploymentPostprocessing = 0; 57 | }; 58 | /* End PBXFrameworksBuildPhase section */ 59 | 60 | /* Begin PBXGroup section */ 61 | 1437344E178BA05700F0910D = { 62 | isa = PBXGroup; 63 | children = ( 64 | 14373460178BA05700F0910D /* IndexSet-Backed-Table */, 65 | 14373459178BA05700F0910D /* Frameworks */, 66 | 14373458178BA05700F0910D /* Products */, 67 | ); 68 | sourceTree = ""; 69 | }; 70 | 14373458178BA05700F0910D /* Products */ = { 71 | isa = PBXGroup; 72 | children = ( 73 | 14373457178BA05700F0910D /* IndexSet-Backed-Table.app */, 74 | ); 75 | name = Products; 76 | sourceTree = ""; 77 | }; 78 | 14373459178BA05700F0910D /* Frameworks */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 1437345A178BA05700F0910D /* UIKit.framework */, 82 | 1437345C178BA05700F0910D /* Foundation.framework */, 83 | 1437345E178BA05700F0910D /* CoreGraphics.framework */, 84 | ); 85 | name = Frameworks; 86 | sourceTree = ""; 87 | }; 88 | 14373460178BA05700F0910D /* IndexSet-Backed-Table */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | 14373469178BA05700F0910D /* SDAppDelegate.h */, 92 | 1437346A178BA05700F0910D /* SDAppDelegate.m */, 93 | 14373472178BA05700F0910D /* MainStoryboard_iPhone.storyboard */, 94 | 14373475178BA05700F0910D /* MainStoryboard_iPad.storyboard */, 95 | 14373478178BA05700F0910D /* SDCalendarTableViewController.h */, 96 | 14373479178BA05700F0910D /* SDCalendarTableViewController.m */, 97 | 1437347B178BA05700F0910D /* SDDetailViewController.h */, 98 | 1437347C178BA05700F0910D /* SDDetailViewController.m */, 99 | 14373461178BA05700F0910D /* Supporting Files */, 100 | ); 101 | path = "IndexSet-Backed-Table"; 102 | sourceTree = ""; 103 | }; 104 | 14373461178BA05700F0910D /* Supporting Files */ = { 105 | isa = PBXGroup; 106 | children = ( 107 | 14373462178BA05700F0910D /* IndexSet-Backed-Table-Info.plist */, 108 | 14373463178BA05700F0910D /* InfoPlist.strings */, 109 | 14373466178BA05700F0910D /* main.m */, 110 | 14373468178BA05700F0910D /* IndexSet-Backed-Table-Prefix.pch */, 111 | 1437346C178BA05700F0910D /* Default.png */, 112 | 1437346E178BA05700F0910D /* Default@2x.png */, 113 | 14373470178BA05700F0910D /* Default-568h@2x.png */, 114 | ); 115 | name = "Supporting Files"; 116 | sourceTree = ""; 117 | }; 118 | /* End PBXGroup section */ 119 | 120 | /* Begin PBXNativeTarget section */ 121 | 14373456178BA05700F0910D /* IndexSet-Backed-Table */ = { 122 | isa = PBXNativeTarget; 123 | buildConfigurationList = 14373480178BA05700F0910D /* Build configuration list for PBXNativeTarget "IndexSet-Backed-Table" */; 124 | buildPhases = ( 125 | 14373453178BA05700F0910D /* Sources */, 126 | 14373454178BA05700F0910D /* Frameworks */, 127 | 14373455178BA05700F0910D /* Resources */, 128 | ); 129 | buildRules = ( 130 | ); 131 | dependencies = ( 132 | ); 133 | name = "IndexSet-Backed-Table"; 134 | productName = "IndexSet-Backed-Table"; 135 | productReference = 14373457178BA05700F0910D /* IndexSet-Backed-Table.app */; 136 | productType = "com.apple.product-type.application"; 137 | }; 138 | /* End PBXNativeTarget section */ 139 | 140 | /* Begin PBXProject section */ 141 | 1437344F178BA05700F0910D /* Project object */ = { 142 | isa = PBXProject; 143 | attributes = { 144 | CLASSPREFIX = SD; 145 | LastUpgradeCheck = 0460; 146 | ORGANIZATIONNAME = "Sean Dougherty"; 147 | }; 148 | buildConfigurationList = 14373452178BA05700F0910D /* Build configuration list for PBXProject "IndexSet-Backed-Table" */; 149 | compatibilityVersion = "Xcode 3.2"; 150 | developmentRegion = English; 151 | hasScannedForEncodings = 0; 152 | knownRegions = ( 153 | en, 154 | ); 155 | mainGroup = 1437344E178BA05700F0910D; 156 | productRefGroup = 14373458178BA05700F0910D /* Products */; 157 | projectDirPath = ""; 158 | projectRoot = ""; 159 | targets = ( 160 | 14373456178BA05700F0910D /* IndexSet-Backed-Table */, 161 | ); 162 | }; 163 | /* End PBXProject section */ 164 | 165 | /* Begin PBXResourcesBuildPhase section */ 166 | 14373455178BA05700F0910D /* Resources */ = { 167 | isa = PBXResourcesBuildPhase; 168 | buildActionMask = 2147483647; 169 | files = ( 170 | 14373465178BA05700F0910D /* InfoPlist.strings in Resources */, 171 | 1437346D178BA05700F0910D /* Default.png in Resources */, 172 | 1437346F178BA05700F0910D /* Default@2x.png in Resources */, 173 | 14373471178BA05700F0910D /* Default-568h@2x.png in Resources */, 174 | 14373474178BA05700F0910D /* MainStoryboard_iPhone.storyboard in Resources */, 175 | 14373477178BA05700F0910D /* MainStoryboard_iPad.storyboard in Resources */, 176 | ); 177 | runOnlyForDeploymentPostprocessing = 0; 178 | }; 179 | /* End PBXResourcesBuildPhase section */ 180 | 181 | /* Begin PBXSourcesBuildPhase section */ 182 | 14373453178BA05700F0910D /* Sources */ = { 183 | isa = PBXSourcesBuildPhase; 184 | buildActionMask = 2147483647; 185 | files = ( 186 | 14373467178BA05700F0910D /* main.m in Sources */, 187 | 1437346B178BA05700F0910D /* SDAppDelegate.m in Sources */, 188 | 1437347A178BA05700F0910D /* SDCalendarTableViewController.m in Sources */, 189 | 1437347D178BA05700F0910D /* SDDetailViewController.m in Sources */, 190 | ); 191 | runOnlyForDeploymentPostprocessing = 0; 192 | }; 193 | /* End PBXSourcesBuildPhase section */ 194 | 195 | /* Begin PBXVariantGroup section */ 196 | 14373463178BA05700F0910D /* InfoPlist.strings */ = { 197 | isa = PBXVariantGroup; 198 | children = ( 199 | 14373464178BA05700F0910D /* en */, 200 | ); 201 | name = InfoPlist.strings; 202 | sourceTree = ""; 203 | }; 204 | 14373472178BA05700F0910D /* MainStoryboard_iPhone.storyboard */ = { 205 | isa = PBXVariantGroup; 206 | children = ( 207 | 14373473178BA05700F0910D /* en */, 208 | ); 209 | name = MainStoryboard_iPhone.storyboard; 210 | sourceTree = ""; 211 | }; 212 | 14373475178BA05700F0910D /* MainStoryboard_iPad.storyboard */ = { 213 | isa = PBXVariantGroup; 214 | children = ( 215 | 14373476178BA05700F0910D /* en */, 216 | ); 217 | name = MainStoryboard_iPad.storyboard; 218 | sourceTree = ""; 219 | }; 220 | /* End PBXVariantGroup section */ 221 | 222 | /* Begin XCBuildConfiguration section */ 223 | 1437347E178BA05700F0910D /* Debug */ = { 224 | isa = XCBuildConfiguration; 225 | buildSettings = { 226 | ALWAYS_SEARCH_USER_PATHS = NO; 227 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 228 | CLANG_CXX_LIBRARY = "libc++"; 229 | CLANG_ENABLE_OBJC_ARC = YES; 230 | CLANG_WARN_CONSTANT_CONVERSION = YES; 231 | CLANG_WARN_EMPTY_BODY = YES; 232 | CLANG_WARN_ENUM_CONVERSION = YES; 233 | CLANG_WARN_INT_CONVERSION = YES; 234 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 235 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 236 | COPY_PHASE_STRIP = NO; 237 | GCC_C_LANGUAGE_STANDARD = gnu99; 238 | GCC_DYNAMIC_NO_PIC = NO; 239 | GCC_OPTIMIZATION_LEVEL = 0; 240 | GCC_PREPROCESSOR_DEFINITIONS = ( 241 | "DEBUG=1", 242 | "$(inherited)", 243 | ); 244 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 245 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 246 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 247 | GCC_WARN_UNUSED_VARIABLE = YES; 248 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 249 | ONLY_ACTIVE_ARCH = YES; 250 | SDKROOT = iphoneos; 251 | TARGETED_DEVICE_FAMILY = "1,2"; 252 | }; 253 | name = Debug; 254 | }; 255 | 1437347F178BA05700F0910D /* Release */ = { 256 | isa = XCBuildConfiguration; 257 | buildSettings = { 258 | ALWAYS_SEARCH_USER_PATHS = NO; 259 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 260 | CLANG_CXX_LIBRARY = "libc++"; 261 | CLANG_ENABLE_OBJC_ARC = YES; 262 | CLANG_WARN_CONSTANT_CONVERSION = YES; 263 | CLANG_WARN_EMPTY_BODY = YES; 264 | CLANG_WARN_ENUM_CONVERSION = YES; 265 | CLANG_WARN_INT_CONVERSION = YES; 266 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 267 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 268 | COPY_PHASE_STRIP = YES; 269 | GCC_C_LANGUAGE_STANDARD = gnu99; 270 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 271 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 272 | GCC_WARN_UNUSED_VARIABLE = YES; 273 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 274 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 275 | SDKROOT = iphoneos; 276 | TARGETED_DEVICE_FAMILY = "1,2"; 277 | VALIDATE_PRODUCT = YES; 278 | }; 279 | name = Release; 280 | }; 281 | 14373481178BA05700F0910D /* Debug */ = { 282 | isa = XCBuildConfiguration; 283 | buildSettings = { 284 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 285 | GCC_PREFIX_HEADER = "IndexSet-Backed-Table/IndexSet-Backed-Table-Prefix.pch"; 286 | INFOPLIST_FILE = "IndexSet-Backed-Table/IndexSet-Backed-Table-Info.plist"; 287 | PRODUCT_NAME = "$(TARGET_NAME)"; 288 | WRAPPER_EXTENSION = app; 289 | }; 290 | name = Debug; 291 | }; 292 | 14373482178BA05700F0910D /* Release */ = { 293 | isa = XCBuildConfiguration; 294 | buildSettings = { 295 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 296 | GCC_PREFIX_HEADER = "IndexSet-Backed-Table/IndexSet-Backed-Table-Prefix.pch"; 297 | INFOPLIST_FILE = "IndexSet-Backed-Table/IndexSet-Backed-Table-Info.plist"; 298 | PRODUCT_NAME = "$(TARGET_NAME)"; 299 | WRAPPER_EXTENSION = app; 300 | }; 301 | name = Release; 302 | }; 303 | /* End XCBuildConfiguration section */ 304 | 305 | /* Begin XCConfigurationList section */ 306 | 14373452178BA05700F0910D /* Build configuration list for PBXProject "IndexSet-Backed-Table" */ = { 307 | isa = XCConfigurationList; 308 | buildConfigurations = ( 309 | 1437347E178BA05700F0910D /* Debug */, 310 | 1437347F178BA05700F0910D /* Release */, 311 | ); 312 | defaultConfigurationIsVisible = 0; 313 | defaultConfigurationName = Release; 314 | }; 315 | 14373480178BA05700F0910D /* Build configuration list for PBXNativeTarget "IndexSet-Backed-Table" */ = { 316 | isa = XCConfigurationList; 317 | buildConfigurations = ( 318 | 14373481178BA05700F0910D /* Debug */, 319 | 14373482178BA05700F0910D /* Release */, 320 | ); 321 | defaultConfigurationIsVisible = 0; 322 | }; 323 | /* End XCConfigurationList section */ 324 | }; 325 | rootObject = 1437344F178BA05700F0910D /* Project object */; 326 | } 327 | --------------------------------------------------------------------------------