├── Gemfile ├── TimesSquareTestApp ├── en.lproj │ └── InfoPlist.strings ├── Default.png ├── Default@2x.png ├── TimesSquareTestAppTests │ ├── en.lproj │ │ └── InfoPlist.strings │ ├── TimesSquareTestAppTests.h │ ├── TimesSquareTestAppTests.m │ └── TimesSquareTestAppTests-Info.plist ├── CalendarRow.png ├── CalendarRow@2x.png ├── Default-568h@2x.png ├── CalendarRowBottom.png ├── CalendarRowBottom@2x.png ├── CalendarSelectedDate.png ├── CalendarTodaysDate.png ├── CalendarPreviousMonth.png ├── CalendarTodaysDate@2x.png ├── CalendarPreviousMonth@2x.png ├── CalendarSelectedDate@2x.png ├── TimesSquareTestApp-Prefix.pch ├── TSQTACalendarRowCell.h ├── TSQTAViewController.h ├── TSQTAAppDelegate.h ├── main.m ├── TimesSquareTestApp-Info.plist ├── TSQTACalendarRowCell.m ├── TSQTAAppDelegate.m ├── TSQTAViewController.m └── TimesSquareTestApp.xcodeproj │ ├── xcshareddata │ └── xcschemes │ │ └── TimesSquareTestApp.xcscheme │ └── project.pbxproj ├── Documentation ├── hebrew.png └── gregorian.png ├── TimesSquare ├── TimesSquare-Prefix.pch ├── TimesSquare.h ├── TSQCalendarMonthHeaderCell.h ├── TSQCalendarRowCell.h ├── TSQCalendarCell.h ├── TSQCalendarCell.m ├── TSQCalendarMonthHeaderCell.m ├── TSQCalendarView.h ├── TSQCalendarRowCell.m └── TSQCalendarView.m ├── .travis.yml ├── .gitignore ├── TimesSquare.podspec ├── LICENSE ├── README.md └── TimesSquare.xcodeproj ├── xcshareddata └── xcschemes │ ├── TimesSquare Documentation.xcscheme │ └── TimesSquare.xcscheme └── project.pbxproj /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'cocoapods', '0.37.2' 4 | -------------------------------------------------------------------------------- /TimesSquareTestApp/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Documentation/hebrew.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puls/objc-TimesSquare/HEAD/Documentation/hebrew.png -------------------------------------------------------------------------------- /Documentation/gregorian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puls/objc-TimesSquare/HEAD/Documentation/gregorian.png -------------------------------------------------------------------------------- /TimesSquareTestApp/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puls/objc-TimesSquare/HEAD/TimesSquareTestApp/Default.png -------------------------------------------------------------------------------- /TimesSquareTestApp/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puls/objc-TimesSquare/HEAD/TimesSquareTestApp/Default@2x.png -------------------------------------------------------------------------------- /TimesSquareTestApp/TimesSquareTestAppTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /TimesSquareTestApp/CalendarRow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puls/objc-TimesSquare/HEAD/TimesSquareTestApp/CalendarRow.png -------------------------------------------------------------------------------- /TimesSquareTestApp/CalendarRow@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puls/objc-TimesSquare/HEAD/TimesSquareTestApp/CalendarRow@2x.png -------------------------------------------------------------------------------- /TimesSquareTestApp/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puls/objc-TimesSquare/HEAD/TimesSquareTestApp/Default-568h@2x.png -------------------------------------------------------------------------------- /TimesSquareTestApp/CalendarRowBottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puls/objc-TimesSquare/HEAD/TimesSquareTestApp/CalendarRowBottom.png -------------------------------------------------------------------------------- /TimesSquareTestApp/CalendarRowBottom@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puls/objc-TimesSquare/HEAD/TimesSquareTestApp/CalendarRowBottom@2x.png -------------------------------------------------------------------------------- /TimesSquareTestApp/CalendarSelectedDate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puls/objc-TimesSquare/HEAD/TimesSquareTestApp/CalendarSelectedDate.png -------------------------------------------------------------------------------- /TimesSquareTestApp/CalendarTodaysDate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puls/objc-TimesSquare/HEAD/TimesSquareTestApp/CalendarTodaysDate.png -------------------------------------------------------------------------------- /TimesSquareTestApp/CalendarPreviousMonth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puls/objc-TimesSquare/HEAD/TimesSquareTestApp/CalendarPreviousMonth.png -------------------------------------------------------------------------------- /TimesSquareTestApp/CalendarTodaysDate@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puls/objc-TimesSquare/HEAD/TimesSquareTestApp/CalendarTodaysDate@2x.png -------------------------------------------------------------------------------- /TimesSquareTestApp/CalendarPreviousMonth@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puls/objc-TimesSquare/HEAD/TimesSquareTestApp/CalendarPreviousMonth@2x.png -------------------------------------------------------------------------------- /TimesSquareTestApp/CalendarSelectedDate@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puls/objc-TimesSquare/HEAD/TimesSquareTestApp/CalendarSelectedDate@2x.png -------------------------------------------------------------------------------- /TimesSquare/TimesSquare-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'TimesSquare' target in the 'TimesSquare' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode6.4 3 | before_script: 4 | - bundle install 5 | script: 6 | - xcodebuild -project TimesSquare.xcodeproj -scheme TimesSquare -sdk iphonesimulator -configuration Debug -PBXBuildsContinueAfterErrors=0 ACTIVE_ARCH_ONLY=0 build 7 | - pod lib lint --verbose --fail-fast 8 | -------------------------------------------------------------------------------- /TimesSquareTestApp/TimesSquareTestAppTests/TimesSquareTestAppTests.h: -------------------------------------------------------------------------------- 1 | // 2 | // TimesSquareTestAppTests.h 3 | // TimesSquareTestAppTests 4 | // 5 | // Created by Jim Puls on 1/2/13. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface TimesSquareTestAppTests : SenTestCase 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /TimesSquareTestApp/TimesSquareTestApp-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'TimesSquareTestApp' target in the 'TimesSquareTestApp' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_3_0 8 | #warning "This project uses features only available in iOS SDK 3.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /TimesSquare/TimesSquare.h: -------------------------------------------------------------------------------- 1 | // 2 | // TimesSquare.h 3 | // TimesSquare 4 | // 5 | // Created by Jim Puls on 12/5/12. 6 | // Licensed to Square, Inc. under one or more contributor license agreements. 7 | // See the LICENSE file distributed with this work for the terms under 8 | // which Square, Inc. licenses this file to you. 9 | 10 | #import 11 | #import 12 | #import 13 | -------------------------------------------------------------------------------- /TimesSquareTestApp/TSQTACalendarRowCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // TSQTACalendarRowCell.h 3 | // TimesSquare 4 | // 5 | // Created by Jim Puls on 12/5/12. 6 | // Licensed to Square, Inc. under one or more contributor license agreements. 7 | // See the LICENSE file distributed with this work for the terms under 8 | // which Square, Inc. licenses this file to you. 9 | 10 | #import 11 | 12 | @interface TSQTACalendarRowCell : TSQCalendarRowCell 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /TimesSquareTestApp/TSQTAViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TSQTAViewController.h 3 | // TimesSquare 4 | // 5 | // Created by Jim Puls on 12/5/12. 6 | // Licensed to Square, Inc. under one or more contributor license agreements. 7 | // See the LICENSE file distributed with this work for the terms under 8 | // which Square, Inc. licenses this file to you. 9 | 10 | #import 11 | 12 | @interface TSQTAViewController : UIViewController 13 | 14 | @property (nonatomic, strong) NSCalendar *calendar; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /TimesSquareTestApp/TSQTAAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // TSQTAAppDelegate.h 3 | // TimesSquareTestApp 4 | // 5 | // Created by Jim Puls on 12/5/12. 6 | // Licensed to Square, Inc. under one or more contributor license agreements. 7 | // See the LICENSE file distributed with this work for the terms under 8 | // which Square, Inc. licenses this file to you. 9 | 10 | #import 11 | 12 | @interface TSQTAAppDelegate : UIResponder 13 | 14 | @property (strong, nonatomic) UIWindow *window; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #Ignore the Mac OS X .DS_Store files 2 | .DS_Store 3 | 4 | #Ignore user-specific settings 5 | *.mode1v3 6 | *.mode2v3 7 | *.pbxuser 8 | *.perspectivev3 9 | *.xcworkspace 10 | xcuserdata 11 | 12 | #Ignore textmate build errors 13 | *.tm_build_errors 14 | 15 | #Ignore temp nibs and swap files 16 | *.swp 17 | *~.nib 18 | 19 | #Ignore the build, since we don't want archived builds 20 | build 21 | 22 | .gitattributes 23 | 24 | #Probably don't want to check in xcuserdata 25 | xcuserdata/ 26 | *.xcworkspace/ 27 | 28 | *.orig 29 | .idea 30 | -------------------------------------------------------------------------------- /TimesSquareTestApp/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // TimesSquareTestApp 4 | // 5 | // Created by Jim Puls on 12/5/12. 6 | // Licensed to Square, Inc. under one or more contributor license agreements. 7 | // See the LICENSE file distributed with this work for the terms under 8 | // which Square, Inc. licenses this file to you. 9 | 10 | #import 11 | 12 | #import "TSQTAAppDelegate.h" 13 | 14 | int main(int argc, char *argv[]) 15 | { 16 | @autoreleasepool { 17 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([TSQTAAppDelegate class])); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /TimesSquare.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "TimesSquare" 3 | s.version = "1.0.2" 4 | s.summary = "TimesSquare is an Objective-C calendar view for your apps." 5 | s.homepage = "https://github.com/square/objc-TimesSquare" 6 | s.license = 'Apache License, Version 2.0' 7 | s.author = { "Square" => "http://squareup.com" } 8 | s.source = { :git => "https://github.com/square/objc-TimesSquare.git", :branch => "master", :tag => s.version.to_s } 9 | s.platform = :ios, '5.0' 10 | s.source_files = 'TimesSquare/*.{h,m}' 11 | s.requires_arc = true 12 | end -------------------------------------------------------------------------------- /TimesSquareTestApp/TimesSquareTestAppTests/TimesSquareTestAppTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // TimesSquareTestAppTests.m 3 | // TimesSquareTestAppTests 4 | // 5 | // Created by Jim Puls on 1/2/13. 6 | // 7 | // 8 | 9 | #import "TimesSquareTestAppTests.h" 10 | 11 | @implementation TimesSquareTestAppTests 12 | 13 | - (void)setUp 14 | { 15 | [super setUp]; 16 | 17 | // Set-up code here. 18 | } 19 | 20 | - (void)tearDown 21 | { 22 | // Tear-down code here. 23 | 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample 28 | { 29 | STFail(@"Unit tests are not implemented yet in TimesSquareTestAppTests"); 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | TimesSquare 2 | Copyright 2012 Square, Inc. 3 | A full list of contributors is available at https://github.com/square/objc-TimesSquare/contributors 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | -------------------------------------------------------------------------------- /TimesSquareTestApp/TimesSquareTestAppTests/TimesSquareTestAppTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.squareup.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /TimesSquareTestApp/TimesSquareTestApp-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.squareup.${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 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /TimesSquare/TSQCalendarMonthHeaderCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // TSQCalendarMonthHeaderCell.h 3 | // TimesSquare 4 | // 5 | // Created by Jim Puls on 11/14/12. 6 | // Licensed to Square, Inc. under one or more contributor license agreements. 7 | // See the LICENSE file distributed with this work for the terms under 8 | // which Square, Inc. licenses this file to you. 9 | 10 | #import "TSQCalendarCell.h" 11 | 12 | /** The `TSQCalendarMonthHeaderCell` class displays the month name and day names at the top of a month's worth of weeks. 13 | 14 | By default, it lays out the day names in the bottom 20 points, the month name in the remainder of its height, and has a height of 65 points. You'll want to subclass it to change any of those things. 15 | */ 16 | @interface TSQCalendarMonthHeaderCell : TSQCalendarCell 17 | 18 | /** @name Day Labels */ 19 | 20 | /** The day header labels. 21 | 22 | The count is equal to the `daysInWeek` property, likely seven. You can position them in the call to `layoutViewsForColumnAtIndex:inRect:`. 23 | */ 24 | @property (nonatomic, strong) NSArray *headerLabels; 25 | 26 | 27 | /** Creates the header labels. 28 | 29 | If you want the text in your header labels to be something other than the short day format ("Mon Tue Wed" etc.), override this method, call `super`, and loop through `self.headerLabels`, changing their text. 30 | */ 31 | - (void)createHeaderLabels; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /TimesSquareTestApp/TSQTACalendarRowCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // TSQTACalendarRowCell.m 3 | // TimesSquare 4 | // 5 | // Created by Jim Puls on 12/5/12. 6 | // Licensed to Square, Inc. under one or more contributor license agreements. 7 | // See the LICENSE file distributed with this work for the terms under 8 | // which Square, Inc. licenses this file to you. 9 | 10 | #import "TSQTACalendarRowCell.h" 11 | 12 | @implementation TSQTACalendarRowCell 13 | 14 | - (void)layoutViewsForColumnAtIndex:(NSUInteger)index inRect:(CGRect)rect; 15 | { 16 | // Move down for the row at the top 17 | rect.origin.y += self.columnSpacing; 18 | rect.size.height -= (self.bottomRow ? 2.0f : 1.0f) * self.columnSpacing; 19 | [super layoutViewsForColumnAtIndex:index inRect:rect]; 20 | } 21 | 22 | - (UIImage *)todayBackgroundImage; 23 | { 24 | return [[UIImage imageNamed:@"CalendarTodaysDate.png"] stretchableImageWithLeftCapWidth:4 topCapHeight:4]; 25 | } 26 | 27 | - (UIImage *)selectedBackgroundImage; 28 | { 29 | return [[UIImage imageNamed:@"CalendarSelectedDate.png"] stretchableImageWithLeftCapWidth:4 topCapHeight:4]; 30 | } 31 | 32 | - (UIImage *)notThisMonthBackgroundImage; 33 | { 34 | return [[UIImage imageNamed:@"CalendarPreviousMonth.png"] stretchableImageWithLeftCapWidth:0 topCapHeight:0]; 35 | } 36 | 37 | - (UIImage *)backgroundImage; 38 | { 39 | return [UIImage imageNamed:[NSString stringWithFormat:@"CalendarRow%@.png", self.bottomRow ? @"Bottom" : @""]]; 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /TimesSquareTestApp/TSQTAAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // TSQTAAppDelegate.m 3 | // TimesSquareTestApp 4 | // 5 | // Created by Jim Puls on 12/5/12. 6 | // Licensed to Square, Inc. under one or more contributor license agreements. 7 | // See the LICENSE file distributed with this work for the terms under 8 | // which Square, Inc. licenses this file to you. 9 | 10 | #import "TSQTAAppDelegate.h" 11 | #import "TSQTAViewController.h" 12 | 13 | @implementation TSQTAAppDelegate 14 | 15 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 16 | { 17 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 18 | 19 | TSQTAViewController *gregorian = [[TSQTAViewController alloc] init]; 20 | gregorian.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; 21 | gregorian.calendar.locale = [NSLocale currentLocale]; 22 | 23 | TSQTAViewController *hebrew = [[TSQTAViewController alloc] init]; 24 | hebrew.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSHebrewCalendar]; 25 | hebrew.calendar.locale = [NSLocale currentLocale]; 26 | 27 | TSQTAViewController *islamic = [[TSQTAViewController alloc] init]; 28 | islamic.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSIslamicCalendar]; 29 | islamic.calendar.locale = [NSLocale currentLocale]; 30 | 31 | TSQTAViewController *indian = [[TSQTAViewController alloc] init]; 32 | indian.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSIndianCalendar]; 33 | indian.calendar.locale = [NSLocale currentLocale]; 34 | 35 | TSQTAViewController *persian = [[TSQTAViewController alloc] init]; 36 | persian.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSPersianCalendar]; 37 | persian.calendar.locale = [NSLocale currentLocale]; 38 | 39 | UITabBarController *tabController = [[UITabBarController alloc] init]; 40 | tabController.viewControllers = @[gregorian, hebrew, islamic, indian, persian]; 41 | self.window.rootViewController = tabController; 42 | 43 | [self.window makeKeyAndVisible]; 44 | return YES; 45 | } 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TimesSquare 2 | 3 | [![CI Status](https://travis-ci.org/square/objc-TimesSquare.svg?branch=master)](https://travis-ci.org/square/objc-TimesSquare) 4 | [![Version](https://img.shields.io/cocoapods/v/TimesSquare.svg)](http://cocoadocs.org/docsets/TimesSquare) 5 | [![License](https://img.shields.io/cocoapods/l/TimesSquare.svg)](http://cocoadocs.org/docsets/TimesSquare) 6 | [![Platform](https://img.shields.io/cocoapods/p/TimesSquare.svg)](http://cocoadocs.org/docsets/TimesSquare) 7 | 8 | TimesSquare is a library to display a calendar in a view in your iPhone or iPad app. We wrote it after searching high and low for a better way and finding none. 9 | 10 | ## Usage 11 | ![Gregorian Calendar](https://github.com/square/objc-TimesSquare/raw/master/Documentation/gregorian.png) 12 | 13 | Easy: create an instance of `TSQCalendarView`. Set its `firstDate` and `lastDate` properties to give yourself a range of dates. 14 | 15 | ## Calendars 16 | ![Hebrew Calendar](https://github.com/square/objc-TimesSquare/raw/master/Documentation/hebrew.png) 17 | 18 | While we fully expect you'll use it to display a Gregorian calendar most of the time, TimesSquare is just as happy displaying any of the calendars `NSCalendar` supports. The included test app shows you how to do this. 19 | 20 | ## Further documentation 21 | 22 | If you install [appledoc](http://gentlebytes.com/appledoc/) ("`brew info homebrew/versions/appledoc22`", "`ln -s /usr/local/Cellar/appledoc22/2.2.1/bin/appledoc /usr/local/bin/appledoc`") you can build the "TimesSquare Documentation" target in Xcode and see (and search!) the full API in your documentation window. 23 | 24 | ## Contributing 25 | 26 | We're glad you're interested in TimesSquare, and we'd love to see where you take it. 27 | 28 | Any contributors to the master TimesSquare repository must sign the [Individual Contributor License Agreement (CLA)](https://spreadsheets.google.com/spreadsheet/viewform?formkey=dDViT2xzUHAwRkI3X3k5Z0lQM091OGc6MQ&ndplr=1). It's a short form that covers our bases and makes sure you're eligible to contribute. 29 | 30 | When you have a change you'd like to see in the master repository, [send a pull request](https://github.com/square/objc-TimesSquare/pulls). Before we merge your request, we'll make sure you're in the list of people who have signed a CLA. 31 | 32 | Thanks, and happy date picking! 33 | -------------------------------------------------------------------------------- /TimesSquareTestApp/TSQTAViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TSQTAViewController.m 3 | // TimesSquare 4 | // 5 | // Created by Jim Puls on 12/5/12. 6 | // Licensed to Square, Inc. under one or more contributor license agreements. 7 | // See the LICENSE file distributed with this work for the terms under 8 | // which Square, Inc. licenses this file to you. 9 | 10 | #import "TSQTAViewController.h" 11 | #import "TSQTACalendarRowCell.h" 12 | #import 13 | 14 | 15 | @interface TSQTAViewController () 16 | 17 | @property (nonatomic, retain) NSTimer *timer; 18 | 19 | @end 20 | 21 | 22 | @interface TSQCalendarView (AccessingPrivateStuff) 23 | 24 | @property (nonatomic, readonly) UITableView *tableView; 25 | 26 | @end 27 | 28 | 29 | @implementation TSQTAViewController 30 | 31 | - (void)loadView; 32 | { 33 | TSQCalendarView *calendarView = [[TSQCalendarView alloc] init]; 34 | calendarView.calendar = self.calendar; 35 | calendarView.rowCellClass = [TSQTACalendarRowCell class]; 36 | calendarView.firstDate = [NSDate dateWithTimeIntervalSinceNow:-60 * 60 * 24 * 365 * 1]; 37 | calendarView.lastDate = [NSDate dateWithTimeIntervalSinceNow:60 * 60 * 24 * 365 * 5]; 38 | calendarView.backgroundColor = [UIColor colorWithRed:0.84f green:0.85f blue:0.86f alpha:1.0f]; 39 | calendarView.pagingEnabled = YES; 40 | CGFloat onePixel = 1.0f / [UIScreen mainScreen].scale; 41 | calendarView.contentInset = UIEdgeInsetsMake(0.0f, onePixel, 0.0f, onePixel); 42 | 43 | self.view = calendarView; 44 | } 45 | 46 | - (void)setCalendar:(NSCalendar *)calendar; 47 | { 48 | _calendar = calendar; 49 | 50 | self.navigationItem.title = calendar.calendarIdentifier; 51 | self.tabBarItem.title = calendar.calendarIdentifier; 52 | } 53 | 54 | - (void)viewDidLayoutSubviews; 55 | { 56 | // Set the calendar view to show today date on start 57 | [(TSQCalendarView *)self.view scrollToDate:[NSDate date] animated:NO]; 58 | } 59 | 60 | - (void)viewDidAppear:(BOOL)animated; 61 | { 62 | [super viewDidAppear:animated]; 63 | 64 | // Uncomment this to test scrolling performance of your custom drawing 65 | // self.timer = [NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:@selector(scroll) userInfo:nil repeats:YES]; 66 | } 67 | 68 | - (void)viewWillDisappear:(BOOL)animated; 69 | { 70 | [self.timer invalidate]; 71 | self.timer = nil; 72 | } 73 | 74 | - (void)scroll; 75 | { 76 | static BOOL atTop = YES; 77 | TSQCalendarView *calendarView = (TSQCalendarView *)self.view; 78 | UITableView *tableView = calendarView.tableView; 79 | 80 | [tableView setContentOffset:CGPointMake(0.f, atTop ? 10000.f : 0.f) animated:YES]; 81 | atTop = !atTop; 82 | } 83 | 84 | @end 85 | -------------------------------------------------------------------------------- /TimesSquare.xcodeproj/xcshareddata/xcschemes/TimesSquare Documentation.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 60 | 61 | 63 | 64 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /TimesSquare/TSQCalendarRowCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // TSQCalendarRowCell.h 3 | // TimesSquare 4 | // 5 | // Created by Jim Puls on 11/14/12. 6 | // Licensed to Square, Inc. under one or more contributor license agreements. 7 | // See the LICENSE file distributed with this work for the terms under 8 | // which Square, Inc. licenses this file to you. 9 | 10 | #import "TSQCalendarCell.h" 11 | 12 | /** The `TSQCalendarRowCell` class is a cell that represents one week in the calendar. 13 | 14 | Each of the seven columns can represent a day that's in this month, a day that's not in this month, a selected day, today, or an unselected day. The cell uses several images placed strategically to achieve the effect. 15 | */ 16 | @interface TSQCalendarRowCell : TSQCalendarCell 17 | 18 | /** @name Images */ 19 | 20 | /** The background image for the entire row. 21 | 22 | This image should be as wide as the entire view and include the grid lines between the columns. It will probably also include the grid line at the top of the row, but not the one at the bottom. 23 | 24 | You might, however, return a different image that includes both the grid line at the top and the one at the bottom if the `bottomRow` property is set to `YES`. You might even adjust the `cellHeight`. 25 | */ 26 | @property (nonatomic, weak, readonly) UIImage *backgroundImage; 27 | 28 | /** The background image for a day that's selected. 29 | 30 | This is blue in the system's built-in Calendar app. You probably want to use a stretchable image. 31 | */ 32 | @property (nonatomic, weak, readonly) UIImage *selectedBackgroundImage; 33 | 34 | /** The background image for a day that's "today". 35 | 36 | This is dark gray in the system's built-in Calendar app. You probably want to use a stretchable image. 37 | */ 38 | @property (nonatomic, weak, readonly) UIImage *todayBackgroundImage; 39 | 40 | /** The background image for a day that's not this month. 41 | 42 | These are the trailing days from the previous month or the leading days from the following month. This can be `nil`. 43 | */ 44 | @property (nonatomic, weak, readonly) UIImage *notThisMonthBackgroundImage; 45 | 46 | /** @name State Properties Set by Calendar View */ 47 | 48 | /** The date at the beginning of the week for this cell. 49 | 50 | Notice that it might be before the `firstOfMonth` property or it might be after. 51 | */ 52 | @property (nonatomic, strong) NSDate *beginningDate; 53 | 54 | /** Whether this cell is the bottom row / last week for the month. 55 | 56 | You may find yourself using a different background image or laying out differently in the last row. 57 | */ 58 | @property (nonatomic, getter = isBottomRow) BOOL bottomRow; 59 | 60 | /** Method to select a specific date within the week. 61 | 62 | This is funneled through and called by the calendar view, to facilitate deselection of other rows. 63 | 64 | @param date The date to select, or nil to deselect all columns. 65 | */ 66 | - (void)selectColumnForDate:(NSDate *)date; 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /TimesSquare.xcodeproj/xcshareddata/xcschemes/TimesSquare.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /TimesSquare/TSQCalendarCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // TSQCalendarCell.h 3 | // TimesSquare 4 | // 5 | // Created by Jim Puls on 11/15/12. 6 | // Licensed to Square, Inc. under one or more contributor license agreements. 7 | // See the LICENSE file distributed with this work for the terms under 8 | // which Square, Inc. licenses this file to you. 9 | 10 | #import 11 | 12 | 13 | @class TSQCalendarView; 14 | 15 | 16 | /** The `TSQCalendarCell` class is an abstract superclass to the two cell types used for display in a `TSQCalendarView`. 17 | 18 | Most of its interface deals with display properties. The most interesting method is `-layoutViewsForColumnAtIndex:inRect:`, which is a simple way of handling seven columns. 19 | */ 20 | @interface TSQCalendarCell : UITableViewCell 21 | 22 | /** @name State Properties Set by Calendar View */ 23 | 24 | /** The first day of the month this cell is currently representing. 25 | 26 | This can be useful for calculations and for display. 27 | */ 28 | @property (nonatomic, strong) NSDate *firstOfMonth; 29 | 30 | /** How many days there are in a week. 31 | 32 | This is usually 7. 33 | */ 34 | @property (nonatomic, readonly) NSUInteger daysInWeek; 35 | 36 | /** The calendar type we're displaying. 37 | 38 | This is whatever the owning `TSQCalendarView`'s `calendar` property is set to; it's likely `[NSCalendar currentCalendar]`. 39 | */ 40 | @property (nonatomic, strong) NSCalendar *calendar; 41 | 42 | /** The owning calendar view. 43 | 44 | This is a weak reference. 45 | */ 46 | @property (nonatomic, weak) TSQCalendarView *calendarView; 47 | 48 | /** @name Display Properties */ 49 | 50 | /** The preferred height for instances of this cell. 51 | 52 | The built-in implementation in `TSQCalendarCell` returns `46.0f`. Your subclass may want to return another value. 53 | */ 54 | + (CGFloat) cellHeight; 55 | 56 | /** The text color. 57 | 58 | This is used for all text the cell draws; if a date is disabled, then it will draw in this color, but at 50% opacity. 59 | */ 60 | @property (nonatomic, strong) UIColor *textColor; 61 | 62 | /** The text shadow offset. 63 | 64 | This is as you would set on `UILabel`. 65 | */ 66 | @property (nonatomic) CGSize shadowOffset; 67 | 68 | /** The spacing between columns. 69 | 70 | This defaults to one pixel or `1.0 / [UIScreen mainScreen].scale`. 71 | */ 72 | @property (nonatomic) CGFloat columnSpacing; 73 | 74 | /** @name Initialization */ 75 | 76 | /** Initializes the cell. 77 | 78 | @param calendar The `NSCalendar` the cell is representing 79 | @param reuseIdentifier A string reuse identifier, as used by `UITableViewCell` 80 | */ 81 | - (id)initWithCalendar:(NSCalendar *)calendar reuseIdentifier:(NSString *)reuseIdentifier; 82 | 83 | /** Seven-column layout helper. 84 | 85 | @param index The index of the column we're laying out, probably in the range [0..6] 86 | @param rect The rect relative to the bounds of the cell's content view that represents the column. 87 | 88 | Feel free to adjust the rect before moving views and to vertically position them within the column. (In fact, you could ignore the rect entirely; it's just there to help.) 89 | */ 90 | - (void)layoutViewsForColumnAtIndex:(NSUInteger)index inRect:(CGRect)rect; 91 | 92 | @end 93 | -------------------------------------------------------------------------------- /TimesSquareTestApp/TimesSquareTestApp.xcodeproj/xcshareddata/xcschemes/TimesSquareTestApp.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /TimesSquare/TSQCalendarCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // TSQCalendarCell.m 3 | // TimesSquare 4 | // 5 | // Created by Jim Puls on 11/15/12. 6 | // Licensed to Square, Inc. under one or more contributor license agreements. 7 | // See the LICENSE file distributed with this work for the terms under 8 | // which Square, Inc. licenses this file to you. 9 | 10 | #import "TSQCalendarCell.h" 11 | #import "TSQCalendarView.h" 12 | 13 | 14 | @interface TSQCalendarCell () 15 | 16 | @property (nonatomic, assign) NSLocaleLanguageDirection layoutDirection; 17 | 18 | @end 19 | 20 | 21 | @implementation TSQCalendarCell 22 | 23 | - (id)initWithCalendar:(NSCalendar *)calendar reuseIdentifier:(NSString *)reuseIdentifier; 24 | { 25 | self = [self initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier]; 26 | if (!self) { 27 | return nil; 28 | } 29 | 30 | _calendar = calendar; 31 | NSString *languageCode = [[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode]; 32 | self.layoutDirection = [NSLocale characterDirectionForLanguage:languageCode]; 33 | self.backgroundColor = [UIColor colorWithRed:0.84f green:0.85f blue:0.86f alpha:1.0f]; 34 | 35 | CGFloat onePixel = 1.0f / [UIScreen mainScreen].scale; 36 | 37 | static CGSize shadowOffset; 38 | static dispatch_once_t onceToken; 39 | dispatch_once(&onceToken, ^{ 40 | shadowOffset = CGSizeMake(0.0f, onePixel); 41 | }); 42 | self.shadowOffset = shadowOffset; 43 | self.columnSpacing = onePixel; 44 | self.textColor = [UIColor colorWithRed:0.47f green:0.5f blue:0.53f alpha:1.0f]; 45 | 46 | return self; 47 | } 48 | 49 | + (CGFloat)cellHeight; 50 | { 51 | return 46.0f; 52 | } 53 | 54 | - (NSUInteger)daysInWeek; 55 | { 56 | static NSUInteger daysInWeek = 0; 57 | if (daysInWeek == 0) { 58 | daysInWeek = [self.calendar maximumRangeOfUnit:NSWeekdayCalendarUnit].length; 59 | } 60 | return daysInWeek; 61 | } 62 | 63 | - (UITableViewCellSelectionStyle)selectionStyle; 64 | { 65 | return UITableViewCellSelectionStyleNone; 66 | } 67 | 68 | - (void)setHighlighted:(BOOL)selected animated:(BOOL)animated; 69 | { 70 | // do nothing 71 | } 72 | 73 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated; 74 | { 75 | // do nothing 76 | } 77 | 78 | - (void)layoutViewsForColumnAtIndex:(NSUInteger)index inRect:(CGRect)rect; 79 | { 80 | // for subclass to implement 81 | } 82 | 83 | - (void)layoutSubviews; 84 | { 85 | [super layoutSubviews]; 86 | 87 | UIEdgeInsets insets = self.calendarView.contentInset; 88 | 89 | 90 | CGRect insetRect = UIEdgeInsetsInsetRect(self.bounds, insets); 91 | insetRect.origin.y = CGRectGetMinY(self.bounds); 92 | insetRect.size.height = CGRectGetHeight(self.bounds); 93 | CGFloat increment = (CGRectGetWidth(insetRect) - (self.daysInWeek - 1) * self.columnSpacing) / self.daysInWeek; 94 | increment = roundf(increment); 95 | CGFloat __block start = insets.left; 96 | 97 | CGFloat extraSpace = (CGRectGetWidth(insetRect) - (self.daysInWeek - 1) * self.columnSpacing) - (increment * self.daysInWeek); 98 | 99 | // Divide the extra space out over the outer columns in increments of the column spacing 100 | NSInteger columnsWithExtraSpace = (NSInteger)fabs(extraSpace / self.columnSpacing); 101 | NSInteger columnsOnLeftWithExtraSpace = columnsWithExtraSpace / 2; 102 | NSInteger columnsOnRightWithExtraSpace = columnsWithExtraSpace - columnsOnLeftWithExtraSpace; 103 | 104 | for (NSUInteger index = 0; index < self.daysInWeek; index++) { 105 | CGFloat width = increment; 106 | if (index < columnsOnLeftWithExtraSpace || index >= self.daysInWeek - columnsOnRightWithExtraSpace) { 107 | width += (extraSpace / columnsWithExtraSpace); 108 | } 109 | 110 | NSUInteger displayIndex = index; 111 | if (self.layoutDirection == NSLocaleLanguageDirectionRightToLeft) { 112 | displayIndex = self.daysInWeek - index - 1; 113 | } 114 | 115 | CGRect columnBounds = self.bounds; 116 | columnBounds.origin.x = start; 117 | columnBounds.size.width = width; 118 | [self layoutViewsForColumnAtIndex:displayIndex inRect:columnBounds]; 119 | start += width + self.columnSpacing; 120 | } 121 | 122 | } 123 | 124 | @end 125 | -------------------------------------------------------------------------------- /TimesSquare/TSQCalendarMonthHeaderCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // TSQCalendarMonthHeaderCell.m 3 | // TimesSquare 4 | // 5 | // Created by Jim Puls on 11/14/12. 6 | // Licensed to Square, Inc. under one or more contributor license agreements. 7 | // See the LICENSE file distributed with this work for the terms under 8 | // which Square, Inc. licenses this file to you. 9 | 10 | #import "TSQCalendarMonthHeaderCell.h" 11 | 12 | 13 | static const CGFloat TSQCalendarMonthHeaderCellMonthsHeight = 20.f; 14 | 15 | 16 | @interface TSQCalendarMonthHeaderCell () 17 | 18 | @property (nonatomic, strong) NSDateFormatter *monthDateFormatter; 19 | 20 | @end 21 | 22 | 23 | @implementation TSQCalendarMonthHeaderCell 24 | 25 | - (id)initWithCalendar:(NSCalendar *)calendar reuseIdentifier:(NSString *)reuseIdentifier; 26 | { 27 | self = [super initWithCalendar:calendar reuseIdentifier:reuseIdentifier]; 28 | if (!self) { 29 | return nil; 30 | } 31 | 32 | [self createHeaderLabels]; 33 | 34 | return self; 35 | } 36 | 37 | 38 | + (CGFloat)cellHeight; 39 | { 40 | return 65.0f; 41 | } 42 | 43 | - (NSDateFormatter *)monthDateFormatter; 44 | { 45 | if (!_monthDateFormatter) { 46 | _monthDateFormatter = [NSDateFormatter new]; 47 | _monthDateFormatter.calendar = self.calendar; 48 | 49 | NSString *dateComponents = @"yyyyLLLL"; 50 | _monthDateFormatter.dateFormat = [NSDateFormatter dateFormatFromTemplate:dateComponents options:0 locale:[NSLocale currentLocale]]; 51 | } 52 | return _monthDateFormatter; 53 | } 54 | 55 | - (void)createHeaderLabels; 56 | { 57 | NSDate *referenceDate = [NSDate dateWithTimeIntervalSinceReferenceDate:0]; 58 | NSDateComponents *offset = [NSDateComponents new]; 59 | offset.day = 1; 60 | NSMutableArray *headerLabels = [NSMutableArray arrayWithCapacity:self.daysInWeek]; 61 | 62 | NSDateFormatter *dayFormatter = [NSDateFormatter new]; 63 | dayFormatter.calendar = self.calendar; 64 | dayFormatter.dateFormat = @"cccccc"; 65 | 66 | for (NSUInteger index = 0; index < self.daysInWeek; index++) { 67 | [headerLabels addObject:@""]; 68 | } 69 | 70 | for (NSUInteger index = 0; index < self.daysInWeek; index++) { 71 | NSInteger ordinality = [self.calendar ordinalityOfUnit:NSDayCalendarUnit inUnit:NSWeekCalendarUnit forDate:referenceDate]; 72 | UILabel *label = [[UILabel alloc] initWithFrame:self.frame]; 73 | label.textAlignment = UITextAlignmentCenter; 74 | label.text = [dayFormatter stringFromDate:referenceDate]; 75 | label.font = [UIFont boldSystemFontOfSize:12.f]; 76 | label.backgroundColor = self.backgroundColor; 77 | label.textColor = self.textColor; 78 | label.shadowColor = [UIColor whiteColor]; 79 | label.shadowOffset = self.shadowOffset; 80 | [label sizeToFit]; 81 | headerLabels[ordinality - 1] = label; 82 | [self.contentView addSubview:label]; 83 | 84 | referenceDate = [self.calendar dateByAddingComponents:offset toDate:referenceDate options:0]; 85 | } 86 | 87 | self.headerLabels = headerLabels; 88 | self.textLabel.textAlignment = UITextAlignmentCenter; 89 | self.textLabel.textColor = self.textColor; 90 | self.textLabel.shadowColor = [UIColor whiteColor]; 91 | self.textLabel.shadowOffset = self.shadowOffset; 92 | } 93 | 94 | - (void)layoutSubviews; 95 | { 96 | [super layoutSubviews]; 97 | 98 | CGRect bounds = self.contentView.bounds; 99 | bounds.size.height -= TSQCalendarMonthHeaderCellMonthsHeight; 100 | self.textLabel.frame = CGRectOffset(bounds, 0.0f, 5.0f); 101 | } 102 | 103 | - (void)layoutViewsForColumnAtIndex:(NSUInteger)index inRect:(CGRect)rect; 104 | { 105 | UILabel *label = self.headerLabels[index]; 106 | CGRect labelFrame = rect; 107 | labelFrame.size.height = TSQCalendarMonthHeaderCellMonthsHeight; 108 | labelFrame.origin.y = self.bounds.size.height - TSQCalendarMonthHeaderCellMonthsHeight; 109 | label.frame = labelFrame; 110 | } 111 | 112 | - (void)setFirstOfMonth:(NSDate *)firstOfMonth; 113 | { 114 | [super setFirstOfMonth:firstOfMonth]; 115 | self.textLabel.text = [self.monthDateFormatter stringFromDate:firstOfMonth]; 116 | self.accessibilityLabel = self.textLabel.text; 117 | } 118 | 119 | - (void)setBackgroundColor:(UIColor *)backgroundColor; 120 | { 121 | [super setBackgroundColor:backgroundColor]; 122 | for (UILabel *label in self.headerLabels) { 123 | label.backgroundColor = backgroundColor; 124 | } 125 | } 126 | 127 | @end 128 | -------------------------------------------------------------------------------- /TimesSquare/TSQCalendarView.h: -------------------------------------------------------------------------------- 1 | // 2 | // TSQCalendarState.h 3 | // TimesSquare 4 | // 5 | // Created by Jim Puls on 11/14/12. 6 | // Licensed to Square, Inc. under one or more contributor license agreements. 7 | // See the LICENSE file distributed with this work for the terms under 8 | // which Square, Inc. licenses this file to you. 9 | 10 | #import 11 | 12 | 13 | @protocol TSQCalendarViewDelegate; 14 | 15 | 16 | /** The `TSQCalendarView` class displays a monthly calendar in a self-contained scrolling view. It supports any calendar that `NSCalendar` supports. 17 | 18 | The implementation and usage are very similar to `UITableView`: the app provides reusable cells via a data source and controls behavior via a delegate. See `TSQCalendarCell` for a cell superclass. 19 | */ 20 | @interface TSQCalendarView : UIView 21 | 22 | /** @name Date Setup */ 23 | 24 | /** The earliest month the calendar view displays. 25 | 26 | Set this property to any `NSDate`; `TSQCalendarView` will only look at the month and year. 27 | Must be set for the calendar to be useful. 28 | */ 29 | @property (nonatomic, strong) NSDate *firstDate; 30 | 31 | /** The latest month the calendar view displays. 32 | 33 | Set this property to any `NSDate`; `TSQCalendarView` will only look at the month and year. 34 | Must be set for the calendar to be useful. 35 | */ 36 | @property (nonatomic, strong) NSDate *lastDate; 37 | 38 | /** The currently-selected date on the calendar. 39 | 40 | Set this property to any `NSDate`; `TSQCalendarView` will only look at the month, day, and year. 41 | You can read and write this property; the delegate method `calendarView:didSelectDate:` will be called both when a new date is selected from the UI and when this method is called manually. 42 | */ 43 | @property (nonatomic, strong) NSDate *selectedDate; 44 | 45 | /** @name Calendar Configuration */ 46 | 47 | /** The calendar type to use when displaying. 48 | 49 | If not set, this defaults to `[NSCalendar currentCalendar]`. 50 | */ 51 | @property (nonatomic, strong) NSCalendar *calendar; 52 | 53 | /** @name Visual Configuration */ 54 | 55 | /** The delegate of the calendar view. 56 | 57 | The delegate must adopt the `TSQCalendarViewDelegate` protocol. 58 | The `TSQCalendarView` class, which does not retain the delegate, invokes each protocol method the delegate implements. 59 | */ 60 | @property (nonatomic, weak) id delegate; 61 | 62 | /** Whether to pin the header to the top of the view. 63 | 64 | If you're trying to emulate the built-in calendar app, set this to `YES`. Default value is `NO`. 65 | */ 66 | @property (nonatomic) BOOL pinsHeaderToTop; 67 | 68 | /** Whether or not the calendar snaps to begin a month at the top of its bounds. 69 | 70 | This property is roughly equivalent to the one defined on `UIScrollView` except the snapping is to months rather than integer multiples of the view's bounds. 71 | */ 72 | @property (nonatomic) BOOL pagingEnabled; 73 | 74 | /** The distance from the edges of the view to where the content begins. 75 | 76 | This property is equivalent to the one defined on `UIScrollView`. 77 | */ 78 | @property (nonatomic) UIEdgeInsets contentInset; 79 | 80 | /** The point on the calendar where the currently-visible region starts. 81 | 82 | This property is equivalent to the one defined on `UIScrollView`. 83 | */ 84 | @property (nonatomic) CGPoint contentOffset; 85 | 86 | /** The cell class to use for month headers. 87 | 88 | Since there's very little configuration to be done for each cell, this can be set as a shortcut to implementing a data source. 89 | The class should be a subclass of `TSQCalendarMonthHeaderCell` or at least implement all of its methods. 90 | */ 91 | @property (nonatomic, strong) Class headerCellClass; 92 | 93 | /** The cell class to use for week rows. 94 | 95 | Since there's very little configuration to be done for each cell, this can be set as a shortcut to implementing a data source. 96 | The class should be a subclass of `TSQCalendarRowCell` or at least implement all of its methods. 97 | */ 98 | @property (nonatomic, strong) Class rowCellClass; 99 | 100 | /** Scrolls the receiver until the specified date month is completely visible. 101 | 102 | @param date A date that identifies the month that will be visible. 103 | @param animated YES if you want to animate the change in position, NO if it should be immediate. 104 | */ 105 | - (void)scrollToDate:(NSDate *)date animated:(BOOL)animated; 106 | 107 | 108 | 109 | /** Scrolls the receiver until the specified date is at the specified position in the view. 110 | 111 | @param date A date that identifies the month that will be visible. 112 | @param position A UITableViewScroll Position, determining the position of the date after scroll is finished. 113 | @param animated YES if you want to animate the change in position, NO if it should be immediate. 114 | */ 115 | - (void)scrollDate:(NSDate *)date toPosition:(UITableViewScrollPosition)position animated:(BOOL)animated; 116 | 117 | @end 118 | 119 | /** The methods in the `TSQCalendarViewDelegate` protocol allow the adopting delegate to either prevent a day from being selected or respond to it. 120 | */ 121 | @protocol TSQCalendarViewDelegate 122 | 123 | @optional 124 | 125 | /** @name Responding to Selection */ 126 | 127 | /** Asks the delegate whether a particular date is selectable. 128 | 129 | This method should be relatively efficient, as it is called repeatedly to appropriate enable and disable individual days on the calendar view. 130 | 131 | @param calendarView The calendar view that is selecting a date. 132 | @param date Midnight on the date being selected. 133 | @return Whether or not the date is selectable. 134 | */ 135 | - (BOOL)calendarView:(TSQCalendarView *)calendarView shouldSelectDate:(NSDate *)date; 136 | 137 | /** Tells the delegate that a particular date was selected. 138 | 139 | @param calendarView The calendar view that is selecting a date. 140 | @param date Midnight on the date being selected. 141 | */ 142 | - (void)calendarView:(TSQCalendarView *)calendarView didSelectDate:(NSDate *)date; 143 | 144 | @end 145 | -------------------------------------------------------------------------------- /TimesSquare/TSQCalendarRowCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // TSQCalendarRowCell.m 3 | // TimesSquare 4 | // 5 | // Created by Jim Puls on 11/14/12. 6 | // Licensed to Square, Inc. under one or more contributor license agreements. 7 | // See the LICENSE file distributed with this work for the terms under 8 | // which Square, Inc. licenses this file to you. 9 | 10 | #import "TSQCalendarRowCell.h" 11 | #import "TSQCalendarView.h" 12 | 13 | 14 | @interface TSQCalendarRowCell () 15 | 16 | @property (nonatomic, strong) NSArray *dayButtons; 17 | @property (nonatomic, strong) NSArray *notThisMonthButtons; 18 | @property (nonatomic, strong) UIButton *todayButton; 19 | @property (nonatomic, strong) UIButton *selectedButton; 20 | 21 | @property (nonatomic, assign) NSInteger indexOfTodayButton; 22 | @property (nonatomic, assign) NSInteger indexOfSelectedButton; 23 | 24 | @property (nonatomic, strong) NSDateFormatter *dayFormatter; 25 | @property (nonatomic, strong) NSDateFormatter *accessibilityFormatter; 26 | 27 | @property (nonatomic, strong) NSDateComponents *todayDateComponents; 28 | @property (nonatomic) NSInteger monthOfBeginningDate; 29 | 30 | @end 31 | 32 | 33 | @implementation TSQCalendarRowCell 34 | 35 | - (id)initWithCalendar:(NSCalendar *)calendar reuseIdentifier:(NSString *)reuseIdentifier; 36 | { 37 | self = [super initWithCalendar:calendar reuseIdentifier:reuseIdentifier]; 38 | if (!self) { 39 | return nil; 40 | } 41 | 42 | return self; 43 | } 44 | 45 | - (void)configureButton:(UIButton *)button; 46 | { 47 | button.titleLabel.font = [UIFont boldSystemFontOfSize:19.f]; 48 | button.titleLabel.shadowOffset = self.shadowOffset; 49 | button.adjustsImageWhenDisabled = NO; 50 | [button setTitleColor:self.textColor forState:UIControlStateNormal]; 51 | [button setTitleShadowColor:[UIColor whiteColor] forState:UIControlStateNormal]; 52 | } 53 | 54 | - (void)createDayButtons; 55 | { 56 | NSMutableArray *dayButtons = [NSMutableArray arrayWithCapacity:self.daysInWeek]; 57 | for (NSUInteger index = 0; index < self.daysInWeek; index++) { 58 | UIButton *button = [[UIButton alloc] initWithFrame:self.contentView.bounds]; 59 | [button addTarget:self action:@selector(dateButtonPressed:) forControlEvents:UIControlEventTouchDown]; 60 | [dayButtons addObject:button]; 61 | [self.contentView addSubview:button]; 62 | [self configureButton:button]; 63 | [button setTitleColor:[self.textColor colorWithAlphaComponent:0.5f] forState:UIControlStateDisabled]; 64 | } 65 | self.dayButtons = dayButtons; 66 | } 67 | 68 | - (void)createNotThisMonthButtons; 69 | { 70 | NSMutableArray *notThisMonthButtons = [NSMutableArray arrayWithCapacity:self.daysInWeek]; 71 | for (NSUInteger index = 0; index < self.daysInWeek; index++) { 72 | UIButton *button = [[UIButton alloc] initWithFrame:self.contentView.bounds]; 73 | [notThisMonthButtons addObject:button]; 74 | [self.contentView addSubview:button]; 75 | [self configureButton:button]; 76 | 77 | button.enabled = NO; 78 | UIColor *backgroundPattern = [UIColor colorWithPatternImage:[self notThisMonthBackgroundImage]]; 79 | button.backgroundColor = backgroundPattern; 80 | button.titleLabel.backgroundColor = backgroundPattern; 81 | } 82 | self.notThisMonthButtons = notThisMonthButtons; 83 | } 84 | 85 | - (void)createTodayButton; 86 | { 87 | self.todayButton = [[UIButton alloc] initWithFrame:self.contentView.bounds]; 88 | [self.contentView addSubview:self.todayButton]; 89 | [self configureButton:self.todayButton]; 90 | [self.todayButton addTarget:self action:@selector(todayButtonPressed:) forControlEvents:UIControlEventTouchDown]; 91 | 92 | [self.todayButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 93 | [self.todayButton setBackgroundImage:[self todayBackgroundImage] forState:UIControlStateNormal]; 94 | [self.todayButton setTitleShadowColor:[UIColor colorWithWhite:0.0f alpha:0.75f] forState:UIControlStateNormal]; 95 | 96 | self.todayButton.titleLabel.shadowOffset = CGSizeMake(0.0f, -1.0f / [UIScreen mainScreen].scale); 97 | } 98 | 99 | - (void)createSelectedButton; 100 | { 101 | self.selectedButton = [[UIButton alloc] initWithFrame:self.contentView.bounds]; 102 | [self.contentView addSubview:self.selectedButton]; 103 | [self configureButton:self.selectedButton]; 104 | 105 | [self.selectedButton setAccessibilityTraits:UIAccessibilityTraitSelected|self.selectedButton.accessibilityTraits]; 106 | 107 | self.selectedButton.enabled = NO; 108 | [self.selectedButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 109 | [self.selectedButton setBackgroundImage:[self selectedBackgroundImage] forState:UIControlStateNormal]; 110 | [self.selectedButton setTitleShadowColor:[UIColor colorWithWhite:0.0f alpha:0.75f] forState:UIControlStateNormal]; 111 | 112 | self.selectedButton.titleLabel.shadowOffset = CGSizeMake(0.0f, -1.0f / [UIScreen mainScreen].scale); 113 | self.indexOfSelectedButton = -1; 114 | } 115 | 116 | - (void)setBeginningDate:(NSDate *)date; 117 | { 118 | _beginningDate = date; 119 | 120 | if (!self.dayButtons) { 121 | [self createDayButtons]; 122 | [self createNotThisMonthButtons]; 123 | [self createTodayButton]; 124 | [self createSelectedButton]; 125 | } 126 | 127 | NSDateComponents *offset = [NSDateComponents new]; 128 | offset.day = 1; 129 | 130 | self.todayButton.hidden = YES; 131 | self.indexOfTodayButton = -1; 132 | self.selectedButton.hidden = YES; 133 | self.indexOfSelectedButton = -1; 134 | 135 | for (NSUInteger index = 0; index < self.daysInWeek; index++) { 136 | NSString *title = [self.dayFormatter stringFromDate:date]; 137 | NSString *accessibilityLabel = [self.accessibilityFormatter stringFromDate:date]; 138 | [self.dayButtons[index] setTitle:title forState:UIControlStateNormal]; 139 | [self.dayButtons[index] setAccessibilityLabel:accessibilityLabel]; 140 | [self.notThisMonthButtons[index] setTitle:title forState:UIControlStateNormal]; 141 | [self.notThisMonthButtons[index] setTitle:title forState:UIControlStateDisabled]; 142 | [self.notThisMonthButtons[index] setAccessibilityLabel:accessibilityLabel]; 143 | 144 | NSDateComponents *thisDateComponents = [self.calendar components:NSDayCalendarUnit|NSMonthCalendarUnit|NSYearCalendarUnit fromDate:date]; 145 | 146 | [self.dayButtons[index] setHidden:YES]; 147 | [self.notThisMonthButtons[index] setHidden:YES]; 148 | 149 | NSInteger thisDayMonth = thisDateComponents.month; 150 | if (self.monthOfBeginningDate != thisDayMonth) { 151 | [self.notThisMonthButtons[index] setHidden:NO]; 152 | } else { 153 | 154 | if ([self.todayDateComponents isEqual:thisDateComponents]) { 155 | self.todayButton.hidden = NO; 156 | [self.todayButton setTitle:title forState:UIControlStateNormal]; 157 | [self.todayButton setAccessibilityLabel:accessibilityLabel]; 158 | self.indexOfTodayButton = index; 159 | } else { 160 | UIButton *button = self.dayButtons[index]; 161 | button.enabled = ![self.calendarView.delegate respondsToSelector:@selector(calendarView:shouldSelectDate:)] || [self.calendarView.delegate calendarView:self.calendarView shouldSelectDate:date]; 162 | button.hidden = NO; 163 | } 164 | } 165 | 166 | date = [self.calendar dateByAddingComponents:offset toDate:date options:0]; 167 | } 168 | } 169 | 170 | - (void)setBottomRow:(BOOL)bottomRow; 171 | { 172 | UIImageView *backgroundImageView = (UIImageView *)self.backgroundView; 173 | if ([backgroundImageView isKindOfClass:[UIImageView class]] && _bottomRow == bottomRow) { 174 | return; 175 | } 176 | 177 | _bottomRow = bottomRow; 178 | 179 | self.backgroundView = [[UIImageView alloc] initWithImage:self.backgroundImage]; 180 | 181 | [self setNeedsLayout]; 182 | } 183 | 184 | - (IBAction)dateButtonPressed:(id)sender; 185 | { 186 | NSDateComponents *offset = [NSDateComponents new]; 187 | offset.day = [self.dayButtons indexOfObject:sender]; 188 | NSDate *selectedDate = [self.calendar dateByAddingComponents:offset toDate:self.beginningDate options:0]; 189 | self.calendarView.selectedDate = selectedDate; 190 | } 191 | 192 | - (IBAction)todayButtonPressed:(id)sender; 193 | { 194 | NSDateComponents *offset = [NSDateComponents new]; 195 | offset.day = self.indexOfTodayButton; 196 | NSDate *selectedDate = [self.calendar dateByAddingComponents:offset toDate:self.beginningDate options:0]; 197 | self.calendarView.selectedDate = selectedDate; 198 | } 199 | 200 | - (void)layoutSubviews; 201 | { 202 | if (!self.backgroundView) { 203 | [self setBottomRow:NO]; 204 | } 205 | 206 | [super layoutSubviews]; 207 | 208 | self.backgroundView.frame = self.bounds; 209 | } 210 | 211 | - (void)layoutViewsForColumnAtIndex:(NSUInteger)index inRect:(CGRect)rect; 212 | { 213 | UIButton *dayButton = self.dayButtons[index]; 214 | UIButton *notThisMonthButton = self.notThisMonthButtons[index]; 215 | 216 | dayButton.frame = rect; 217 | notThisMonthButton.frame = rect; 218 | 219 | if (self.indexOfTodayButton == (NSInteger)index) { 220 | self.todayButton.frame = rect; 221 | } 222 | if (self.indexOfSelectedButton == (NSInteger)index) { 223 | self.selectedButton.frame = rect; 224 | } 225 | } 226 | 227 | - (void)selectColumnForDate:(NSDate *)date; 228 | { 229 | if (!date && self.indexOfSelectedButton == -1) { 230 | return; 231 | } 232 | 233 | NSInteger newIndexOfSelectedButton = -1; 234 | if (date) { 235 | NSInteger thisDayMonth = [self.calendar components:NSMonthCalendarUnit fromDate:date].month; 236 | if (self.monthOfBeginningDate == thisDayMonth) { 237 | newIndexOfSelectedButton = [self.calendar components:NSDayCalendarUnit fromDate:self.beginningDate toDate:date options:0].day; 238 | if (newIndexOfSelectedButton >= (NSInteger)self.daysInWeek) { 239 | newIndexOfSelectedButton = -1; 240 | } 241 | } 242 | } 243 | 244 | self.indexOfSelectedButton = newIndexOfSelectedButton; 245 | 246 | if (newIndexOfSelectedButton >= 0) { 247 | self.selectedButton.hidden = NO; 248 | NSString *newTitle = [self.dayButtons[newIndexOfSelectedButton] currentTitle]; 249 | [self.selectedButton setTitle:newTitle forState:UIControlStateNormal]; 250 | [self.selectedButton setTitle:newTitle forState:UIControlStateDisabled]; 251 | [self.selectedButton setAccessibilityLabel:[self.dayButtons[newIndexOfSelectedButton] accessibilityLabel]]; 252 | } else { 253 | self.selectedButton.hidden = YES; 254 | } 255 | 256 | [self setNeedsLayout]; 257 | } 258 | 259 | - (NSDateFormatter *)dayFormatter; 260 | { 261 | if (!_dayFormatter) { 262 | _dayFormatter = [NSDateFormatter new]; 263 | _dayFormatter.calendar = self.calendar; 264 | _dayFormatter.dateFormat = @"d"; 265 | } 266 | return _dayFormatter; 267 | } 268 | 269 | - (NSDateFormatter *)accessibilityFormatter; 270 | { 271 | if (!_accessibilityFormatter) { 272 | _accessibilityFormatter = [NSDateFormatter new]; 273 | _accessibilityFormatter.calendar = self.calendar; 274 | _accessibilityFormatter.dateStyle = NSDateFormatterLongStyle; 275 | } 276 | return _accessibilityFormatter; 277 | } 278 | 279 | - (NSInteger)monthOfBeginningDate; 280 | { 281 | if (!_monthOfBeginningDate) { 282 | _monthOfBeginningDate = [self.calendar components:NSMonthCalendarUnit fromDate:self.firstOfMonth].month; 283 | } 284 | return _monthOfBeginningDate; 285 | } 286 | 287 | - (void)setFirstOfMonth:(NSDate *)firstOfMonth; 288 | { 289 | [super setFirstOfMonth:firstOfMonth]; 290 | self.monthOfBeginningDate = 0; 291 | } 292 | 293 | - (NSDateComponents *)todayDateComponents; 294 | { 295 | if (!_todayDateComponents) { 296 | self.todayDateComponents = [self.calendar components:NSDayCalendarUnit|NSMonthCalendarUnit|NSYearCalendarUnit fromDate:[NSDate date]]; 297 | } 298 | return _todayDateComponents; 299 | } 300 | 301 | @end 302 | -------------------------------------------------------------------------------- /TimesSquare/TSQCalendarView.m: -------------------------------------------------------------------------------- 1 | // 2 | // TSQCalendarState.m 3 | // TimesSquare 4 | // 5 | // Created by Jim Puls on 11/14/12. 6 | // Licensed to Square, Inc. under one or more contributor license agreements. 7 | // See the LICENSE file distributed with this work for the terms under 8 | // which Square, Inc. licenses this file to you. 9 | 10 | #import "TSQCalendarView.h" 11 | #import "TSQCalendarMonthHeaderCell.h" 12 | #import "TSQCalendarRowCell.h" 13 | 14 | @interface TSQCalendarView () 15 | 16 | @property (nonatomic, strong) UITableView *tableView; 17 | @property (nonatomic, strong) TSQCalendarMonthHeaderCell *headerView; // nil unless pinsHeaderToTop == YES 18 | 19 | @end 20 | 21 | 22 | @implementation TSQCalendarView 23 | 24 | - (id)initWithCoder:(NSCoder *)aDecoder; 25 | { 26 | self = [super initWithCoder:aDecoder]; 27 | if (!self) { 28 | return nil; 29 | } 30 | 31 | [self _TSQCalendarView_commonInit]; 32 | 33 | return self; 34 | } 35 | 36 | - (id)initWithFrame:(CGRect)frame; 37 | { 38 | self = [super initWithFrame:frame]; 39 | if (!self) { 40 | return nil; 41 | } 42 | 43 | [self _TSQCalendarView_commonInit]; 44 | 45 | return self; 46 | } 47 | 48 | - (void)_TSQCalendarView_commonInit; 49 | { 50 | _tableView = [[UITableView alloc] initWithFrame:self.bounds style:UITableViewStylePlain]; 51 | _tableView.dataSource = self; 52 | _tableView.delegate = self; 53 | _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; 54 | _tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth; 55 | [self addSubview:_tableView]; 56 | } 57 | 58 | - (void)dealloc; 59 | { 60 | _tableView.dataSource = nil; 61 | _tableView.delegate = nil; 62 | } 63 | 64 | - (NSCalendar *)calendar; 65 | { 66 | if (!_calendar) { 67 | self.calendar = [NSCalendar currentCalendar]; 68 | } 69 | return _calendar; 70 | } 71 | 72 | - (Class)headerCellClass; 73 | { 74 | if (!_headerCellClass) { 75 | self.headerCellClass = [TSQCalendarMonthHeaderCell class]; 76 | } 77 | return _headerCellClass; 78 | } 79 | 80 | - (Class)rowCellClass; 81 | { 82 | if (!_rowCellClass) { 83 | self.rowCellClass = [TSQCalendarRowCell class]; 84 | } 85 | return _rowCellClass; 86 | } 87 | 88 | - (Class)cellClassForRowAtIndexPath:(NSIndexPath *)indexPath; 89 | { 90 | if (indexPath.row == 0 && !self.pinsHeaderToTop) { 91 | return [self headerCellClass]; 92 | } else { 93 | return [self rowCellClass]; 94 | } 95 | } 96 | 97 | - (void)setBackgroundColor:(UIColor *)backgroundColor; 98 | { 99 | [super setBackgroundColor:backgroundColor]; 100 | [self.tableView setBackgroundColor:backgroundColor]; 101 | } 102 | 103 | - (void)setPinsHeaderToTop:(BOOL)pinsHeaderToTop; 104 | { 105 | _pinsHeaderToTop = pinsHeaderToTop; 106 | [self setNeedsLayout]; 107 | } 108 | 109 | - (void)setFirstDate:(NSDate *)firstDate; 110 | { 111 | // clamp to the beginning of its month 112 | _firstDate = [self clampDate:firstDate toComponents:NSMonthCalendarUnit|NSYearCalendarUnit]; 113 | } 114 | 115 | - (void)setLastDate:(NSDate *)lastDate; 116 | { 117 | // clamp to the end of its month 118 | NSDate *firstOfMonth = [self clampDate:lastDate toComponents:NSMonthCalendarUnit|NSYearCalendarUnit]; 119 | 120 | NSDateComponents *offsetComponents = [[NSDateComponents alloc] init]; 121 | offsetComponents.month = 1; 122 | offsetComponents.day = -1; 123 | _lastDate = [self.calendar dateByAddingComponents:offsetComponents toDate:firstOfMonth options:0]; 124 | } 125 | 126 | - (void)setSelectedDate:(NSDate *)newSelectedDate; 127 | { 128 | // clamp to beginning of its day 129 | NSDate *startOfDay = [self clampDate:newSelectedDate toComponents:NSDayCalendarUnit|NSMonthCalendarUnit|NSYearCalendarUnit]; 130 | 131 | if ([self.delegate respondsToSelector:@selector(calendarView:shouldSelectDate:)] && ![self.delegate calendarView:self shouldSelectDate:startOfDay]) { 132 | return; 133 | } 134 | 135 | [[self cellForRowAtDate:_selectedDate] selectColumnForDate:nil]; 136 | [[self cellForRowAtDate:startOfDay] selectColumnForDate:startOfDay]; 137 | NSIndexPath *newIndexPath = [self indexPathForRowAtDate:startOfDay]; 138 | CGRect newIndexPathRect = [self.tableView rectForRowAtIndexPath:newIndexPath]; 139 | CGRect scrollBounds = self.tableView.bounds; 140 | 141 | if (self.pagingEnabled) { 142 | CGRect sectionRect = [self.tableView rectForSection:newIndexPath.section]; 143 | [self.tableView setContentOffset:sectionRect.origin animated:YES]; 144 | } else { 145 | if (CGRectGetMinY(scrollBounds) > CGRectGetMinY(newIndexPathRect)) { 146 | [self.tableView scrollToRowAtIndexPath:newIndexPath atScrollPosition:UITableViewScrollPositionTop animated:YES]; 147 | } else if (CGRectGetMaxY(scrollBounds) < CGRectGetMaxY(newIndexPathRect)) { 148 | [self.tableView scrollToRowAtIndexPath:newIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES]; 149 | } 150 | } 151 | 152 | _selectedDate = startOfDay; 153 | 154 | if ([self.delegate respondsToSelector:@selector(calendarView:didSelectDate:)]) { 155 | [self.delegate calendarView:self didSelectDate:startOfDay]; 156 | } 157 | } 158 | 159 | - (void)scrollToDate:(NSDate *)date animated:(BOOL)animated 160 | { 161 | NSInteger section = [self sectionForDate:date]; 162 | [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:section] atScrollPosition:UITableViewScrollPositionTop animated:animated]; 163 | } 164 | 165 | 166 | 167 | - (void)scrollDate:(NSDate *)date toPosition:(UITableViewScrollPosition)position animated:(BOOL)animated { 168 | NSIndexPath *cellPath = [self indexPathForRowAtDate:date]; 169 | 170 | [self.tableView scrollToRowAtIndexPath:cellPath 171 | atScrollPosition:position 172 | animated:animated]; 173 | } 174 | 175 | 176 | 177 | - (TSQCalendarMonthHeaderCell *)makeHeaderCellWithIdentifier:(NSString *)identifier; 178 | { 179 | TSQCalendarMonthHeaderCell *cell = [[[self headerCellClass] alloc] initWithCalendar:self.calendar reuseIdentifier:identifier]; 180 | cell.backgroundColor = self.backgroundColor; 181 | cell.calendarView = self; 182 | return cell; 183 | } 184 | 185 | #pragma mark Calendar calculations 186 | 187 | - (NSDate *)firstOfMonthForSection:(NSInteger)section; 188 | { 189 | NSDateComponents *offset = [NSDateComponents new]; 190 | offset.month = section; 191 | return [self.calendar dateByAddingComponents:offset toDate:self.firstDate options:0]; 192 | } 193 | 194 | - (TSQCalendarRowCell *)cellForRowAtDate:(NSDate *)date; 195 | { 196 | return (TSQCalendarRowCell *)[self.tableView cellForRowAtIndexPath:[self indexPathForRowAtDate:date]]; 197 | } 198 | 199 | - (NSInteger)sectionForDate:(NSDate *)date; 200 | { 201 | return [self.calendar components:NSMonthCalendarUnit fromDate:self.firstDate toDate:date options:0].month; 202 | } 203 | 204 | - (NSIndexPath *)indexPathForRowAtDate:(NSDate *)date; 205 | { 206 | if (!date) { 207 | return nil; 208 | } 209 | 210 | NSInteger section = [self sectionForDate:date]; 211 | NSDate *firstOfMonth = [self firstOfMonthForSection:section]; 212 | 213 | NSInteger firstWeek = [self.calendar components:NSWeekOfMonthCalendarUnit fromDate:firstOfMonth].weekOfMonth; 214 | NSInteger targetWeek = [self.calendar components:NSWeekOfMonthCalendarUnit fromDate:date].weekOfMonth; 215 | 216 | return [NSIndexPath indexPathForRow:(self.pinsHeaderToTop ? 0 : 1) + targetWeek - firstWeek inSection:section]; 217 | } 218 | 219 | #pragma mark UIView 220 | 221 | - (void)layoutSubviews; 222 | { 223 | if (self.pinsHeaderToTop) { 224 | if (!self.headerView) { 225 | self.headerView = [self makeHeaderCellWithIdentifier:nil]; 226 | if (self.tableView.visibleCells.count > 0) { 227 | self.headerView.firstOfMonth = [self.tableView.visibleCells[0] firstOfMonth]; 228 | } else { 229 | self.headerView.firstOfMonth = self.firstDate; 230 | } 231 | [self addSubview:self.headerView]; 232 | } 233 | CGRect bounds = self.bounds; 234 | CGRect headerRect; 235 | CGRect tableRect; 236 | CGRectDivide(bounds, &headerRect, &tableRect, [[self headerCellClass] cellHeight], CGRectMinYEdge); 237 | self.headerView.frame = headerRect; 238 | self.tableView.frame = tableRect; 239 | } else { 240 | if (self.headerView) { 241 | [self.headerView removeFromSuperview]; 242 | self.headerView = nil; 243 | } 244 | self.tableView.frame = self.bounds; 245 | } 246 | } 247 | 248 | #pragma mark UITableViewDataSource 249 | 250 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; 251 | { 252 | return 1 + [self.calendar components:NSMonthCalendarUnit fromDate:self.firstDate toDate:self.lastDate options:0].month; 253 | } 254 | 255 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; 256 | { 257 | NSDate *firstOfMonth = [self firstOfMonthForSection:section]; 258 | NSRange rangeOfWeeks = [self.calendar rangeOfUnit:NSWeekCalendarUnit inUnit:NSMonthCalendarUnit forDate:firstOfMonth]; 259 | return (self.pinsHeaderToTop ? 0 : 1) + rangeOfWeeks.length; 260 | } 261 | 262 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; 263 | { 264 | if (indexPath.row == 0 && !self.pinsHeaderToTop) { 265 | // month header 266 | static NSString *identifier = @"header"; 267 | TSQCalendarMonthHeaderCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier]; 268 | if (!cell) { 269 | cell = [self makeHeaderCellWithIdentifier:identifier]; 270 | } 271 | return cell; 272 | } else { 273 | static NSString *identifier = @"row"; 274 | TSQCalendarRowCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier]; 275 | if (!cell) { 276 | cell = [[[self rowCellClass] alloc] initWithCalendar:self.calendar reuseIdentifier:identifier]; 277 | cell.backgroundColor = self.backgroundColor; 278 | cell.calendarView = self; 279 | } 280 | return cell; 281 | } 282 | } 283 | 284 | #pragma mark UITableViewDelegate 285 | 286 | - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; 287 | { 288 | NSDate *firstOfMonth = [self firstOfMonthForSection:indexPath.section]; 289 | [(TSQCalendarCell *)cell setFirstOfMonth:firstOfMonth]; 290 | if (indexPath.row > 0 || self.pinsHeaderToTop) { 291 | NSInteger ordinalityOfFirstDay = [self.calendar ordinalityOfUnit:NSDayCalendarUnit inUnit:NSWeekCalendarUnit forDate:firstOfMonth]; 292 | NSDateComponents *dateComponents = [NSDateComponents new]; 293 | dateComponents.day = 1 - ordinalityOfFirstDay; 294 | dateComponents.week = indexPath.row - (self.pinsHeaderToTop ? 0 : 1); 295 | [(TSQCalendarRowCell *)cell setBeginningDate:[self.calendar dateByAddingComponents:dateComponents toDate:firstOfMonth options:0]]; 296 | [(TSQCalendarRowCell *)cell selectColumnForDate:self.selectedDate]; 297 | 298 | BOOL isBottomRow = (indexPath.row == [self tableView:tableView numberOfRowsInSection:indexPath.section] - (self.pinsHeaderToTop ? 0 : 1)); 299 | [(TSQCalendarRowCell *)cell setBottomRow:isBottomRow]; 300 | } 301 | } 302 | 303 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath; 304 | { 305 | return [[self cellClassForRowAtIndexPath:indexPath] cellHeight]; 306 | } 307 | 308 | #pragma mark UIScrollViewDelegate 309 | 310 | - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset; 311 | { 312 | if (self.pagingEnabled) { 313 | NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:*targetContentOffset]; 314 | // If the target offset is at the third row or later, target the next month; otherwise, target the beginning of this month. 315 | NSInteger section = indexPath.section; 316 | if (indexPath.row > 2) { 317 | section++; 318 | } 319 | CGRect sectionRect = [self.tableView rectForSection:section]; 320 | *targetContentOffset = sectionRect.origin; 321 | } 322 | } 323 | 324 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView; 325 | { 326 | if (self.pinsHeaderToTop && self.tableView.visibleCells.count > 0) { 327 | TSQCalendarCell *cell = self.tableView.visibleCells[0]; 328 | self.headerView.firstOfMonth = cell.firstOfMonth; 329 | } 330 | } 331 | 332 | - (NSDate *)clampDate:(NSDate *)date toComponents:(NSUInteger)unitFlags 333 | { 334 | NSDateComponents *components = [self.calendar components:unitFlags fromDate:date]; 335 | return [self.calendar dateFromComponents:components]; 336 | } 337 | 338 | @end 339 | -------------------------------------------------------------------------------- /TimesSquare.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | A806805F16700FD70071C71E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A806805E16700FD70071C71E /* Foundation.framework */; }; 11 | A806808E167010030071C71E /* TSQCalendarCell.m in Sources */ = {isa = PBXBuildFile; fileRef = A8068087167010030071C71E /* TSQCalendarCell.m */; }; 12 | A8068090167010030071C71E /* TSQCalendarMonthHeaderCell.m in Sources */ = {isa = PBXBuildFile; fileRef = A8068089167010030071C71E /* TSQCalendarMonthHeaderCell.m */; }; 13 | A8068092167010030071C71E /* TSQCalendarRowCell.m in Sources */ = {isa = PBXBuildFile; fileRef = A806808B167010030071C71E /* TSQCalendarRowCell.m */; }; 14 | A8068094167010030071C71E /* TSQCalendarView.m in Sources */ = {isa = PBXBuildFile; fileRef = A806808D167010030071C71E /* TSQCalendarView.m */; }; 15 | A80B62AB1672720C00792DFE /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A806809E167012980071C71E /* CoreGraphics.framework */; }; 16 | EFD8DE6D167AF77B00F87FBE /* TimesSquare.h in Headers */ = {isa = PBXBuildFile; fileRef = A806806316700FD70071C71E /* TimesSquare.h */; settings = {ATTRIBUTES = (Public, ); }; }; 17 | EFD8DE6E167AF78100F87FBE /* TSQCalendarCell.h in Headers */ = {isa = PBXBuildFile; fileRef = A8068086167010030071C71E /* TSQCalendarCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; 18 | EFD8DE6F167AF78600F87FBE /* TSQCalendarMonthHeaderCell.h in Headers */ = {isa = PBXBuildFile; fileRef = A8068088167010030071C71E /* TSQCalendarMonthHeaderCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; 19 | EFD8DE70167AF78C00F87FBE /* TSQCalendarRowCell.h in Headers */ = {isa = PBXBuildFile; fileRef = A806808A167010030071C71E /* TSQCalendarRowCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; 20 | EFD8DE71167AF79000F87FBE /* TSQCalendarView.h in Headers */ = {isa = PBXBuildFile; fileRef = A806808C167010030071C71E /* TSQCalendarView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXCopyFilesBuildPhase section */ 24 | A806805916700FD70071C71E /* CopyFiles */ = { 25 | isa = PBXCopyFilesBuildPhase; 26 | buildActionMask = 2147483647; 27 | dstPath = "include/${PRODUCT_NAME}"; 28 | dstSubfolderSpec = 16; 29 | files = ( 30 | ); 31 | runOnlyForDeploymentPostprocessing = 0; 32 | }; 33 | /* End PBXCopyFilesBuildPhase section */ 34 | 35 | /* Begin PBXFileReference section */ 36 | A806805B16700FD70071C71E /* libTimesSquare.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libTimesSquare.a; sourceTree = BUILT_PRODUCTS_DIR; }; 37 | A806805E16700FD70071C71E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 38 | A806806216700FD70071C71E /* TimesSquare-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TimesSquare-Prefix.pch"; sourceTree = ""; }; 39 | A806806316700FD70071C71E /* TimesSquare.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TimesSquare.h; sourceTree = ""; }; 40 | A806806D16700FD80071C71E /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; 41 | A806806F16700FD80071C71E /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; 42 | A8068086167010030071C71E /* TSQCalendarCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSQCalendarCell.h; sourceTree = ""; }; 43 | A8068087167010030071C71E /* TSQCalendarCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSQCalendarCell.m; sourceTree = ""; }; 44 | A8068088167010030071C71E /* TSQCalendarMonthHeaderCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSQCalendarMonthHeaderCell.h; sourceTree = ""; }; 45 | A8068089167010030071C71E /* TSQCalendarMonthHeaderCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSQCalendarMonthHeaderCell.m; sourceTree = ""; }; 46 | A806808A167010030071C71E /* TSQCalendarRowCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSQCalendarRowCell.h; sourceTree = ""; }; 47 | A806808B167010030071C71E /* TSQCalendarRowCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSQCalendarRowCell.m; sourceTree = ""; }; 48 | A806808C167010030071C71E /* TSQCalendarView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSQCalendarView.h; sourceTree = ""; }; 49 | A806808D167010030071C71E /* TSQCalendarView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSQCalendarView.m; sourceTree = ""; }; 50 | A806809E167012980071C71E /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 51 | /* End PBXFileReference section */ 52 | 53 | /* Begin PBXFrameworksBuildPhase section */ 54 | A806805816700FD70071C71E /* Frameworks */ = { 55 | isa = PBXFrameworksBuildPhase; 56 | buildActionMask = 2147483647; 57 | files = ( 58 | A80B62AB1672720C00792DFE /* CoreGraphics.framework in Frameworks */, 59 | A806805F16700FD70071C71E /* Foundation.framework in Frameworks */, 60 | ); 61 | runOnlyForDeploymentPostprocessing = 0; 62 | }; 63 | /* End PBXFrameworksBuildPhase section */ 64 | 65 | /* Begin PBXGroup section */ 66 | A806805016700FD70071C71E = { 67 | isa = PBXGroup; 68 | children = ( 69 | A806806016700FD70071C71E /* TimesSquare */, 70 | A806805D16700FD70071C71E /* Frameworks */, 71 | A806805C16700FD70071C71E /* Products */, 72 | ); 73 | sourceTree = ""; 74 | }; 75 | A806805C16700FD70071C71E /* Products */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | A806805B16700FD70071C71E /* libTimesSquare.a */, 79 | ); 80 | name = Products; 81 | sourceTree = ""; 82 | }; 83 | A806805D16700FD70071C71E /* Frameworks */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | A806805E16700FD70071C71E /* Foundation.framework */, 87 | A806806D16700FD80071C71E /* SenTestingKit.framework */, 88 | A806806F16700FD80071C71E /* UIKit.framework */, 89 | A806809E167012980071C71E /* CoreGraphics.framework */, 90 | ); 91 | name = Frameworks; 92 | sourceTree = ""; 93 | }; 94 | A806806016700FD70071C71E /* TimesSquare */ = { 95 | isa = PBXGroup; 96 | children = ( 97 | A806806316700FD70071C71E /* TimesSquare.h */, 98 | A8068086167010030071C71E /* TSQCalendarCell.h */, 99 | A8068087167010030071C71E /* TSQCalendarCell.m */, 100 | A8068088167010030071C71E /* TSQCalendarMonthHeaderCell.h */, 101 | A8068089167010030071C71E /* TSQCalendarMonthHeaderCell.m */, 102 | A806808A167010030071C71E /* TSQCalendarRowCell.h */, 103 | A806808B167010030071C71E /* TSQCalendarRowCell.m */, 104 | A806808C167010030071C71E /* TSQCalendarView.h */, 105 | A806808D167010030071C71E /* TSQCalendarView.m */, 106 | A806806116700FD70071C71E /* Supporting Files */, 107 | ); 108 | path = TimesSquare; 109 | sourceTree = ""; 110 | }; 111 | A806806116700FD70071C71E /* Supporting Files */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | A806806216700FD70071C71E /* TimesSquare-Prefix.pch */, 115 | ); 116 | name = "Supporting Files"; 117 | sourceTree = ""; 118 | }; 119 | /* End PBXGroup section */ 120 | 121 | /* Begin PBXHeadersBuildPhase section */ 122 | EFD8DE6B167AF77100F87FBE /* Headers */ = { 123 | isa = PBXHeadersBuildPhase; 124 | buildActionMask = 2147483647; 125 | files = ( 126 | EFD8DE6D167AF77B00F87FBE /* TimesSquare.h in Headers */, 127 | EFD8DE6E167AF78100F87FBE /* TSQCalendarCell.h in Headers */, 128 | EFD8DE6F167AF78600F87FBE /* TSQCalendarMonthHeaderCell.h in Headers */, 129 | EFD8DE70167AF78C00F87FBE /* TSQCalendarRowCell.h in Headers */, 130 | EFD8DE71167AF79000F87FBE /* TSQCalendarView.h in Headers */, 131 | ); 132 | runOnlyForDeploymentPostprocessing = 0; 133 | }; 134 | /* End PBXHeadersBuildPhase section */ 135 | 136 | /* Begin PBXLegacyTarget section */ 137 | A81E05F71682A0E000E79A2B /* TimesSquare Documentation */ = { 138 | isa = PBXLegacyTarget; 139 | buildArgumentsString = "--exit-threshold 2 --logformat xcode --output /tmp/tsq-docs --project-name TimesSquare --project-version 1.0 --project-company \"Square, Inc.\" --company-id com.squareup --no-repeat-first-par --no-search-undocumented-doc TimesSquare/"; 140 | buildConfigurationList = A81E05F81682A0E000E79A2B /* Build configuration list for PBXLegacyTarget "TimesSquare Documentation" */; 141 | buildPhases = ( 142 | ); 143 | buildToolPath = /usr/local/bin/appledoc; 144 | buildWorkingDirectory = ""; 145 | dependencies = ( 146 | ); 147 | name = "TimesSquare Documentation"; 148 | passBuildSettingsInEnvironment = 0; 149 | productName = "TimesSquare Documentation"; 150 | }; 151 | /* End PBXLegacyTarget section */ 152 | 153 | /* Begin PBXNativeTarget section */ 154 | A806805A16700FD70071C71E /* TimesSquare */ = { 155 | isa = PBXNativeTarget; 156 | buildConfigurationList = A806808016700FD80071C71E /* Build configuration list for PBXNativeTarget "TimesSquare" */; 157 | buildPhases = ( 158 | EFD8DE6B167AF77100F87FBE /* Headers */, 159 | A806805716700FD70071C71E /* Sources */, 160 | A806805816700FD70071C71E /* Frameworks */, 161 | A806805916700FD70071C71E /* CopyFiles */, 162 | ); 163 | buildRules = ( 164 | ); 165 | dependencies = ( 166 | ); 167 | name = TimesSquare; 168 | productName = PonyDate; 169 | productReference = A806805B16700FD70071C71E /* libTimesSquare.a */; 170 | productType = "com.apple.product-type.library.static"; 171 | }; 172 | /* End PBXNativeTarget section */ 173 | 174 | /* Begin PBXProject section */ 175 | A806805216700FD70071C71E /* Project object */ = { 176 | isa = PBXProject; 177 | attributes = { 178 | LastUpgradeCheck = 0640; 179 | ORGANIZATIONNAME = Square; 180 | }; 181 | buildConfigurationList = A806805516700FD70071C71E /* Build configuration list for PBXProject "TimesSquare" */; 182 | compatibilityVersion = "Xcode 3.2"; 183 | developmentRegion = English; 184 | hasScannedForEncodings = 0; 185 | knownRegions = ( 186 | en, 187 | ); 188 | mainGroup = A806805016700FD70071C71E; 189 | productRefGroup = A806805C16700FD70071C71E /* Products */; 190 | projectDirPath = ""; 191 | projectRoot = ""; 192 | targets = ( 193 | A806805A16700FD70071C71E /* TimesSquare */, 194 | A81E05F71682A0E000E79A2B /* TimesSquare Documentation */, 195 | ); 196 | }; 197 | /* End PBXProject section */ 198 | 199 | /* Begin PBXSourcesBuildPhase section */ 200 | A806805716700FD70071C71E /* Sources */ = { 201 | isa = PBXSourcesBuildPhase; 202 | buildActionMask = 2147483647; 203 | files = ( 204 | A806808E167010030071C71E /* TSQCalendarCell.m in Sources */, 205 | A8068090167010030071C71E /* TSQCalendarMonthHeaderCell.m in Sources */, 206 | A8068092167010030071C71E /* TSQCalendarRowCell.m in Sources */, 207 | A8068094167010030071C71E /* TSQCalendarView.m in Sources */, 208 | ); 209 | runOnlyForDeploymentPostprocessing = 0; 210 | }; 211 | /* End PBXSourcesBuildPhase section */ 212 | 213 | /* Begin XCBuildConfiguration section */ 214 | A806807E16700FD80071C71E /* Debug */ = { 215 | isa = XCBuildConfiguration; 216 | buildSettings = { 217 | ALWAYS_SEARCH_USER_PATHS = NO; 218 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 219 | CLANG_CXX_LIBRARY = "libc++"; 220 | CLANG_WARN_EMPTY_BODY = YES; 221 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 222 | COPY_PHASE_STRIP = NO; 223 | GCC_C_LANGUAGE_STANDARD = gnu99; 224 | GCC_DYNAMIC_NO_PIC = NO; 225 | GCC_OPTIMIZATION_LEVEL = 0; 226 | GCC_PREPROCESSOR_DEFINITIONS = ( 227 | "DEBUG=1", 228 | "$(inherited)", 229 | ); 230 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 231 | GCC_TREAT_WARNINGS_AS_ERRORS = YES; 232 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 233 | GCC_WARN_PEDANTIC = YES; 234 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 235 | GCC_WARN_UNUSED_VARIABLE = YES; 236 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 237 | ONLY_ACTIVE_ARCH = YES; 238 | PUBLIC_HEADERS_FOLDER_PATH = "include/$(PRODUCT_NAME)"; 239 | RUN_CLANG_STATIC_ANALYZER = YES; 240 | SDKROOT = iphoneos; 241 | }; 242 | name = Debug; 243 | }; 244 | A806807F16700FD80071C71E /* Release */ = { 245 | isa = XCBuildConfiguration; 246 | buildSettings = { 247 | ALWAYS_SEARCH_USER_PATHS = NO; 248 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 249 | CLANG_CXX_LIBRARY = "libc++"; 250 | CLANG_WARN_EMPTY_BODY = YES; 251 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 252 | COPY_PHASE_STRIP = YES; 253 | GCC_C_LANGUAGE_STANDARD = gnu99; 254 | GCC_TREAT_WARNINGS_AS_ERRORS = YES; 255 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 256 | GCC_WARN_PEDANTIC = YES; 257 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 258 | GCC_WARN_UNUSED_VARIABLE = YES; 259 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 260 | PUBLIC_HEADERS_FOLDER_PATH = "include/$(PRODUCT_NAME)"; 261 | RUN_CLANG_STATIC_ANALYZER = YES; 262 | SDKROOT = iphoneos; 263 | VALIDATE_PRODUCT = YES; 264 | }; 265 | name = Release; 266 | }; 267 | A806808116700FD80071C71E /* Debug */ = { 268 | isa = XCBuildConfiguration; 269 | buildSettings = { 270 | CLANG_ENABLE_OBJC_ARC = YES; 271 | DSTROOT = /tmp/TimesSquare.dst; 272 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 273 | GCC_PREFIX_HEADER = "TimesSquare/TimesSquare-Prefix.pch"; 274 | OTHER_LDFLAGS = "-ObjC"; 275 | PRODUCT_NAME = "$(TARGET_NAME)"; 276 | SKIP_INSTALL = YES; 277 | }; 278 | name = Debug; 279 | }; 280 | A806808216700FD80071C71E /* Release */ = { 281 | isa = XCBuildConfiguration; 282 | buildSettings = { 283 | CLANG_ENABLE_OBJC_ARC = YES; 284 | DSTROOT = /tmp/TimesSquare.dst; 285 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 286 | GCC_PREFIX_HEADER = "TimesSquare/TimesSquare-Prefix.pch"; 287 | OTHER_LDFLAGS = "-ObjC"; 288 | PRODUCT_NAME = "$(TARGET_NAME)"; 289 | SKIP_INSTALL = YES; 290 | }; 291 | name = Release; 292 | }; 293 | A81E05F91682A0E000E79A2B /* Debug */ = { 294 | isa = XCBuildConfiguration; 295 | buildSettings = { 296 | DEBUGGING_SYMBOLS = YES; 297 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 298 | GCC_GENERATE_DEBUGGING_SYMBOLS = YES; 299 | GCC_OPTIMIZATION_LEVEL = 0; 300 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 301 | MACOSX_DEPLOYMENT_TARGET = 10.8; 302 | OTHER_CFLAGS = ""; 303 | OTHER_LDFLAGS = ""; 304 | PRODUCT_NAME = "$(TARGET_NAME)"; 305 | SDKROOT = macosx; 306 | }; 307 | name = Debug; 308 | }; 309 | A81E05FA1682A0E000E79A2B /* Release */ = { 310 | isa = XCBuildConfiguration; 311 | buildSettings = { 312 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 313 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 314 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 315 | MACOSX_DEPLOYMENT_TARGET = 10.8; 316 | OTHER_CFLAGS = ""; 317 | OTHER_LDFLAGS = ""; 318 | PRODUCT_NAME = "$(TARGET_NAME)"; 319 | SDKROOT = macosx; 320 | }; 321 | name = Release; 322 | }; 323 | /* End XCBuildConfiguration section */ 324 | 325 | /* Begin XCConfigurationList section */ 326 | A806805516700FD70071C71E /* Build configuration list for PBXProject "TimesSquare" */ = { 327 | isa = XCConfigurationList; 328 | buildConfigurations = ( 329 | A806807E16700FD80071C71E /* Debug */, 330 | A806807F16700FD80071C71E /* Release */, 331 | ); 332 | defaultConfigurationIsVisible = 0; 333 | defaultConfigurationName = Release; 334 | }; 335 | A806808016700FD80071C71E /* Build configuration list for PBXNativeTarget "TimesSquare" */ = { 336 | isa = XCConfigurationList; 337 | buildConfigurations = ( 338 | A806808116700FD80071C71E /* Debug */, 339 | A806808216700FD80071C71E /* Release */, 340 | ); 341 | defaultConfigurationIsVisible = 0; 342 | defaultConfigurationName = Release; 343 | }; 344 | A81E05F81682A0E000E79A2B /* Build configuration list for PBXLegacyTarget "TimesSquare Documentation" */ = { 345 | isa = XCConfigurationList; 346 | buildConfigurations = ( 347 | A81E05F91682A0E000E79A2B /* Debug */, 348 | A81E05FA1682A0E000E79A2B /* Release */, 349 | ); 350 | defaultConfigurationIsVisible = 0; 351 | defaultConfigurationName = Release; 352 | }; 353 | /* End XCConfigurationList section */ 354 | }; 355 | rootObject = A806805216700FD70071C71E /* Project object */; 356 | } 357 | -------------------------------------------------------------------------------- /TimesSquareTestApp/TimesSquareTestApp.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | A885A9771694FCDD00CA6E1B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A885A9761694FCDD00CA6E1B /* UIKit.framework */; }; 11 | A885A9791694FCDD00CA6E1B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A885A9781694FCDD00CA6E1B /* Foundation.framework */; }; 12 | A885A97B1694FCDD00CA6E1B /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A885A97A1694FCDD00CA6E1B /* CoreGraphics.framework */; }; 13 | A885A9951694FCDD00CA6E1B /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A885A9941694FCDD00CA6E1B /* SenTestingKit.framework */; }; 14 | A885A9961694FCDD00CA6E1B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A885A9761694FCDD00CA6E1B /* UIKit.framework */; }; 15 | A885A9971694FCDD00CA6E1B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A885A9781694FCDD00CA6E1B /* Foundation.framework */; }; 16 | A885A99F1694FCDD00CA6E1B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A885A99D1694FCDD00CA6E1B /* InfoPlist.strings */; }; 17 | A885A9A21694FCDD00CA6E1B /* TimesSquareTestAppTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A885A9A11694FCDD00CA6E1B /* TimesSquareTestAppTests.m */; }; 18 | A885A9B61694FD5400CA6E1B /* TSQTAAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = A885A9681694FC8A00CA6E1B /* TSQTAAppDelegate.m */; }; 19 | A885A9B81694FD5400CA6E1B /* TSQTACalendarRowCell.m in Sources */ = {isa = PBXBuildFile; fileRef = A885A96A1694FC8A00CA6E1B /* TSQTACalendarRowCell.m */; }; 20 | A885A9BA1694FD5400CA6E1B /* TSQTAViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A885A96C1694FC8A00CA6E1B /* TSQTAViewController.m */; }; 21 | A885A9BB1694FDE000CA6E1B /* CalendarPreviousMonth.png in Resources */ = {isa = PBXBuildFile; fileRef = A885A9541694FC8A00CA6E1B /* CalendarPreviousMonth.png */; }; 22 | A885A9BC1694FDE000CA6E1B /* CalendarPreviousMonth@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = A885A9551694FC8A00CA6E1B /* CalendarPreviousMonth@2x.png */; }; 23 | A885A9BD1694FDE000CA6E1B /* CalendarRow.png in Resources */ = {isa = PBXBuildFile; fileRef = A885A9561694FC8A00CA6E1B /* CalendarRow.png */; }; 24 | A885A9BE1694FDE000CA6E1B /* CalendarRow@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = A885A9571694FC8A00CA6E1B /* CalendarRow@2x.png */; }; 25 | A885A9BF1694FDE000CA6E1B /* CalendarRowBottom.png in Resources */ = {isa = PBXBuildFile; fileRef = A885A9581694FC8A00CA6E1B /* CalendarRowBottom.png */; }; 26 | A885A9C01694FDE000CA6E1B /* CalendarRowBottom@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = A885A9591694FC8A00CA6E1B /* CalendarRowBottom@2x.png */; }; 27 | A885A9C11694FDE000CA6E1B /* CalendarSelectedDate.png in Resources */ = {isa = PBXBuildFile; fileRef = A885A95A1694FC8A00CA6E1B /* CalendarSelectedDate.png */; }; 28 | A885A9C21694FDE000CA6E1B /* CalendarSelectedDate@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = A885A95B1694FC8A00CA6E1B /* CalendarSelectedDate@2x.png */; }; 29 | A885A9C31694FDE000CA6E1B /* CalendarTodaysDate.png in Resources */ = {isa = PBXBuildFile; fileRef = A885A95C1694FC8A00CA6E1B /* CalendarTodaysDate.png */; }; 30 | A885A9C41694FDE000CA6E1B /* CalendarTodaysDate@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = A885A95D1694FC8A00CA6E1B /* CalendarTodaysDate@2x.png */; }; 31 | A885A9C51694FDE000CA6E1B /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = A885A95E1694FC8A00CA6E1B /* Default-568h@2x.png */; }; 32 | A885A9C61694FDE000CA6E1B /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = A885A95F1694FC8A00CA6E1B /* Default.png */; }; 33 | A885A9C71694FDE000CA6E1B /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = A885A9601694FC8A00CA6E1B /* Default@2x.png */; }; 34 | A885A9C81694FDE400CA6E1B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A885A9621694FC8A00CA6E1B /* InfoPlist.strings */; }; 35 | A885A9C91694FEDA00CA6E1B /* libTimesSquare.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A885A9B21694FD3900CA6E1B /* libTimesSquare.a */; }; 36 | A885AA841695023500CA6E1B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = A885A9641694FC8A00CA6E1B /* main.m */; }; 37 | /* End PBXBuildFile section */ 38 | 39 | /* Begin PBXContainerItemProxy section */ 40 | A885A9981694FCDD00CA6E1B /* PBXContainerItemProxy */ = { 41 | isa = PBXContainerItemProxy; 42 | containerPortal = A885A9481694FC4500CA6E1B /* Project object */; 43 | proxyType = 1; 44 | remoteGlobalIDString = A885A9721694FCDD00CA6E1B; 45 | remoteInfo = TimesSquareTestApp; 46 | }; 47 | A885A9B11694FD3900CA6E1B /* PBXContainerItemProxy */ = { 48 | isa = PBXContainerItemProxy; 49 | containerPortal = A885A9A91694FD3900CA6E1B /* TimesSquare.xcodeproj */; 50 | proxyType = 2; 51 | remoteGlobalIDString = A806805B16700FD70071C71E; 52 | remoteInfo = TimesSquare; 53 | }; 54 | A885A9B31694FD4700CA6E1B /* PBXContainerItemProxy */ = { 55 | isa = PBXContainerItemProxy; 56 | containerPortal = A885A9A91694FD3900CA6E1B /* TimesSquare.xcodeproj */; 57 | proxyType = 1; 58 | remoteGlobalIDString = A806805A16700FD70071C71E; 59 | remoteInfo = TimesSquare; 60 | }; 61 | /* End PBXContainerItemProxy section */ 62 | 63 | /* Begin PBXFileReference section */ 64 | A885A9541694FC8A00CA6E1B /* CalendarPreviousMonth.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = CalendarPreviousMonth.png; sourceTree = ""; }; 65 | A885A9551694FC8A00CA6E1B /* CalendarPreviousMonth@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "CalendarPreviousMonth@2x.png"; sourceTree = ""; }; 66 | A885A9561694FC8A00CA6E1B /* CalendarRow.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = CalendarRow.png; sourceTree = ""; }; 67 | A885A9571694FC8A00CA6E1B /* CalendarRow@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "CalendarRow@2x.png"; sourceTree = ""; }; 68 | A885A9581694FC8A00CA6E1B /* CalendarRowBottom.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = CalendarRowBottom.png; sourceTree = ""; }; 69 | A885A9591694FC8A00CA6E1B /* CalendarRowBottom@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "CalendarRowBottom@2x.png"; sourceTree = ""; }; 70 | A885A95A1694FC8A00CA6E1B /* CalendarSelectedDate.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = CalendarSelectedDate.png; sourceTree = ""; }; 71 | A885A95B1694FC8A00CA6E1B /* CalendarSelectedDate@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "CalendarSelectedDate@2x.png"; sourceTree = ""; }; 72 | A885A95C1694FC8A00CA6E1B /* CalendarTodaysDate.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = CalendarTodaysDate.png; sourceTree = ""; }; 73 | A885A95D1694FC8A00CA6E1B /* CalendarTodaysDate@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "CalendarTodaysDate@2x.png"; sourceTree = ""; }; 74 | A885A95E1694FC8A00CA6E1B /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 75 | A885A95F1694FC8A00CA6E1B /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; 76 | A885A9601694FC8A00CA6E1B /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; 77 | A885A9631694FC8A00CA6E1B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = InfoPlist.strings; sourceTree = ""; }; 78 | A885A9641694FC8A00CA6E1B /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 79 | A885A9651694FC8A00CA6E1B /* TimesSquareTestApp-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "TimesSquareTestApp-Info.plist"; sourceTree = ""; }; 80 | A885A9661694FC8A00CA6E1B /* TimesSquareTestApp-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TimesSquareTestApp-Prefix.pch"; sourceTree = ""; }; 81 | A885A9671694FC8A00CA6E1B /* TSQTAAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TSQTAAppDelegate.h; sourceTree = ""; }; 82 | A885A9681694FC8A00CA6E1B /* TSQTAAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TSQTAAppDelegate.m; sourceTree = ""; }; 83 | A885A9691694FC8A00CA6E1B /* TSQTACalendarRowCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TSQTACalendarRowCell.h; sourceTree = ""; }; 84 | A885A96A1694FC8A00CA6E1B /* TSQTACalendarRowCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TSQTACalendarRowCell.m; sourceTree = ""; }; 85 | A885A96B1694FC8A00CA6E1B /* TSQTAViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TSQTAViewController.h; sourceTree = ""; }; 86 | A885A96C1694FC8A00CA6E1B /* TSQTAViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TSQTAViewController.m; sourceTree = ""; }; 87 | A885A9731694FCDD00CA6E1B /* TimesSquareTestApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TimesSquareTestApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 88 | A885A9761694FCDD00CA6E1B /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; 89 | A885A9781694FCDD00CA6E1B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 90 | A885A97A1694FCDD00CA6E1B /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; }; 91 | A885A9931694FCDD00CA6E1B /* TimesSquareTestAppTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TimesSquareTestAppTests.octest; sourceTree = BUILT_PRODUCTS_DIR; }; 92 | A885A9941694FCDD00CA6E1B /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; 93 | A885A99C1694FCDD00CA6E1B /* TimesSquareTestAppTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "TimesSquareTestAppTests-Info.plist"; sourceTree = ""; }; 94 | A885A99E1694FCDD00CA6E1B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 95 | A885A9A01694FCDD00CA6E1B /* TimesSquareTestAppTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TimesSquareTestAppTests.h; sourceTree = ""; }; 96 | A885A9A11694FCDD00CA6E1B /* TimesSquareTestAppTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TimesSquareTestAppTests.m; sourceTree = ""; }; 97 | A885A9A91694FD3900CA6E1B /* TimesSquare.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = TimesSquare.xcodeproj; path = ../TimesSquare.xcodeproj; sourceTree = ""; }; 98 | /* End PBXFileReference section */ 99 | 100 | /* Begin PBXFrameworksBuildPhase section */ 101 | A885A9701694FCDD00CA6E1B /* Frameworks */ = { 102 | isa = PBXFrameworksBuildPhase; 103 | buildActionMask = 2147483647; 104 | files = ( 105 | A885A9C91694FEDA00CA6E1B /* libTimesSquare.a in Frameworks */, 106 | A885A9771694FCDD00CA6E1B /* UIKit.framework in Frameworks */, 107 | A885A9791694FCDD00CA6E1B /* Foundation.framework in Frameworks */, 108 | A885A97B1694FCDD00CA6E1B /* CoreGraphics.framework in Frameworks */, 109 | ); 110 | runOnlyForDeploymentPostprocessing = 0; 111 | }; 112 | A885A98F1694FCDD00CA6E1B /* Frameworks */ = { 113 | isa = PBXFrameworksBuildPhase; 114 | buildActionMask = 2147483647; 115 | files = ( 116 | A885A9951694FCDD00CA6E1B /* SenTestingKit.framework in Frameworks */, 117 | A885A9961694FCDD00CA6E1B /* UIKit.framework in Frameworks */, 118 | A885A9971694FCDD00CA6E1B /* Foundation.framework in Frameworks */, 119 | ); 120 | runOnlyForDeploymentPostprocessing = 0; 121 | }; 122 | /* End PBXFrameworksBuildPhase section */ 123 | 124 | /* Begin PBXGroup section */ 125 | A885A9461694FC4500CA6E1B = { 126 | isa = PBXGroup; 127 | children = ( 128 | A885A9521694FC7100CA6E1B /* App */, 129 | A885A99A1694FCDD00CA6E1B /* Tests */, 130 | A885A96E1694FCC000CA6E1B /* Frameworks */, 131 | A885A9741694FCDD00CA6E1B /* Products */, 132 | ); 133 | sourceTree = ""; 134 | }; 135 | A885A9521694FC7100CA6E1B /* App */ = { 136 | isa = PBXGroup; 137 | children = ( 138 | A885A96D1694FCA700CA6E1B /* Resources */, 139 | A885A9641694FC8A00CA6E1B /* main.m */, 140 | A885A9651694FC8A00CA6E1B /* TimesSquareTestApp-Info.plist */, 141 | A885A9661694FC8A00CA6E1B /* TimesSquareTestApp-Prefix.pch */, 142 | A885A9671694FC8A00CA6E1B /* TSQTAAppDelegate.h */, 143 | A885A9681694FC8A00CA6E1B /* TSQTAAppDelegate.m */, 144 | A885A9691694FC8A00CA6E1B /* TSQTACalendarRowCell.h */, 145 | A885A96A1694FC8A00CA6E1B /* TSQTACalendarRowCell.m */, 146 | A885A96B1694FC8A00CA6E1B /* TSQTAViewController.h */, 147 | A885A96C1694FC8A00CA6E1B /* TSQTAViewController.m */, 148 | ); 149 | name = App; 150 | sourceTree = SOURCE_ROOT; 151 | }; 152 | A885A96D1694FCA700CA6E1B /* Resources */ = { 153 | isa = PBXGroup; 154 | children = ( 155 | A885A9621694FC8A00CA6E1B /* InfoPlist.strings */, 156 | A885A9541694FC8A00CA6E1B /* CalendarPreviousMonth.png */, 157 | A885A9551694FC8A00CA6E1B /* CalendarPreviousMonth@2x.png */, 158 | A885A9561694FC8A00CA6E1B /* CalendarRow.png */, 159 | A885A9571694FC8A00CA6E1B /* CalendarRow@2x.png */, 160 | A885A9581694FC8A00CA6E1B /* CalendarRowBottom.png */, 161 | A885A9591694FC8A00CA6E1B /* CalendarRowBottom@2x.png */, 162 | A885A95A1694FC8A00CA6E1B /* CalendarSelectedDate.png */, 163 | A885A95B1694FC8A00CA6E1B /* CalendarSelectedDate@2x.png */, 164 | A885A95C1694FC8A00CA6E1B /* CalendarTodaysDate.png */, 165 | A885A95D1694FC8A00CA6E1B /* CalendarTodaysDate@2x.png */, 166 | A885A95E1694FC8A00CA6E1B /* Default-568h@2x.png */, 167 | A885A95F1694FC8A00CA6E1B /* Default.png */, 168 | A885A9601694FC8A00CA6E1B /* Default@2x.png */, 169 | ); 170 | name = Resources; 171 | sourceTree = ""; 172 | }; 173 | A885A96E1694FCC000CA6E1B /* Frameworks */ = { 174 | isa = PBXGroup; 175 | children = ( 176 | A885A9A91694FD3900CA6E1B /* TimesSquare.xcodeproj */, 177 | A885A9761694FCDD00CA6E1B /* UIKit.framework */, 178 | A885A9781694FCDD00CA6E1B /* Foundation.framework */, 179 | A885A97A1694FCDD00CA6E1B /* CoreGraphics.framework */, 180 | A885A9941694FCDD00CA6E1B /* SenTestingKit.framework */, 181 | ); 182 | name = Frameworks; 183 | sourceTree = ""; 184 | }; 185 | A885A9741694FCDD00CA6E1B /* Products */ = { 186 | isa = PBXGroup; 187 | children = ( 188 | A885A9731694FCDD00CA6E1B /* TimesSquareTestApp.app */, 189 | A885A9931694FCDD00CA6E1B /* TimesSquareTestAppTests.octest */, 190 | ); 191 | name = Products; 192 | sourceTree = ""; 193 | }; 194 | A885A99A1694FCDD00CA6E1B /* Tests */ = { 195 | isa = PBXGroup; 196 | children = ( 197 | A885A9A01694FCDD00CA6E1B /* TimesSquareTestAppTests.h */, 198 | A885A9A11694FCDD00CA6E1B /* TimesSquareTestAppTests.m */, 199 | A885A99B1694FCDD00CA6E1B /* Supporting Files */, 200 | ); 201 | name = Tests; 202 | path = TimesSquareTestAppTests; 203 | sourceTree = ""; 204 | }; 205 | A885A99B1694FCDD00CA6E1B /* Supporting Files */ = { 206 | isa = PBXGroup; 207 | children = ( 208 | A885A99C1694FCDD00CA6E1B /* TimesSquareTestAppTests-Info.plist */, 209 | A885A99D1694FCDD00CA6E1B /* InfoPlist.strings */, 210 | ); 211 | name = "Supporting Files"; 212 | sourceTree = ""; 213 | }; 214 | A885A9AA1694FD3900CA6E1B /* Products */ = { 215 | isa = PBXGroup; 216 | children = ( 217 | A885A9B21694FD3900CA6E1B /* libTimesSquare.a */, 218 | ); 219 | name = Products; 220 | sourceTree = ""; 221 | }; 222 | /* End PBXGroup section */ 223 | 224 | /* Begin PBXNativeTarget section */ 225 | A885A9721694FCDD00CA6E1B /* TimesSquareTestApp */ = { 226 | isa = PBXNativeTarget; 227 | buildConfigurationList = A885A9A31694FCDD00CA6E1B /* Build configuration list for PBXNativeTarget "TimesSquareTestApp" */; 228 | buildPhases = ( 229 | A885A96F1694FCDD00CA6E1B /* Sources */, 230 | A885A9701694FCDD00CA6E1B /* Frameworks */, 231 | A885A9711694FCDD00CA6E1B /* Resources */, 232 | ); 233 | buildRules = ( 234 | ); 235 | dependencies = ( 236 | A885A9B41694FD4700CA6E1B /* PBXTargetDependency */, 237 | ); 238 | name = TimesSquareTestApp; 239 | productName = TimesSquareTestApp; 240 | productReference = A885A9731694FCDD00CA6E1B /* TimesSquareTestApp.app */; 241 | productType = "com.apple.product-type.application"; 242 | }; 243 | A885A9921694FCDD00CA6E1B /* TimesSquareTestAppTests */ = { 244 | isa = PBXNativeTarget; 245 | buildConfigurationList = A885A9A61694FCDD00CA6E1B /* Build configuration list for PBXNativeTarget "TimesSquareTestAppTests" */; 246 | buildPhases = ( 247 | A885A98E1694FCDD00CA6E1B /* Sources */, 248 | A885A98F1694FCDD00CA6E1B /* Frameworks */, 249 | A885A9901694FCDD00CA6E1B /* Resources */, 250 | A885A9911694FCDD00CA6E1B /* ShellScript */, 251 | ); 252 | buildRules = ( 253 | ); 254 | dependencies = ( 255 | A885A9991694FCDD00CA6E1B /* PBXTargetDependency */, 256 | ); 257 | name = TimesSquareTestAppTests; 258 | productName = TimesSquareTestAppTests; 259 | productReference = A885A9931694FCDD00CA6E1B /* TimesSquareTestAppTests.octest */; 260 | productType = "com.apple.product-type.bundle"; 261 | }; 262 | /* End PBXNativeTarget section */ 263 | 264 | /* Begin PBXProject section */ 265 | A885A9481694FC4500CA6E1B /* Project object */ = { 266 | isa = PBXProject; 267 | attributes = { 268 | LastTestingUpgradeCheck = 0510; 269 | LastUpgradeCheck = 0510; 270 | }; 271 | buildConfigurationList = A885A94B1694FC4500CA6E1B /* Build configuration list for PBXProject "TimesSquareTestApp" */; 272 | compatibilityVersion = "Xcode 3.2"; 273 | developmentRegion = English; 274 | hasScannedForEncodings = 0; 275 | knownRegions = ( 276 | en, 277 | ); 278 | mainGroup = A885A9461694FC4500CA6E1B; 279 | productRefGroup = A885A9741694FCDD00CA6E1B /* Products */; 280 | projectDirPath = ""; 281 | projectReferences = ( 282 | { 283 | ProductGroup = A885A9AA1694FD3900CA6E1B /* Products */; 284 | ProjectRef = A885A9A91694FD3900CA6E1B /* TimesSquare.xcodeproj */; 285 | }, 286 | ); 287 | projectRoot = ""; 288 | targets = ( 289 | A885A9721694FCDD00CA6E1B /* TimesSquareTestApp */, 290 | A885A9921694FCDD00CA6E1B /* TimesSquareTestAppTests */, 291 | ); 292 | }; 293 | /* End PBXProject section */ 294 | 295 | /* Begin PBXReferenceProxy section */ 296 | A885A9B21694FD3900CA6E1B /* libTimesSquare.a */ = { 297 | isa = PBXReferenceProxy; 298 | fileType = archive.ar; 299 | path = libTimesSquare.a; 300 | remoteRef = A885A9B11694FD3900CA6E1B /* PBXContainerItemProxy */; 301 | sourceTree = BUILT_PRODUCTS_DIR; 302 | }; 303 | /* End PBXReferenceProxy section */ 304 | 305 | /* Begin PBXResourcesBuildPhase section */ 306 | A885A9711694FCDD00CA6E1B /* Resources */ = { 307 | isa = PBXResourcesBuildPhase; 308 | buildActionMask = 2147483647; 309 | files = ( 310 | A885A9BB1694FDE000CA6E1B /* CalendarPreviousMonth.png in Resources */, 311 | A885A9BC1694FDE000CA6E1B /* CalendarPreviousMonth@2x.png in Resources */, 312 | A885A9BD1694FDE000CA6E1B /* CalendarRow.png in Resources */, 313 | A885A9BE1694FDE000CA6E1B /* CalendarRow@2x.png in Resources */, 314 | A885A9BF1694FDE000CA6E1B /* CalendarRowBottom.png in Resources */, 315 | A885A9C01694FDE000CA6E1B /* CalendarRowBottom@2x.png in Resources */, 316 | A885A9C11694FDE000CA6E1B /* CalendarSelectedDate.png in Resources */, 317 | A885A9C21694FDE000CA6E1B /* CalendarSelectedDate@2x.png in Resources */, 318 | A885A9C31694FDE000CA6E1B /* CalendarTodaysDate.png in Resources */, 319 | A885A9C41694FDE000CA6E1B /* CalendarTodaysDate@2x.png in Resources */, 320 | A885A9C51694FDE000CA6E1B /* Default-568h@2x.png in Resources */, 321 | A885A9C61694FDE000CA6E1B /* Default.png in Resources */, 322 | A885A9C71694FDE000CA6E1B /* Default@2x.png in Resources */, 323 | A885A9C81694FDE400CA6E1B /* InfoPlist.strings in Resources */, 324 | ); 325 | runOnlyForDeploymentPostprocessing = 0; 326 | }; 327 | A885A9901694FCDD00CA6E1B /* Resources */ = { 328 | isa = PBXResourcesBuildPhase; 329 | buildActionMask = 2147483647; 330 | files = ( 331 | A885A99F1694FCDD00CA6E1B /* InfoPlist.strings in Resources */, 332 | ); 333 | runOnlyForDeploymentPostprocessing = 0; 334 | }; 335 | /* End PBXResourcesBuildPhase section */ 336 | 337 | /* Begin PBXShellScriptBuildPhase section */ 338 | A885A9911694FCDD00CA6E1B /* ShellScript */ = { 339 | isa = PBXShellScriptBuildPhase; 340 | buildActionMask = 2147483647; 341 | files = ( 342 | ); 343 | inputPaths = ( 344 | ); 345 | outputPaths = ( 346 | ); 347 | runOnlyForDeploymentPostprocessing = 0; 348 | shellPath = /bin/sh; 349 | shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n"; 350 | }; 351 | /* End PBXShellScriptBuildPhase section */ 352 | 353 | /* Begin PBXSourcesBuildPhase section */ 354 | A885A96F1694FCDD00CA6E1B /* Sources */ = { 355 | isa = PBXSourcesBuildPhase; 356 | buildActionMask = 2147483647; 357 | files = ( 358 | A885A9B61694FD5400CA6E1B /* TSQTAAppDelegate.m in Sources */, 359 | A885A9B81694FD5400CA6E1B /* TSQTACalendarRowCell.m in Sources */, 360 | A885A9BA1694FD5400CA6E1B /* TSQTAViewController.m in Sources */, 361 | A885AA841695023500CA6E1B /* main.m in Sources */, 362 | ); 363 | runOnlyForDeploymentPostprocessing = 0; 364 | }; 365 | A885A98E1694FCDD00CA6E1B /* Sources */ = { 366 | isa = PBXSourcesBuildPhase; 367 | buildActionMask = 2147483647; 368 | files = ( 369 | A885A9A21694FCDD00CA6E1B /* TimesSquareTestAppTests.m in Sources */, 370 | ); 371 | runOnlyForDeploymentPostprocessing = 0; 372 | }; 373 | /* End PBXSourcesBuildPhase section */ 374 | 375 | /* Begin PBXTargetDependency section */ 376 | A885A9991694FCDD00CA6E1B /* PBXTargetDependency */ = { 377 | isa = PBXTargetDependency; 378 | target = A885A9721694FCDD00CA6E1B /* TimesSquareTestApp */; 379 | targetProxy = A885A9981694FCDD00CA6E1B /* PBXContainerItemProxy */; 380 | }; 381 | A885A9B41694FD4700CA6E1B /* PBXTargetDependency */ = { 382 | isa = PBXTargetDependency; 383 | name = TimesSquare; 384 | targetProxy = A885A9B31694FD4700CA6E1B /* PBXContainerItemProxy */; 385 | }; 386 | /* End PBXTargetDependency section */ 387 | 388 | /* Begin PBXVariantGroup section */ 389 | A885A9621694FC8A00CA6E1B /* InfoPlist.strings */ = { 390 | isa = PBXVariantGroup; 391 | children = ( 392 | A885A9631694FC8A00CA6E1B /* en */, 393 | ); 394 | name = InfoPlist.strings; 395 | path = en.lproj; 396 | sourceTree = ""; 397 | }; 398 | A885A99D1694FCDD00CA6E1B /* InfoPlist.strings */ = { 399 | isa = PBXVariantGroup; 400 | children = ( 401 | A885A99E1694FCDD00CA6E1B /* en */, 402 | ); 403 | name = InfoPlist.strings; 404 | sourceTree = ""; 405 | }; 406 | /* End PBXVariantGroup section */ 407 | 408 | /* Begin XCBuildConfiguration section */ 409 | A885A94D1694FC4500CA6E1B /* Debug */ = { 410 | isa = XCBuildConfiguration; 411 | buildSettings = { 412 | ONLY_ACTIVE_ARCH = YES; 413 | }; 414 | name = Debug; 415 | }; 416 | A885A94E1694FC4500CA6E1B /* Release */ = { 417 | isa = XCBuildConfiguration; 418 | buildSettings = { 419 | }; 420 | name = Release; 421 | }; 422 | A885A9A41694FCDD00CA6E1B /* Debug */ = { 423 | isa = XCBuildConfiguration; 424 | buildSettings = { 425 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 426 | CLANG_CXX_LIBRARY = "libc++"; 427 | CLANG_ENABLE_OBJC_ARC = YES; 428 | CLANG_WARN_EMPTY_BODY = YES; 429 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 430 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 431 | COPY_PHASE_STRIP = NO; 432 | FRAMEWORK_SEARCH_PATHS = ( 433 | "$(inherited)", 434 | "\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Library/Frameworks\"", 435 | ); 436 | GCC_C_LANGUAGE_STANDARD = gnu99; 437 | GCC_DYNAMIC_NO_PIC = NO; 438 | GCC_OPTIMIZATION_LEVEL = 0; 439 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 440 | GCC_PREFIX_HEADER = "TimesSquareTestApp-Prefix.pch"; 441 | GCC_PREPROCESSOR_DEFINITIONS = ( 442 | "DEBUG=1", 443 | "$(inherited)", 444 | ); 445 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 446 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 447 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 448 | GCC_WARN_UNUSED_VARIABLE = YES; 449 | INFOPLIST_FILE = "$(SRCROOT)/TimesSquareTestApp-Info.plist"; 450 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 451 | ONLY_ACTIVE_ARCH = YES; 452 | PRODUCT_NAME = "$(TARGET_NAME)"; 453 | SDKROOT = iphoneos; 454 | WRAPPER_EXTENSION = app; 455 | }; 456 | name = Debug; 457 | }; 458 | A885A9A51694FCDD00CA6E1B /* Release */ = { 459 | isa = XCBuildConfiguration; 460 | buildSettings = { 461 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 462 | CLANG_CXX_LIBRARY = "libc++"; 463 | CLANG_ENABLE_OBJC_ARC = YES; 464 | CLANG_WARN_EMPTY_BODY = YES; 465 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 466 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 467 | COPY_PHASE_STRIP = YES; 468 | FRAMEWORK_SEARCH_PATHS = ( 469 | "$(inherited)", 470 | "\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Library/Frameworks\"", 471 | ); 472 | GCC_C_LANGUAGE_STANDARD = gnu99; 473 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 474 | GCC_PREFIX_HEADER = "TimesSquareTestApp-Prefix.pch"; 475 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 476 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 477 | GCC_WARN_UNUSED_VARIABLE = YES; 478 | INFOPLIST_FILE = "$(SRCROOT)/TimesSquareTestApp-Info.plist"; 479 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 480 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 481 | PRODUCT_NAME = "$(TARGET_NAME)"; 482 | SDKROOT = iphoneos; 483 | VALIDATE_PRODUCT = YES; 484 | WRAPPER_EXTENSION = app; 485 | }; 486 | name = Release; 487 | }; 488 | A885A9A71694FCDD00CA6E1B /* Debug */ = { 489 | isa = XCBuildConfiguration; 490 | buildSettings = { 491 | ALWAYS_SEARCH_USER_PATHS = NO; 492 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/TimesSquareTestApp.app/TimesSquareTestApp"; 493 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 494 | CLANG_CXX_LIBRARY = "libc++"; 495 | CLANG_ENABLE_OBJC_ARC = YES; 496 | CLANG_WARN_EMPTY_BODY = YES; 497 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 498 | COPY_PHASE_STRIP = NO; 499 | FRAMEWORK_SEARCH_PATHS = ( 500 | "\"$(SDKROOT)/Developer/Library/Frameworks\"", 501 | "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", 502 | ); 503 | GCC_C_LANGUAGE_STANDARD = gnu99; 504 | GCC_DYNAMIC_NO_PIC = NO; 505 | GCC_OPTIMIZATION_LEVEL = 0; 506 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 507 | GCC_PREFIX_HEADER = "TimesSquareTestApp/TimesSquareTestApp-Prefix.pch"; 508 | GCC_PREPROCESSOR_DEFINITIONS = ( 509 | "DEBUG=1", 510 | "$(inherited)", 511 | ); 512 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 513 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 514 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 515 | GCC_WARN_UNUSED_VARIABLE = YES; 516 | INFOPLIST_FILE = "TimesSquareTestAppTests/TimesSquareTestAppTests-Info.plist"; 517 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 518 | ONLY_ACTIVE_ARCH = YES; 519 | PRODUCT_NAME = "$(TARGET_NAME)"; 520 | SDKROOT = iphoneos; 521 | TEST_HOST = "$(BUNDLE_LOADER)"; 522 | WRAPPER_EXTENSION = octest; 523 | }; 524 | name = Debug; 525 | }; 526 | A885A9A81694FCDD00CA6E1B /* Release */ = { 527 | isa = XCBuildConfiguration; 528 | buildSettings = { 529 | ALWAYS_SEARCH_USER_PATHS = NO; 530 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/TimesSquareTestApp.app/TimesSquareTestApp"; 531 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 532 | CLANG_CXX_LIBRARY = "libc++"; 533 | CLANG_ENABLE_OBJC_ARC = YES; 534 | CLANG_WARN_EMPTY_BODY = YES; 535 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 536 | COPY_PHASE_STRIP = YES; 537 | FRAMEWORK_SEARCH_PATHS = ( 538 | "\"$(SDKROOT)/Developer/Library/Frameworks\"", 539 | "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", 540 | ); 541 | GCC_C_LANGUAGE_STANDARD = gnu99; 542 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 543 | GCC_PREFIX_HEADER = "TimesSquareTestApp/TimesSquareTestApp-Prefix.pch"; 544 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 545 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 546 | GCC_WARN_UNUSED_VARIABLE = YES; 547 | INFOPLIST_FILE = "TimesSquareTestAppTests/TimesSquareTestAppTests-Info.plist"; 548 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 549 | PRODUCT_NAME = "$(TARGET_NAME)"; 550 | SDKROOT = iphoneos; 551 | TEST_HOST = "$(BUNDLE_LOADER)"; 552 | VALIDATE_PRODUCT = YES; 553 | WRAPPER_EXTENSION = octest; 554 | }; 555 | name = Release; 556 | }; 557 | /* End XCBuildConfiguration section */ 558 | 559 | /* Begin XCConfigurationList section */ 560 | A885A94B1694FC4500CA6E1B /* Build configuration list for PBXProject "TimesSquareTestApp" */ = { 561 | isa = XCConfigurationList; 562 | buildConfigurations = ( 563 | A885A94D1694FC4500CA6E1B /* Debug */, 564 | A885A94E1694FC4500CA6E1B /* Release */, 565 | ); 566 | defaultConfigurationIsVisible = 0; 567 | defaultConfigurationName = Release; 568 | }; 569 | A885A9A31694FCDD00CA6E1B /* Build configuration list for PBXNativeTarget "TimesSquareTestApp" */ = { 570 | isa = XCConfigurationList; 571 | buildConfigurations = ( 572 | A885A9A41694FCDD00CA6E1B /* Debug */, 573 | A885A9A51694FCDD00CA6E1B /* Release */, 574 | ); 575 | defaultConfigurationIsVisible = 0; 576 | defaultConfigurationName = Release; 577 | }; 578 | A885A9A61694FCDD00CA6E1B /* Build configuration list for PBXNativeTarget "TimesSquareTestAppTests" */ = { 579 | isa = XCConfigurationList; 580 | buildConfigurations = ( 581 | A885A9A71694FCDD00CA6E1B /* Debug */, 582 | A885A9A81694FCDD00CA6E1B /* Release */, 583 | ); 584 | defaultConfigurationIsVisible = 0; 585 | defaultConfigurationName = Release; 586 | }; 587 | /* End XCConfigurationList section */ 588 | }; 589 | rootObject = A885A9481694FC4500CA6E1B /* Project object */; 590 | } 591 | --------------------------------------------------------------------------------