├── Gemfile ├── .travis.yml ├── NSDate+SRGFekable.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata ├── xcshareddata │ └── xcschemes │ │ └── NSDate+SRGFekable.xcscheme └── project.pbxproj ├── Rakefile ├── NSDate+SRGFekable ├── ViewController.h ├── AppDelegate.h ├── main.m ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── ViewController.m ├── Info.plist ├── AppDelegate.m └── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── Classes ├── SRGFakableViewController.h ├── NSDate+SRGFekable.h ├── SRGFakableViewController.m ├── NSDate+SRGFekable.m └── SRGFakableViewController.xib ├── NSDate+SRGFekable.podspec ├── .gitignore ├── NSDate+SRGFekableTests ├── Info.plist └── NSDate_SRGFekableTests.m ├── LICENSE └── README.md /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'rake' 4 | gem 'xcpretty' 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | 3 | script: 4 | - bundle exec rake default 5 | -------------------------------------------------------------------------------- /NSDate+SRGFekable.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | SCHEME = "NSDate+SRGFekable" 2 | DESTINATION = "name=iPhone 5,OS=8.1" 3 | 4 | desc "unit test" 5 | task :default do 6 | sh "xcodebuild test -scheme #{SCHEME} -destination \"#{DESTINATION}\" -configuration Debug | bundle exec xcpretty -c && exit ${PIPESTATUS[0]}" 7 | end 8 | -------------------------------------------------------------------------------- /NSDate+SRGFekable/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // NSDate+SRGFekable 4 | // 5 | // Created by nori0620 on 2015/01/01. 6 | // Copyright (c) 2015年 soragoto. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /NSDate+SRGFekable/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // NSDate+SRGFekable 4 | // 5 | // Created by nori0620 on 2015/01/01. 6 | // Copyright (c) 2015年 soragoto. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /Classes/SRGFakableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SRGFakableViewController.h 3 | // NSDate+SRGFekable 4 | // 5 | // Created by nori0620 on 2015/01/02. 6 | // Copyright (c) 2015年 soragoto. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SRGFakableViewController : UIViewController 12 | 13 | + (void) showOn:(UIViewController *)below 14 | freezeOnFake:(BOOL)freezeOnFake; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /NSDate+SRGFekable/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // NSDate+SRGFekable 4 | // 5 | // Created by nori0620 on 2015/01/01. 6 | // Copyright (c) 2015年 soragoto. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /NSDate+SRGFekable.podspec: -------------------------------------------------------------------------------- 1 | 2 | Pod::Spec.new do |s| 3 | 4 | s.name = "NSDate+SRGFekable" 5 | s.version = "0.0.2" 6 | s.summary = "A category to fake current date for unit tests." 7 | s.homepage = "https://github.com/soragoto/NSDate-SRGFekable" 8 | s.license = "MIT" 9 | s.author = { "Norihiro Sakamoto" => "nori0620@gmail.com" } 10 | s.source = { :git => "https://github.com/soragoto/NSDate-SRGFekable.git", :tag => "0.0.2" } 11 | s.platform = :ios, '6.0' 12 | s.source_files = "Classes", "Classes/**/*.{h,m}" 13 | s.resources = ['Classes/SRGFakableViewController.xib'] 14 | s.requires_arc = true 15 | 16 | end 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # Ruby 21 | # 22 | vendor 23 | Gemfile.lock 24 | .bundle 25 | 26 | # CocoaPods 27 | # 28 | # We recommend against adding the Pods directory to your .gitignore. However 29 | # you should judge for yourself, the pros and cons are mentioned at: 30 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 31 | # 32 | # Pods/ 33 | -------------------------------------------------------------------------------- /NSDate+SRGFekableTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | info.soragoto.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Classes/NSDate+SRGFekable.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDate+SRGFekable.h 3 | // NSDate+SRGFekable 4 | // 5 | // Created by nori0620 on 2015/01/01. 6 | // Copyright (c) 2015年 soragoto. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSDate (SRGFakable) 12 | 13 | + (instancetype) now; 14 | + (BOOL) doFaking; 15 | + (void) stopFaking; 16 | + (void) fakeWithDate:(NSDate *)date; 17 | + (void) fakeWithDate:(NSDate *)date 18 | freeze:(BOOL)freeze 19 | ; 20 | + (void) fakeWithString:(NSString *)dateString; 21 | + (void) fakeWithString:(NSString *)dateString 22 | freeze:(BOOL)freeze 23 | ; 24 | + (void) fakeWithString:(NSString *)dateString 25 | timeZone:(NSTimeZone *)timeZone 26 | ; 27 | + (void) fakeWithString:(NSString *)dateString 28 | timeZone:(NSTimeZone *)timeZone 29 | freeze:(BOOL)freeze 30 | ; 31 | + (void) fakeWithDelta:(NSTimeInterval)delta; 32 | + (void) fakeWithDelta:(NSTimeInterval)delta 33 | freeze:(BOOL)freeze 34 | ; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 soragoto 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /NSDate+SRGFekable/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /NSDate+SRGFekable/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // NSDate+SRGFekable 4 | // 5 | // Created by nori0620 on 2015/01/01. 6 | // Copyright (c) 2015年 soragoto. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "SRGFakableViewController.h" 11 | 12 | @interface ViewController () 13 | 14 | @property (nonatomic) IBOutlet UILabel *currentDateLabel; 15 | @property NSTimer *timer; 16 | 17 | @end 18 | 19 | @implementation ViewController 20 | 21 | - (NSString *)title { 22 | return @"NSDate+SRGFakable"; 23 | } 24 | 25 | - (void)viewDidLoad { 26 | [super viewDidLoad]; 27 | [self p_updateDateLabel]; 28 | } 29 | 30 | - (void)didReceiveMemoryWarning { 31 | [super didReceiveMemoryWarning]; 32 | } 33 | 34 | - (void)viewWillAppear:(BOOL)animated { 35 | [super viewWillAppear:animated]; 36 | self.timer = [NSTimer scheduledTimerWithTimeInterval:1 37 | target:self 38 | selector:@selector(p_updateDateLabel) 39 | userInfo:nil 40 | repeats:YES]; 41 | } 42 | 43 | - (void)viewDidDisappear:(BOOL)animated { 44 | [super viewDidDisappear:animated]; 45 | [self.timer invalidate]; 46 | } 47 | 48 | - (IBAction)didTapLaunchFaker:(id)sender { 49 | [SRGFakableViewController showOn:self 50 | freezeOnFake:NO 51 | ]; 52 | } 53 | 54 | - (void) p_updateDateLabel { 55 | self.currentDateLabel.text = [NSString stringWithFormat:@"now:%@",[NSDate date]]; 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /NSDate+SRGFekable/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | info.soragoto.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 0.0.2 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /NSDate+SRGFekable/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // NSDate+SRGFekable 4 | // 5 | // Created by nori0620 on 2015/01/01. 6 | // Copyright (c) 2015年 soragoto. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | NSDate+SRGFekable 2 | =========== 3 | 4 | 5 | [![CI Status](http://img.shields.io/travis/soragoto/NSDate-SRGFekable.svg?style=flat)](https://travis-ci.org/soragoto/NSDate-SRGFekable) 6 | [![Version](https://img.shields.io/cocoapods/v/NSDate+SRGFekable.svg?style=flat)](https://github.com/soragoto/NSDate-SRGFekable) 7 | [![License](https://img.shields.io/cocoapods/l/NSDate+SRGFekable.svg?style=flat)](https://github.com/soragoto/NSDate-SRGFekable) 8 | [![Platform](https://img.shields.io/cocoapods/p/NSDate+SRGFekable.svg?style=flat)](https://github.com/soragoto/NSDate-SRGFekable) 9 | 10 | NSDate+SRGFekable is a category to fake results of NSDate. You can test your app features that depend on date more easily. 11 | 12 | ## Installation 13 | 14 | Add the following line to your podfile and run `pod update`. 15 | 16 | ```ruby 17 | pod 'NSDate+SRGFekable' 18 | ``` 19 | 20 | ## Usage 21 | 22 | At first you need to include header file. 23 | 24 | ```objc 25 | #import 'NSDate+SRGFekable' 26 | ``` 27 | 28 | You can fake NSDate simply 29 | 30 | 31 | ```objc 32 | // You can fake result of NSDate. 33 | [NSDate fakeWithString:@"2014/12/27 10:00:00"]; 34 | 35 | // On this process, NSDate behave as if current-time is "2014/12/27 10:00:00" 36 | NSLog(@"now:%@",[NSDate date]); // -> now:2014/12/27 10:00:00 37 | ```` 38 | 39 | By using this category , you can write unit tests easily. 40 | 41 | ```objc 42 | .... 43 | - (void)testIsXmas { 44 | SeasonalEvent *seasonalEvent = [SeasonalEvent new]; 45 | 46 | [NSDate fakeWithString:@"2014/12/20 10:00:00"]; 47 | XCTAssertFalse( seasonalEvent.isXmas ); 48 | 49 | [NSDate fakeWithString:@"2014/12/25 10:00:00"]; 50 | XCTAssertTrue( seasonalEvent.isXmas ); 51 | } 52 | ... 53 | ```` 54 | 55 | ## All methods 56 | 57 | ### fakeWithDate 58 | 59 | You can fake from another NSDate instance.. 60 | 61 | 62 | ```objc 63 | NSDate *aDate = [NSDate dateWithTimeIntervalSinceNow:100]; 64 | [NSDate fakeWithDate:aDate]; 65 | 66 | // NSDate behave as if current-time is aDate 67 | ```` 68 | 69 | ### fakeWithDelta 70 | 71 | 72 | ```objc 73 | // NSDate behave as if current-time is 60 seconds latter of real date. 74 | [NSDate fakeWithDelta:100]; 75 | 76 | // NSDate behave as if current-time is 180(=120+60) seconds latter of real date. 77 | [NSDate fakeWithDelta:120]; 78 | 79 | //// NSDate behave as if current-time is 150(=180-30) seconds latter of real date. 80 | [NSDate fakeWithDelta:-30]; 81 | ```` 82 | 83 | ### Stop stopFaking 84 | 85 | ```objc 86 | // You can stop faking. 87 | [NSDate stopFaking]; 88 | 89 | // You can get status of faking or not. 90 | BOOL doFaking = [NSDate doFaking]; 91 | ```` 92 | 93 | ### freeze option 94 | 95 | Each `fakeXXX` methods have `freeze` option. (Default is `YES`) 96 | 97 | * If `freeze` is `YES`、faked date is completely stop. 98 | * If `freeze` is `NO`, faked date go on. 99 | 100 | This option may be useful when you fake date on Main Project(not Test Project) for manually test. 101 | 102 | 103 | ```objc 104 | // YES is default. 105 | [NSDate fakeWithString:@"2014/12/27 10:00:00" freeze:YES]; 106 | // -> [NSDate date] always return @"2014/12/27 10:00:00" 107 | 108 | // freeze:NO 109 | [NSDate fakeWithString:@"2014/12/27 10:00:00" freeze:NO]; 110 | // -> If elapsed 10 seconds after call above, [NSDate date] returns @"2014/12/27 10:00:10" 111 | ```` 112 | 113 | ## LICENSE 114 | 115 | NSDate+SRGFekable is released under the MIT license. See LICENSE for details. 116 | -------------------------------------------------------------------------------- /NSDate+SRGFekable/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /NSDate+SRGFekable.xcodeproj/xcshareddata/xcschemes/NSDate+SRGFekable.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 94 | 100 | 101 | 102 | 103 | 105 | 106 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /NSDate+SRGFekable/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /NSDate+SRGFekableTests/NSDate_SRGFekableTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDate_SRGFekableTests.m 3 | // NSDate+SRGFekableTests 4 | // 5 | // Created by nori0620 on 2015/01/01. 6 | // Copyright (c) 2015年 soragoto. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "NSDate+SRGFekable.h" 12 | 13 | @interface NSDate_SRGFekableTests : XCTestCase 14 | 15 | @end 16 | 17 | @implementation NSDate_SRGFekableTests 18 | 19 | - (void)setUp { 20 | [NSDate stopFaking]; 21 | [super setUp]; 22 | } 23 | 24 | - (void)tearDown { 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testDate { 29 | NSDate *realDate = [NSDate date]; 30 | XCTAssertFalse([NSDate doFaking]); 31 | 32 | [NSDate fakeWithDate:[NSDate dateWithTimeIntervalSinceNow:100] ]; 33 | NSDate *fakedDate = [NSDate date]; 34 | XCTAssertTrue([NSDate doFaking]); 35 | 36 | XCTAssertEqual((int)[fakedDate timeIntervalSinceDate:realDate],100); 37 | XCTAssertTrue([NSDate doFaking]); 38 | 39 | [NSDate stopFaking]; 40 | NSDate *realDate2 = [NSDate date]; 41 | XCTAssertFalse([NSDate doFaking]); 42 | XCTAssertEqual((int)[realDate2 timeIntervalSinceDate:realDate],0); 43 | } 44 | 45 | - (void)testInit{ 46 | NSDate *realDate = [[NSDate alloc] init]; 47 | 48 | [NSDate fakeWithDate:[NSDate dateWithTimeIntervalSinceNow:100] 49 | freeze:YES 50 | ]; 51 | NSDate *fakedDate = [[NSDate alloc] init]; 52 | 53 | XCTAssertEqual((int)[fakedDate timeIntervalSinceDate:realDate],100); 54 | 55 | [NSDate stopFaking]; 56 | NSDate *realDate2 = [[NSDate alloc] init]; 57 | XCTAssertEqual((int)[realDate2 timeIntervalSinceDate:realDate],0); 58 | } 59 | 60 | - (void)testInitWithTimeIntervalSinceNow{ 61 | 62 | NSDate *realDate = [NSDate new]; 63 | NSDate *realDate60 = [[NSDate alloc] initWithTimeIntervalSinceNow:60]; 64 | NSTimeInterval realDiff = [realDate60 timeIntervalSinceDate:realDate]; 65 | 66 | [NSDate fakeWithString:@"2014/11/11 11:11:11"]; 67 | 68 | NSDate *fakeDate = [NSDate date]; 69 | NSDate *fakeDate60 = [[NSDate alloc] initWithTimeIntervalSinceNow:60]; 70 | NSTimeInterval fakeDiff = [fakeDate60 timeIntervalSinceDate:fakeDate]; 71 | 72 | XCTAssertEqual( 73 | (int)realDiff, 74 | (int)fakeDiff 75 | ); 76 | 77 | } 78 | 79 | - (void)testNow { 80 | NSDate *realDate = [NSDate now]; 81 | 82 | [NSDate fakeWithDate:[NSDate dateWithTimeIntervalSinceNow:100] 83 | freeze:YES 84 | ]; 85 | NSDate *fakedDate = [NSDate now]; 86 | 87 | XCTAssertEqual((int)[fakedDate timeIntervalSinceDate:realDate],100); 88 | 89 | [NSDate stopFaking]; 90 | NSDate *realDate2 = [NSDate now]; 91 | XCTAssertEqual((int)[realDate2 timeIntervalSinceDate:realDate],0); 92 | } 93 | 94 | 95 | - (void) testDateWithTimeIntervalSinceNow { 96 | 97 | NSDate *realDate = [NSDate dateWithTimeIntervalSinceNow:300]; 98 | 99 | [NSDate fakeWithDate: 100 | [NSDate dateWithTimeIntervalSinceNow:100] 101 | freeze:YES 102 | ]; 103 | 104 | NSDate *fakedDate = [NSDate dateWithTimeIntervalSinceNow:300]; 105 | XCTAssertEqual((int)[fakedDate timeIntervalSinceDate:realDate],100); 106 | 107 | [NSDate stopFaking]; 108 | NSDate *realDate2 = [NSDate dateWithTimeIntervalSinceNow:300]; 109 | XCTAssertEqual((int)[realDate2 timeIntervalSinceDate:realDate],0); 110 | 111 | } 112 | 113 | - (void) testTimeIntervalSinceNow { 114 | 115 | NSDate *aDate = [NSDate date]; 116 | 117 | NSTimeInterval realInterval = [aDate timeIntervalSinceNow]; 118 | 119 | [NSDate fakeWithDate: [NSDate dateWithTimeIntervalSinceNow:-100] 120 | freeze:YES 121 | ]; 122 | 123 | NSTimeInterval fakeInterval = [aDate timeIntervalSinceNow]; 124 | 125 | NSTimeInterval diff = fakeInterval - realInterval; 126 | BOOL expected = diff >= 99.0 && diff <= 100.0; 127 | XCTAssertTrue( expected ); 128 | 129 | [NSDate stopFaking]; 130 | NSTimeInterval realInterval2 = [aDate timeIntervalSinceNow]; 131 | XCTAssertEqual( (int)realInterval2 - (int)realInterval,0); 132 | 133 | } 134 | 135 | - (void) testFakeWithString{ 136 | 137 | [NSDate fakeWithString:@"2014/01/05 11:32:00" 138 | timeZone:[NSTimeZone timeZoneWithName:@"Asia/Tokyo"] 139 | freeze:YES 140 | ]; 141 | NSTimeInterval intervalSince1970 = [[NSDate date] timeIntervalSince1970]; 142 | XCTAssertEqual(intervalSince1970, 1388889120 ); 143 | 144 | } 145 | 146 | - (void) testFakeWithDelta { 147 | NSDate *realDate = [NSDate date]; 148 | 149 | [NSDate fakeWithDelta:60]; 150 | 151 | NSDate *fakedDate = [NSDate date]; 152 | XCTAssertEqual((int)[fakedDate timeIntervalSinceDate:realDate],60); 153 | 154 | [NSDate fakeWithDelta:120]; 155 | NSDate *fakedDate2 = [NSDate date]; 156 | 157 | XCTAssertEqual((int)[fakedDate2 timeIntervalSinceDate:realDate],180); 158 | 159 | [NSDate fakeWithDelta:-60]; 160 | NSDate *fakedDate3 = [NSDate date]; 161 | XCTAssertEqual((int)[fakedDate3 timeIntervalSinceDate:realDate],120); 162 | 163 | [NSDate stopFaking]; 164 | NSDate *realDate2 = [NSDate date]; 165 | XCTAssertEqual((int)[realDate2 timeIntervalSinceDate:realDate],0); 166 | 167 | } 168 | 169 | 170 | @end 171 | -------------------------------------------------------------------------------- /Classes/SRGFakableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SRGFakableViewController.m 3 | // NSDate+SRGFekable 4 | // 5 | // Created by nori0620 on 2015/01/02. 6 | // Copyright (c) 2015年 soragoto. All rights reserved. 7 | // 8 | 9 | #import "SRGFakableViewController.h" 10 | #import "NSDate+SRGFekable.h" 11 | 12 | @interface SRGFakableViewController () 13 | 14 | @property BOOL freezeOnFake; 15 | @property NSTimer *timer; 16 | @property (nonatomic) IBOutlet UIDatePicker *datePicker; 17 | @property (nonatomic) IBOutlet UILabel *titleLabel; 18 | @property (nonatomic) IBOutlet UILabel *dateResultLabel; 19 | @property (nonatomic) IBOutlet UIButton *startFakingButton; 20 | @property (nonatomic) IBOutlet UIButton *stopFakingButton; 21 | @property (nonatomic) IBOutlet UIButton *doFakeButton; 22 | @property (nonatomic) IBOutlet NSLayoutConstraint *pickerHeight; 23 | @property (nonatomic) BOOL doSelectiongDate; 24 | 25 | @end 26 | 27 | @implementation SRGFakableViewController 28 | 29 | + (void)showOn:(UIViewController *)below 30 | freezeOnFake:(BOOL)freezeOnFake 31 | { 32 | SRGFakableViewController *controller = [[[self class] alloc] initWithNibName:NSStringFromClass([self class]) 33 | 34 | bundle:nil]; 35 | controller.freezeOnFake = freezeOnFake; 36 | UINavigationController *navigationController = [UINavigationController new]; 37 | [navigationController pushViewController:controller animated:NO]; 38 | [below presentViewController:navigationController 39 | animated:YES 40 | completion:nil]; 41 | 42 | } 43 | 44 | # pragma mark - Life cycle events 45 | 46 | - (void)viewDidLoad { 47 | [super viewDidLoad]; 48 | self.title = @"Fake NSDate"; 49 | if ([self respondsToSelector:@selector(edgesForExtendedLayout)]){ 50 | self.edgesForExtendedLayout = UIRectEdgeNone; 51 | } 52 | [self showDoneToNavigation]; 53 | [self updateVisibility]; 54 | [self updateLabels]; 55 | [self updateButtonEnability]; 56 | } 57 | 58 | - (void)viewWillAppear:(BOOL)animated { 59 | [super viewWillAppear:animated]; 60 | self.timer = [NSTimer scheduledTimerWithTimeInterval:1 61 | target:self 62 | selector:@selector(updateLabels) 63 | userInfo:nil 64 | repeats:YES]; 65 | } 66 | 67 | - (void)viewDidDisappear:(BOOL)animated { 68 | [super viewDidDisappear:animated]; 69 | [self.timer invalidate]; 70 | } 71 | 72 | - (void)updateViewConstraints { 73 | [super updateViewConstraints]; 74 | self.pickerHeight.constant = _doSelectiongDate ? 100 : 0 ; 75 | } 76 | 77 | #pragma mark - Tap Handlers 78 | 79 | 80 | - (IBAction)didTapStartFakingDate:(id)sender { 81 | self.datePicker.date = [NSDate date]; 82 | self.doSelectiongDate = YES; 83 | } 84 | 85 | - (IBAction)didTapStopFakingDate:(id)sender { 86 | [NSDate stopFaking]; 87 | [self updateLabels]; 88 | [self updateButtonEnability]; 89 | } 90 | 91 | - (IBAction)didTapDoFake:(id)sender { 92 | [NSDate fakeWithDate: _datePicker.date 93 | freeze: self.freezeOnFake 94 | ]; 95 | [self updateLabels]; 96 | [self updateButtonEnability]; 97 | self.doSelectiongDate = NO; 98 | } 99 | 100 | - (void) didTapDone { 101 | [self.navigationController dismissViewControllerAnimated:YES completion:nil]; 102 | } 103 | 104 | # pragma mark - Status Updater 105 | 106 | - (void) updateVisibility { 107 | self.dateResultLabel.alpha = !_doSelectiongDate; 108 | self.startFakingButton.alpha = !_doSelectiongDate; 109 | self.stopFakingButton.alpha = !_doSelectiongDate; 110 | self.datePicker.alpha = _doSelectiongDate; 111 | self.doFakeButton.alpha = _doSelectiongDate; 112 | } 113 | 114 | - (void) updateLabels{ 115 | self.dateResultLabel.text = [self stringFromDate:[NSDate date]]; 116 | self.titleLabel.text = [NSDate doFaking] 117 | ? @"Result of NSDate.date(!Faking!)" 118 | : @"Result of NSDate.date(original)"; 119 | self.titleLabel.textColor = [NSDate doFaking] 120 | ? [UIColor redColor] 121 | : [UIColor colorWithRed:83.0f/255.0f 122 | green:181.0f/255.0f 123 | blue:26.0f/255.0f 124 | alpha:1.0f]; 125 | } 126 | 127 | - (void) updateButtonEnability { 128 | self.stopFakingButton.enabled = [NSDate doFaking]; 129 | self.startFakingButton.enabled = ![NSDate doFaking]; 130 | } 131 | 132 | 133 | - (void)setDoSelectiongDate:(BOOL)doSelectiongDate { 134 | _doSelectiongDate = doSelectiongDate; 135 | __weak typeof(self) wSlef = self; 136 | [UIView animateWithDuration:0.3f delay:0 options:UIViewAnimationOptionCurveEaseIn 137 | animations:^{ 138 | [wSlef updateVisibility]; 139 | [wSlef.view setNeedsUpdateConstraints]; 140 | [wSlef.view layoutIfNeeded]; 141 | } 142 | completion:nil 143 | ]; 144 | } 145 | 146 | # pragma mark - Utils 147 | 148 | - (void) showDoneToNavigation { 149 | UIBarButtonItem *done = [[UIBarButtonItem alloc] 150 | initWithBarButtonSystemItem:UIBarButtonSystemItemDone 151 | target:self 152 | action:@selector(didTapDone)]; 153 | self.navigationItem.leftBarButtonItem = done; 154 | } 155 | 156 | - (NSString *) stringFromDate:(NSDate *)date { 157 | NSDateFormatter *df = [[NSDateFormatter alloc] init]; 158 | [df setLocale:[NSLocale currentLocale]]; 159 | [df setDateFormat:@"yyyy/MM/dd HH:mm:ss"]; 160 | return [df stringFromDate:date]; 161 | } 162 | 163 | @end 164 | -------------------------------------------------------------------------------- /Classes/NSDate+SRGFekable.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDate+SRGFekable.m 3 | // NSDate+SRGFekable 4 | // 5 | // Created by nori0620 on 2015/01/01. 6 | // Copyright (c) 2015年 soragoto. All rights reserved. 7 | // 8 | 9 | #import "NSDate+SRGFekable.h" 10 | #import 11 | 12 | @interface NSDate (SRGFakable_Private) 13 | + (instancetype) p_swizzledDate ; 14 | +(void) p_swizzleMethods ; 15 | +(NSDate *) p_dateFromString:(NSString *)dateString 16 | timeZone:(NSTimeZone *)timeZone; 17 | @end 18 | 19 | #pragma mark - Public methods 20 | 21 | @implementation NSDate (SRGFakable) 22 | 23 | static NSDate *fakedNow = nil; 24 | static NSTimeInterval fakeDiff = 0; 25 | static BOOL isSwizzledDateMehtods = NO; 26 | static BOOL doFreeze = NO; 27 | 28 | + (instancetype)now { 29 | return [[self class] date]; 30 | } 31 | 32 | + (BOOL)doFaking{ 33 | return !!fakedNow; 34 | } 35 | 36 | + (void)stopFaking { 37 | fakedNow = nil; 38 | } 39 | 40 | 41 | + (void)fakeWithDate:(NSDate *)date { 42 | return[self fakeWithDate:date freeze:YES]; 43 | } 44 | 45 | + (void)fakeWithDate:(NSDate *)date 46 | freeze:(BOOL)freeze 47 | { 48 | fakedNow = date; 49 | doFreeze = freeze; 50 | [self p_swizzleMethods]; 51 | fakeDiff = [[[self class] p_swizzledDate] timeIntervalSinceDate:fakedNow]; 52 | } 53 | 54 | + (void)fakeWithString:(NSString *)dateString 55 | timeZone:(NSTimeZone *)timeZone 56 | freeze:(BOOL)freeze 57 | { 58 | NSDate *date = [[self class] p_dateFromString:dateString 59 | timeZone:timeZone ]; 60 | [self fakeWithDate:date 61 | freeze:freeze 62 | ]; 63 | } 64 | 65 | + (void)fakeWithString:(NSString *)dateString 66 | timeZone:(NSTimeZone *)timeZone 67 | { 68 | return [[self class] fakeWithString:dateString 69 | timeZone:[NSTimeZone systemTimeZone] 70 | freeze:YES]; 71 | } 72 | 73 | + (void)fakeWithString:(NSString *)dateString 74 | freeze:(BOOL)freeze 75 | { 76 | return [[self class] fakeWithString:dateString 77 | timeZone:[NSTimeZone systemTimeZone] 78 | freeze:freeze]; 79 | } 80 | 81 | + (void)fakeWithString:(NSString *)dateString { 82 | return [self fakeWithString:dateString freeze:YES]; 83 | } 84 | 85 | 86 | + (void)fakeWithDelta:(NSTimeInterval)delta { 87 | return [self fakeWithDelta:delta freeze:YES]; 88 | } 89 | 90 | + (void)fakeWithDelta:(NSTimeInterval)delta 91 | freeze:(BOOL)freeze { 92 | [self fakeWithDate:[[NSDate date] dateByAddingTimeInterval:delta] 93 | freeze:freeze]; 94 | } 95 | 96 | @end 97 | 98 | 99 | #pragma mark - Private methods 100 | 101 | @implementation NSDate (SRGFakable_Private) 102 | 103 | + (NSDate *) p_reloadFakedNow { 104 | if( !fakedNow ){ return nil; } 105 | if( doFreeze ){ return fakedNow; } 106 | 107 | NSTimeInterval latestDiff = [[NSDate p_swizzledDate] timeIntervalSinceDate:fakedNow]; 108 | return [fakedNow dateByAddingTimeInterval: latestDiff - fakeDiff ]; 109 | } 110 | 111 | #pragma mark Swizzing Targets 112 | 113 | + (instancetype) p_swizzledDate { 114 | NSDate *faked = [[self class] p_reloadFakedNow]; 115 | if( faked ){ return faked; } 116 | return [self p_swizzledDate]; 117 | } 118 | 119 | + (instancetype) p_swizzledDateWithTimeIntervalSinceNow:(NSTimeInterval)secs{ 120 | NSDate *faked = [[self class] p_reloadFakedNow]; 121 | if( faked ){ 122 | return [NSDate dateWithTimeInterval:secs sinceDate:faked]; 123 | } 124 | return [self p_swizzledDateWithTimeIntervalSinceNow:secs]; 125 | } 126 | 127 | - (id) p_swizzledInit { 128 | if( [NSDate doFaking] ){ 129 | return [[NSDate alloc] p_swizzledInitWithTimeIntervalSinceNow:-fakeDiff]; 130 | } 131 | return [self p_swizzledInit]; 132 | } 133 | 134 | - (id) p_swizzledInitWithTimeIntervalSinceNow:(NSTimeInterval)secs { 135 | NSDate *faked = [[self class] p_reloadFakedNow]; 136 | if( faked ){ 137 | return [self p_swizzledInitWithTimeIntervalSinceNow:secs - fakeDiff]; 138 | } 139 | return [self p_swizzledInitWithTimeIntervalSinceNow:secs]; 140 | } 141 | 142 | - (NSTimeInterval) p_swizzledTimeIntervalSinceNow { 143 | NSDate *faked = [[self class] p_reloadFakedNow]; 144 | if( faked ){ 145 | return [ self timeIntervalSinceDate:faked]; 146 | } 147 | return [self p_swizzledTimeIntervalSinceNow]; 148 | } 149 | 150 | #pragma mark Execute Swizzing 151 | 152 | + (void)p_swizzleMethods { 153 | if( isSwizzledDateMehtods ){ return; } 154 | 155 | /* sizzle class methods */ { 156 | [self p_swizzleClassMethodWithOriginal:@selector(date) 157 | new:@selector(p_swizzledDate) 158 | ]; 159 | [self p_swizzleClassMethodWithOriginal:@selector(dateWithTimeIntervalSinceNow:) 160 | new:@selector(p_swizzledDateWithTimeIntervalSinceNow:) 161 | ]; 162 | } 163 | 164 | /* sizzle instance methods */ { 165 | [self p_swizzleInstanceMethodWithOriginal:@selector(timeIntervalSinceNow) 166 | new:@selector(p_swizzledTimeIntervalSinceNow) 167 | ]; 168 | [self p_swizzleInstanceMethodWithOriginal:@selector(init) 169 | new:@selector(p_swizzledInit) 170 | originalClass:NSClassFromString(@"__NSPlaceholderDate") 171 | ]; 172 | [self p_swizzleInstanceMethodWithOriginal:@selector(initWithTimeIntervalSinceNow:) 173 | new:@selector(p_swizzledInitWithTimeIntervalSinceNow:) 174 | originalClass:NSClassFromString(@"__NSPlaceholderDate") 175 | ]; 176 | } 177 | 178 | 179 | isSwizzledDateMehtods = YES; 180 | } 181 | 182 | +(void) p_swizzleClassMethodWithOriginal:(SEL)original 183 | new:(SEL)new 184 | { 185 | Method originalMethod = class_getClassMethod([self class], original); 186 | Method newMethod = class_getClassMethod([self class], new); 187 | method_exchangeImplementations(originalMethod, newMethod); 188 | } 189 | 190 | +(void) p_swizzleInstanceMethodWithOriginal:(SEL)original 191 | new:(SEL)new 192 | { 193 | return [self p_swizzleInstanceMethodWithOriginal:original 194 | new:new 195 | originalClass:[self class] ]; 196 | } 197 | 198 | +(void) p_swizzleInstanceMethodWithOriginal:(SEL)original 199 | new:(SEL)new 200 | originalClass:(Class)originalClass 201 | { 202 | Method originalMethod = class_getInstanceMethod(originalClass, original); 203 | Method newMethod = class_getInstanceMethod([self class], new); 204 | method_exchangeImplementations(originalMethod, newMethod); 205 | } 206 | 207 | #pragma mark Utils 208 | 209 | + (NSDate *) p_dateFromString:(NSString *)dateString 210 | timeZone:(NSTimeZone *)timeZone 211 | { 212 | NSDateFormatter *formatter = [NSDateFormatter new]; 213 | NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]; 214 | [formatter setLocale:locale]; 215 | [formatter setDateFormat:@"yyyy/MM/dd HH:mm:ss"]; 216 | [formatter setTimeZone:timeZone]; 217 | return [formatter dateFromString:dateString]; 218 | } 219 | 220 | @end 221 | -------------------------------------------------------------------------------- /Classes/SRGFakableViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 60 | 70 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /NSDate+SRGFekable.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | CC367D8C1A55348300B87159 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = CC367D8B1A55348300B87159 /* main.m */; }; 11 | CC367D8F1A55348300B87159 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CC367D8E1A55348300B87159 /* AppDelegate.m */; }; 12 | CC367D921A55348300B87159 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CC367D911A55348300B87159 /* ViewController.m */; }; 13 | CC367D951A55348300B87159 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CC367D931A55348300B87159 /* Main.storyboard */; }; 14 | CC367D971A55348300B87159 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CC367D961A55348300B87159 /* Images.xcassets */; }; 15 | CC367D9A1A55348300B87159 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = CC367D981A55348300B87159 /* LaunchScreen.xib */; }; 16 | CC367DA61A55348400B87159 /* NSDate_SRGFekableTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC367DA51A55348400B87159 /* NSDate_SRGFekableTests.m */; }; 17 | CC367DB81A55359E00B87159 /* NSDate+SRGFekable.m in Sources */ = {isa = PBXBuildFile; fileRef = CC367DB71A55359E00B87159 /* NSDate+SRGFekable.m */; }; 18 | CC367DBC1A55BCBF00B87159 /* SRGFakableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CC367DBA1A55BCBF00B87159 /* SRGFakableViewController.m */; }; 19 | CC367DBD1A55BCBF00B87159 /* SRGFakableViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = CC367DBB1A55BCBF00B87159 /* SRGFakableViewController.xib */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXContainerItemProxy section */ 23 | CC367DA01A55348400B87159 /* PBXContainerItemProxy */ = { 24 | isa = PBXContainerItemProxy; 25 | containerPortal = CC367D7E1A55348300B87159 /* Project object */; 26 | proxyType = 1; 27 | remoteGlobalIDString = CC367D851A55348300B87159; 28 | remoteInfo = "NSDate+SRGFekable"; 29 | }; 30 | /* End PBXContainerItemProxy section */ 31 | 32 | /* Begin PBXFileReference section */ 33 | CC367D861A55348300B87159 /* NSDate+SRGFekable.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "NSDate+SRGFekable.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 34 | CC367D8A1A55348300B87159 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 35 | CC367D8B1A55348300B87159 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 36 | CC367D8D1A55348300B87159 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 37 | CC367D8E1A55348300B87159 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 38 | CC367D901A55348300B87159 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 39 | CC367D911A55348300B87159 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 40 | CC367D941A55348300B87159 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 41 | CC367D961A55348300B87159 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 42 | CC367D991A55348300B87159 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 43 | CC367D9F1A55348400B87159 /* NSDate+SRGFekableTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "NSDate+SRGFekableTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | CC367DA41A55348400B87159 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 45 | CC367DA51A55348400B87159 /* NSDate_SRGFekableTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NSDate_SRGFekableTests.m; sourceTree = ""; }; 46 | CC367DB61A55359E00B87159 /* NSDate+SRGFekable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDate+SRGFekable.h"; sourceTree = ""; }; 47 | CC367DB71A55359E00B87159 /* NSDate+SRGFekable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDate+SRGFekable.m"; sourceTree = ""; }; 48 | CC367DB91A55BCBF00B87159 /* SRGFakableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SRGFakableViewController.h; sourceTree = ""; }; 49 | CC367DBA1A55BCBF00B87159 /* SRGFakableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SRGFakableViewController.m; sourceTree = ""; }; 50 | CC367DBB1A55BCBF00B87159 /* SRGFakableViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SRGFakableViewController.xib; sourceTree = ""; }; 51 | /* End PBXFileReference section */ 52 | 53 | /* Begin PBXFrameworksBuildPhase section */ 54 | CC367D831A55348300B87159 /* Frameworks */ = { 55 | isa = PBXFrameworksBuildPhase; 56 | buildActionMask = 2147483647; 57 | files = ( 58 | ); 59 | runOnlyForDeploymentPostprocessing = 0; 60 | }; 61 | CC367D9C1A55348400B87159 /* Frameworks */ = { 62 | isa = PBXFrameworksBuildPhase; 63 | buildActionMask = 2147483647; 64 | files = ( 65 | ); 66 | runOnlyForDeploymentPostprocessing = 0; 67 | }; 68 | /* End PBXFrameworksBuildPhase section */ 69 | 70 | /* Begin PBXGroup section */ 71 | CC367D7D1A55348300B87159 = { 72 | isa = PBXGroup; 73 | children = ( 74 | CC367DAF1A5534E800B87159 /* Classes */, 75 | CC367D881A55348300B87159 /* NSDate+SRGFekable */, 76 | CC367DA21A55348400B87159 /* NSDate+SRGFekableTests */, 77 | CC367D871A55348300B87159 /* Products */, 78 | ); 79 | sourceTree = ""; 80 | }; 81 | CC367D871A55348300B87159 /* Products */ = { 82 | isa = PBXGroup; 83 | children = ( 84 | CC367D861A55348300B87159 /* NSDate+SRGFekable.app */, 85 | CC367D9F1A55348400B87159 /* NSDate+SRGFekableTests.xctest */, 86 | ); 87 | name = Products; 88 | sourceTree = ""; 89 | }; 90 | CC367D881A55348300B87159 /* NSDate+SRGFekable */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | CC367D8D1A55348300B87159 /* AppDelegate.h */, 94 | CC367D8E1A55348300B87159 /* AppDelegate.m */, 95 | CC367D901A55348300B87159 /* ViewController.h */, 96 | CC367D911A55348300B87159 /* ViewController.m */, 97 | CC367D931A55348300B87159 /* Main.storyboard */, 98 | CC367D961A55348300B87159 /* Images.xcassets */, 99 | CC367D981A55348300B87159 /* LaunchScreen.xib */, 100 | CC367D891A55348300B87159 /* Supporting Files */, 101 | ); 102 | path = "NSDate+SRGFekable"; 103 | sourceTree = ""; 104 | }; 105 | CC367D891A55348300B87159 /* Supporting Files */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | CC367D8A1A55348300B87159 /* Info.plist */, 109 | CC367D8B1A55348300B87159 /* main.m */, 110 | ); 111 | name = "Supporting Files"; 112 | sourceTree = ""; 113 | }; 114 | CC367DA21A55348400B87159 /* NSDate+SRGFekableTests */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | CC367DA51A55348400B87159 /* NSDate_SRGFekableTests.m */, 118 | CC367DA31A55348400B87159 /* Supporting Files */, 119 | ); 120 | path = "NSDate+SRGFekableTests"; 121 | sourceTree = ""; 122 | }; 123 | CC367DA31A55348400B87159 /* Supporting Files */ = { 124 | isa = PBXGroup; 125 | children = ( 126 | CC367DA41A55348400B87159 /* Info.plist */, 127 | ); 128 | name = "Supporting Files"; 129 | sourceTree = ""; 130 | }; 131 | CC367DAF1A5534E800B87159 /* Classes */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | CC367DB61A55359E00B87159 /* NSDate+SRGFekable.h */, 135 | CC367DB71A55359E00B87159 /* NSDate+SRGFekable.m */, 136 | CC367DB91A55BCBF00B87159 /* SRGFakableViewController.h */, 137 | CC367DBA1A55BCBF00B87159 /* SRGFakableViewController.m */, 138 | CC367DBB1A55BCBF00B87159 /* SRGFakableViewController.xib */, 139 | ); 140 | path = Classes; 141 | sourceTree = ""; 142 | }; 143 | /* End PBXGroup section */ 144 | 145 | /* Begin PBXNativeTarget section */ 146 | CC367D851A55348300B87159 /* NSDate+SRGFekable */ = { 147 | isa = PBXNativeTarget; 148 | buildConfigurationList = CC367DA91A55348400B87159 /* Build configuration list for PBXNativeTarget "NSDate+SRGFekable" */; 149 | buildPhases = ( 150 | CC367D821A55348300B87159 /* Sources */, 151 | CC367D831A55348300B87159 /* Frameworks */, 152 | CC367D841A55348300B87159 /* Resources */, 153 | ); 154 | buildRules = ( 155 | ); 156 | dependencies = ( 157 | ); 158 | name = "NSDate+SRGFekable"; 159 | productName = "NSDate+SRGFekable"; 160 | productReference = CC367D861A55348300B87159 /* NSDate+SRGFekable.app */; 161 | productType = "com.apple.product-type.application"; 162 | }; 163 | CC367D9E1A55348400B87159 /* NSDate+SRGFekableTests */ = { 164 | isa = PBXNativeTarget; 165 | buildConfigurationList = CC367DAC1A55348400B87159 /* Build configuration list for PBXNativeTarget "NSDate+SRGFekableTests" */; 166 | buildPhases = ( 167 | CC367D9B1A55348400B87159 /* Sources */, 168 | CC367D9C1A55348400B87159 /* Frameworks */, 169 | CC367D9D1A55348400B87159 /* Resources */, 170 | ); 171 | buildRules = ( 172 | ); 173 | dependencies = ( 174 | CC367DA11A55348400B87159 /* PBXTargetDependency */, 175 | ); 176 | name = "NSDate+SRGFekableTests"; 177 | productName = "NSDate+SRGFekableTests"; 178 | productReference = CC367D9F1A55348400B87159 /* NSDate+SRGFekableTests.xctest */; 179 | productType = "com.apple.product-type.bundle.unit-test"; 180 | }; 181 | /* End PBXNativeTarget section */ 182 | 183 | /* Begin PBXProject section */ 184 | CC367D7E1A55348300B87159 /* Project object */ = { 185 | isa = PBXProject; 186 | attributes = { 187 | LastUpgradeCheck = 0610; 188 | ORGANIZATIONNAME = soragoto; 189 | TargetAttributes = { 190 | CC367D851A55348300B87159 = { 191 | CreatedOnToolsVersion = 6.1; 192 | }; 193 | CC367D9E1A55348400B87159 = { 194 | CreatedOnToolsVersion = 6.1; 195 | TestTargetID = CC367D851A55348300B87159; 196 | }; 197 | }; 198 | }; 199 | buildConfigurationList = CC367D811A55348300B87159 /* Build configuration list for PBXProject "NSDate+SRGFekable" */; 200 | compatibilityVersion = "Xcode 3.2"; 201 | developmentRegion = English; 202 | hasScannedForEncodings = 0; 203 | knownRegions = ( 204 | en, 205 | Base, 206 | ); 207 | mainGroup = CC367D7D1A55348300B87159; 208 | productRefGroup = CC367D871A55348300B87159 /* Products */; 209 | projectDirPath = ""; 210 | projectRoot = ""; 211 | targets = ( 212 | CC367D851A55348300B87159 /* NSDate+SRGFekable */, 213 | CC367D9E1A55348400B87159 /* NSDate+SRGFekableTests */, 214 | ); 215 | }; 216 | /* End PBXProject section */ 217 | 218 | /* Begin PBXResourcesBuildPhase section */ 219 | CC367D841A55348300B87159 /* Resources */ = { 220 | isa = PBXResourcesBuildPhase; 221 | buildActionMask = 2147483647; 222 | files = ( 223 | CC367D951A55348300B87159 /* Main.storyboard in Resources */, 224 | CC367D9A1A55348300B87159 /* LaunchScreen.xib in Resources */, 225 | CC367DBD1A55BCBF00B87159 /* SRGFakableViewController.xib in Resources */, 226 | CC367D971A55348300B87159 /* Images.xcassets in Resources */, 227 | ); 228 | runOnlyForDeploymentPostprocessing = 0; 229 | }; 230 | CC367D9D1A55348400B87159 /* Resources */ = { 231 | isa = PBXResourcesBuildPhase; 232 | buildActionMask = 2147483647; 233 | files = ( 234 | ); 235 | runOnlyForDeploymentPostprocessing = 0; 236 | }; 237 | /* End PBXResourcesBuildPhase section */ 238 | 239 | /* Begin PBXSourcesBuildPhase section */ 240 | CC367D821A55348300B87159 /* Sources */ = { 241 | isa = PBXSourcesBuildPhase; 242 | buildActionMask = 2147483647; 243 | files = ( 244 | CC367D921A55348300B87159 /* ViewController.m in Sources */, 245 | CC367D8F1A55348300B87159 /* AppDelegate.m in Sources */, 246 | CC367DB81A55359E00B87159 /* NSDate+SRGFekable.m in Sources */, 247 | CC367D8C1A55348300B87159 /* main.m in Sources */, 248 | CC367DBC1A55BCBF00B87159 /* SRGFakableViewController.m in Sources */, 249 | ); 250 | runOnlyForDeploymentPostprocessing = 0; 251 | }; 252 | CC367D9B1A55348400B87159 /* Sources */ = { 253 | isa = PBXSourcesBuildPhase; 254 | buildActionMask = 2147483647; 255 | files = ( 256 | CC367DA61A55348400B87159 /* NSDate_SRGFekableTests.m in Sources */, 257 | ); 258 | runOnlyForDeploymentPostprocessing = 0; 259 | }; 260 | /* End PBXSourcesBuildPhase section */ 261 | 262 | /* Begin PBXTargetDependency section */ 263 | CC367DA11A55348400B87159 /* PBXTargetDependency */ = { 264 | isa = PBXTargetDependency; 265 | target = CC367D851A55348300B87159 /* NSDate+SRGFekable */; 266 | targetProxy = CC367DA01A55348400B87159 /* PBXContainerItemProxy */; 267 | }; 268 | /* End PBXTargetDependency section */ 269 | 270 | /* Begin PBXVariantGroup section */ 271 | CC367D931A55348300B87159 /* Main.storyboard */ = { 272 | isa = PBXVariantGroup; 273 | children = ( 274 | CC367D941A55348300B87159 /* Base */, 275 | ); 276 | name = Main.storyboard; 277 | sourceTree = ""; 278 | }; 279 | CC367D981A55348300B87159 /* LaunchScreen.xib */ = { 280 | isa = PBXVariantGroup; 281 | children = ( 282 | CC367D991A55348300B87159 /* Base */, 283 | ); 284 | name = LaunchScreen.xib; 285 | sourceTree = ""; 286 | }; 287 | /* End PBXVariantGroup section */ 288 | 289 | /* Begin XCBuildConfiguration section */ 290 | CC367DA71A55348400B87159 /* Debug */ = { 291 | isa = XCBuildConfiguration; 292 | buildSettings = { 293 | ALWAYS_SEARCH_USER_PATHS = NO; 294 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 295 | CLANG_CXX_LIBRARY = "libc++"; 296 | CLANG_ENABLE_MODULES = YES; 297 | CLANG_ENABLE_OBJC_ARC = YES; 298 | CLANG_WARN_BOOL_CONVERSION = YES; 299 | CLANG_WARN_CONSTANT_CONVERSION = YES; 300 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 301 | CLANG_WARN_EMPTY_BODY = YES; 302 | CLANG_WARN_ENUM_CONVERSION = YES; 303 | CLANG_WARN_INT_CONVERSION = YES; 304 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 305 | CLANG_WARN_UNREACHABLE_CODE = YES; 306 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 307 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 308 | COPY_PHASE_STRIP = NO; 309 | ENABLE_STRICT_OBJC_MSGSEND = YES; 310 | GCC_C_LANGUAGE_STANDARD = gnu99; 311 | GCC_DYNAMIC_NO_PIC = NO; 312 | GCC_OPTIMIZATION_LEVEL = 0; 313 | GCC_PREPROCESSOR_DEFINITIONS = ( 314 | "DEBUG=1", 315 | "$(inherited)", 316 | ); 317 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 318 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 319 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 320 | GCC_WARN_UNDECLARED_SELECTOR = YES; 321 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 322 | GCC_WARN_UNUSED_FUNCTION = YES; 323 | GCC_WARN_UNUSED_VARIABLE = YES; 324 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 325 | MTL_ENABLE_DEBUG_INFO = YES; 326 | ONLY_ACTIVE_ARCH = YES; 327 | SDKROOT = iphoneos; 328 | TARGETED_DEVICE_FAMILY = "1,2"; 329 | }; 330 | name = Debug; 331 | }; 332 | CC367DA81A55348400B87159 /* Release */ = { 333 | isa = XCBuildConfiguration; 334 | buildSettings = { 335 | ALWAYS_SEARCH_USER_PATHS = NO; 336 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 337 | CLANG_CXX_LIBRARY = "libc++"; 338 | CLANG_ENABLE_MODULES = YES; 339 | CLANG_ENABLE_OBJC_ARC = YES; 340 | CLANG_WARN_BOOL_CONVERSION = YES; 341 | CLANG_WARN_CONSTANT_CONVERSION = YES; 342 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 343 | CLANG_WARN_EMPTY_BODY = YES; 344 | CLANG_WARN_ENUM_CONVERSION = YES; 345 | CLANG_WARN_INT_CONVERSION = YES; 346 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 347 | CLANG_WARN_UNREACHABLE_CODE = YES; 348 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 349 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 350 | COPY_PHASE_STRIP = YES; 351 | ENABLE_NS_ASSERTIONS = NO; 352 | ENABLE_STRICT_OBJC_MSGSEND = YES; 353 | GCC_C_LANGUAGE_STANDARD = gnu99; 354 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 355 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 356 | GCC_WARN_UNDECLARED_SELECTOR = YES; 357 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 358 | GCC_WARN_UNUSED_FUNCTION = YES; 359 | GCC_WARN_UNUSED_VARIABLE = YES; 360 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 361 | MTL_ENABLE_DEBUG_INFO = NO; 362 | SDKROOT = iphoneos; 363 | TARGETED_DEVICE_FAMILY = "1,2"; 364 | VALIDATE_PRODUCT = YES; 365 | }; 366 | name = Release; 367 | }; 368 | CC367DAA1A55348400B87159 /* Debug */ = { 369 | isa = XCBuildConfiguration; 370 | buildSettings = { 371 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 372 | INFOPLIST_FILE = "NSDate+SRGFekable/Info.plist"; 373 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 374 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 375 | PRODUCT_NAME = "$(TARGET_NAME)"; 376 | }; 377 | name = Debug; 378 | }; 379 | CC367DAB1A55348400B87159 /* Release */ = { 380 | isa = XCBuildConfiguration; 381 | buildSettings = { 382 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 383 | INFOPLIST_FILE = "NSDate+SRGFekable/Info.plist"; 384 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 385 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 386 | PRODUCT_NAME = "$(TARGET_NAME)"; 387 | }; 388 | name = Release; 389 | }; 390 | CC367DAD1A55348400B87159 /* Debug */ = { 391 | isa = XCBuildConfiguration; 392 | buildSettings = { 393 | BUNDLE_LOADER = "$(TEST_HOST)"; 394 | FRAMEWORK_SEARCH_PATHS = ( 395 | "$(SDKROOT)/Developer/Library/Frameworks", 396 | "$(inherited)", 397 | ); 398 | GCC_PREPROCESSOR_DEFINITIONS = ( 399 | "DEBUG=1", 400 | "$(inherited)", 401 | ); 402 | INFOPLIST_FILE = "NSDate+SRGFekableTests/Info.plist"; 403 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 404 | PRODUCT_NAME = "$(TARGET_NAME)"; 405 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/NSDate+SRGFekable.app/NSDate+SRGFekable"; 406 | }; 407 | name = Debug; 408 | }; 409 | CC367DAE1A55348400B87159 /* Release */ = { 410 | isa = XCBuildConfiguration; 411 | buildSettings = { 412 | BUNDLE_LOADER = "$(TEST_HOST)"; 413 | FRAMEWORK_SEARCH_PATHS = ( 414 | "$(SDKROOT)/Developer/Library/Frameworks", 415 | "$(inherited)", 416 | ); 417 | INFOPLIST_FILE = "NSDate+SRGFekableTests/Info.plist"; 418 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 419 | PRODUCT_NAME = "$(TARGET_NAME)"; 420 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/NSDate+SRGFekable.app/NSDate+SRGFekable"; 421 | }; 422 | name = Release; 423 | }; 424 | /* End XCBuildConfiguration section */ 425 | 426 | /* Begin XCConfigurationList section */ 427 | CC367D811A55348300B87159 /* Build configuration list for PBXProject "NSDate+SRGFekable" */ = { 428 | isa = XCConfigurationList; 429 | buildConfigurations = ( 430 | CC367DA71A55348400B87159 /* Debug */, 431 | CC367DA81A55348400B87159 /* Release */, 432 | ); 433 | defaultConfigurationIsVisible = 0; 434 | defaultConfigurationName = Release; 435 | }; 436 | CC367DA91A55348400B87159 /* Build configuration list for PBXNativeTarget "NSDate+SRGFekable" */ = { 437 | isa = XCConfigurationList; 438 | buildConfigurations = ( 439 | CC367DAA1A55348400B87159 /* Debug */, 440 | CC367DAB1A55348400B87159 /* Release */, 441 | ); 442 | defaultConfigurationIsVisible = 0; 443 | defaultConfigurationName = Release; 444 | }; 445 | CC367DAC1A55348400B87159 /* Build configuration list for PBXNativeTarget "NSDate+SRGFekableTests" */ = { 446 | isa = XCConfigurationList; 447 | buildConfigurations = ( 448 | CC367DAD1A55348400B87159 /* Debug */, 449 | CC367DAE1A55348400B87159 /* Release */, 450 | ); 451 | defaultConfigurationIsVisible = 0; 452 | defaultConfigurationName = Release; 453 | }; 454 | /* End XCConfigurationList section */ 455 | }; 456 | rootObject = CC367D7E1A55348300B87159 /* Project object */; 457 | } 458 | --------------------------------------------------------------------------------