├── example.gif ├── screenshots ├── pixelperfect-screen1.png └── pixelperfect-screen2.png ├── PixelPerfect-Example ├── mockups │ └── add-point.png ├── resources │ ├── background@2x.png │ ├── add-point-icon.png │ ├── add-password-icon.png │ ├── add-point-icon@2x.png │ ├── add-point-icon@3x.png │ ├── add-password-icon@2x.png │ ├── add-password-icon@3x.png │ ├── facebook-btn-normal.png │ ├── facebook-btn-normal@2x.png │ ├── facebook-btn-normal@3x.png │ ├── facebook-btn-selected.png │ ├── facebook-btn-selected@2x.png │ └── facebook-btn-selected@3x.png ├── classes │ ├── ExampleViewController.h │ └── ExampleViewController.m ├── AppDelegate.h ├── main.m ├── AppDelegate.m ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist └── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── PixelPerfect-Example.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── project.pbxproj ├── PixelPerfect ├── PIXELWindow.h ├── PIXELViewController.h ├── UIImage+ColorInverse.h ├── PIXELSettingsViewController.h ├── PIXELPerfect+Public.h ├── PIXELWindow.m ├── UIImage+ColorInverse.m ├── PIXELPerfect.h ├── PIXELSettingsViewController.m ├── PIXELPerfect.m └── PIXELViewController.m ├── .gitignore ├── PixelPerfect.podspec ├── PixelPerfectTests ├── Info.plist └── PixelPerfectTests.m ├── LICENSE └── README.md /example.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuraware/PixelPerfect/HEAD/example.gif -------------------------------------------------------------------------------- /screenshots/pixelperfect-screen1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuraware/PixelPerfect/HEAD/screenshots/pixelperfect-screen1.png -------------------------------------------------------------------------------- /screenshots/pixelperfect-screen2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuraware/PixelPerfect/HEAD/screenshots/pixelperfect-screen2.png -------------------------------------------------------------------------------- /PixelPerfect-Example/mockups/add-point.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuraware/PixelPerfect/HEAD/PixelPerfect-Example/mockups/add-point.png -------------------------------------------------------------------------------- /PixelPerfect-Example/resources/background@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuraware/PixelPerfect/HEAD/PixelPerfect-Example/resources/background@2x.png -------------------------------------------------------------------------------- /PixelPerfect-Example/resources/add-point-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuraware/PixelPerfect/HEAD/PixelPerfect-Example/resources/add-point-icon.png -------------------------------------------------------------------------------- /PixelPerfect-Example/resources/add-password-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuraware/PixelPerfect/HEAD/PixelPerfect-Example/resources/add-password-icon.png -------------------------------------------------------------------------------- /PixelPerfect-Example/resources/add-point-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuraware/PixelPerfect/HEAD/PixelPerfect-Example/resources/add-point-icon@2x.png -------------------------------------------------------------------------------- /PixelPerfect-Example/resources/add-point-icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuraware/PixelPerfect/HEAD/PixelPerfect-Example/resources/add-point-icon@3x.png -------------------------------------------------------------------------------- /PixelPerfect-Example/resources/add-password-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuraware/PixelPerfect/HEAD/PixelPerfect-Example/resources/add-password-icon@2x.png -------------------------------------------------------------------------------- /PixelPerfect-Example/resources/add-password-icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuraware/PixelPerfect/HEAD/PixelPerfect-Example/resources/add-password-icon@3x.png -------------------------------------------------------------------------------- /PixelPerfect-Example/resources/facebook-btn-normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuraware/PixelPerfect/HEAD/PixelPerfect-Example/resources/facebook-btn-normal.png -------------------------------------------------------------------------------- /PixelPerfect-Example/resources/facebook-btn-normal@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuraware/PixelPerfect/HEAD/PixelPerfect-Example/resources/facebook-btn-normal@2x.png -------------------------------------------------------------------------------- /PixelPerfect-Example/resources/facebook-btn-normal@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuraware/PixelPerfect/HEAD/PixelPerfect-Example/resources/facebook-btn-normal@3x.png -------------------------------------------------------------------------------- /PixelPerfect-Example/resources/facebook-btn-selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuraware/PixelPerfect/HEAD/PixelPerfect-Example/resources/facebook-btn-selected.png -------------------------------------------------------------------------------- /PixelPerfect-Example/resources/facebook-btn-selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuraware/PixelPerfect/HEAD/PixelPerfect-Example/resources/facebook-btn-selected@2x.png -------------------------------------------------------------------------------- /PixelPerfect-Example/resources/facebook-btn-selected@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuraware/PixelPerfect/HEAD/PixelPerfect-Example/resources/facebook-btn-selected@3x.png -------------------------------------------------------------------------------- /PixelPerfect-Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PixelPerfect/PIXELWindow.h: -------------------------------------------------------------------------------- 1 | // 2 | // PerfectWindow.h 3 | // PixelPerfect 4 | // 5 | // Created by Yuri on 5/2/15. 6 | // Copyright (c) 2015 Yuri Kobets. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface PIXELWindow : UIWindow 12 | 13 | - (void)removeSubviews; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /PixelPerfect/PIXELViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // PPPerfectViewController.h 3 | // PerfectPixel-Example 4 | // 5 | // Created by Yuri on 4/30/15. 6 | // Copyright (c) 2015 Yuri Kobets. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface PIXELViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /PixelPerfect/UIImage+ColorInverse.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+ColorInverse.h 3 | // PixelPerfect 4 | // 5 | // Created by Yuri on 5/2/15. 6 | // Copyright (c) 2015 Yuri Kobets. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIImage (ColorInverse) 12 | 13 | - (UIImage *)inverseColors; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /PixelPerfect-Example/classes/ExampleViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ExampleViewController.h 3 | // PixelPerfect-Example 4 | // 5 | // Created by Yuri on 5/14/15. 6 | // Copyright (c) 2015 Yuri Kobets. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ExampleViewController : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /PixelPerfect/PIXELSettingsViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // PIXELSettingsViewController.h 3 | // PixelPerfect-Example 4 | // 5 | // Created by Yuri on 5/17/15. 6 | // Copyright (c) 2015 Yuri Kobets. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface PIXELSettingsViewController : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /PixelPerfect/PIXELPerfect+Public.h: -------------------------------------------------------------------------------- 1 | // 2 | // PIXELPerfect+Public.h 3 | // PixelPerfect-Example 4 | // 5 | // Created by Yuri on 8/31/15. 6 | // Copyright (c) 2015 Yuri Kobets. All rights reserved. 7 | // 8 | 9 | #ifndef PixelPerfect_Example_PIXELPerfect_Public_h 10 | #define PixelPerfect_Example_PIXELPerfect_Public_h 11 | 12 | #import "PIXELPerfect.h" 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /PixelPerfect-Example/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // PixelPerfect 4 | // 5 | // Created by Yuri on 5/14/15. 6 | // Copyright (c) 2015 Yuri Kobets. 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 | -------------------------------------------------------------------------------- /PixelPerfect-Example/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // PixelPerfect 4 | // 5 | // Created by Yuri on 5/14/15. 6 | // Copyright (c) 2015 Yuri Kobets. 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 | -------------------------------------------------------------------------------- /.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 | #AppCode 21 | *.idea 22 | 23 | # CocoaPods 24 | # 25 | # We recommend against adding the Pods directory to your .gitignore. However 26 | # you should judge for yourself, the pros and cons are mentioned at: 27 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 28 | # 29 | #Pods/ 30 | -------------------------------------------------------------------------------- /PixelPerfect/PIXELWindow.m: -------------------------------------------------------------------------------- 1 | // 2 | // PerfectWindow.m 3 | // PixelPerfect 4 | // 5 | // Created by Yuri on 5/2/15. 6 | // Copyright (c) 2015 Yuri Kobets. All rights reserved. 7 | // 8 | 9 | #import "PIXELWindow.h" 10 | 11 | @implementation PIXELWindow 12 | 13 | - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 14 | { 15 | // accept only touches on status bar 16 | if (point.y < 20.) { 17 | return [super hitTest:point withEvent:event]; 18 | } 19 | return nil; 20 | } 21 | 22 | - (void)removeSubviews 23 | { 24 | for (UIView *view in self.subviews) { 25 | [view removeFromSuperview]; 26 | } 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /PixelPerfect/UIImage+ColorInverse.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+ColorInverse.m 3 | // PixelPerfect 4 | // 5 | // Created by Yuri on 5/2/15. 6 | // Copyright (c) 2015 Yuri Kobets. All rights reserved. 7 | // 8 | 9 | #import "UIImage+ColorInverse.h" 10 | #import 11 | 12 | @implementation UIImage (ColorInverse) 13 | 14 | - (UIImage *)inverseColors 15 | { 16 | CIImage *coreImage = [CIImage imageWithCGImage:self.CGImage]; 17 | CIFilter *filter = [CIFilter filterWithName:@"CIColorInvert"]; 18 | [filter setValue:coreImage forKey:kCIInputImageKey]; 19 | CIImage *result = [filter valueForKey:kCIOutputImageKey]; 20 | return [UIImage imageWithCIImage:result]; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /PixelPerfect.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'PixelPerfect' 3 | s.version = '0.1.0' 4 | s.platform = :ios, '7.0' 5 | s.license = 'MIT' 6 | s.summary = 'Compare mockup design with your interface on iOS' 7 | s.description = 'Compare mockup design images with user interface on iOS. Get the diff of images using inversion or transparency of design mockups.' 8 | s.homepage = 'https://github.com/ykobets/PixelPerfect' 9 | s.authors = { 'Yuri Kobets' => 'y.kobets@me.com' } 10 | s.source = { :git => 'https://github.com/ykobets/PixelPerfect.git', :tag => s.version.to_s } 11 | s.source_files = 'PixelPerfect' 12 | s.requires_arc = true 13 | s.frameworks = ['CoreImage', 'UIKit'] 14 | s.public_header_files = 'PixelPerfect/PIXELPerfect+Public.h' 15 | end -------------------------------------------------------------------------------- /PixelPerfectTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.perfectpixel.ios.$(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 | -------------------------------------------------------------------------------- /PixelPerfect-Example/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // PixelPerfect 4 | // 5 | // Created by Yuri on 5/14/15. 6 | // Copyright (c) 2015 Yuri Kobets. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | #import "PIXELPerfect.h" 12 | #import "ExampleViewController.h" 13 | 14 | @interface AppDelegate () 15 | 16 | @end 17 | 18 | @implementation AppDelegate 19 | 20 | 21 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 22 | 23 | 24 | // Use it only in DEBUG mode 25 | // #ifdef DEBUG 26 | // 'code' 27 | // #else 28 | 29 | 30 | NSDictionary *classesImagesDictionary = @{ NSStringFromClass([ExampleViewController class]) : @"add-point.png" }; 31 | [[PIXELPerfect shared] setControllersClassesAndImages:classesImagesDictionary]; 32 | 33 | 34 | return YES; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /PixelPerfectTests/PixelPerfectTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // PixelPerfectTests.m 3 | // PixelPerfectTests 4 | // 5 | // Created by Yuri on 5/14/15. 6 | // Copyright (c) 2015 Yuri Kobets. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface PixelPerfectTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation PixelPerfectTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Yuri Kobets 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 | -------------------------------------------------------------------------------- /PixelPerfect-Example/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 | } -------------------------------------------------------------------------------- /PixelPerfect/PIXELPerfect.h: -------------------------------------------------------------------------------- 1 | // 2 | // PPPerfectManager.h 3 | // PerfectPixel-Project 4 | // 5 | // Created by Yuri on 4/30/15. 6 | // Copyright (c) 2015 Yuri Kobets. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @class PIXELWindow; 13 | 14 | @interface PIXELPerfect : NSObject 15 | 16 | @property (nonatomic,strong) PIXELWindow *overlayWindow; 17 | 18 | @property (nonatomic,strong) Class recentUsedClass; 19 | 20 | @property (nonatomic,assign, getter=isShowingOnStart) BOOL showOnStart; 21 | @property (nonatomic,assign, getter=isImageInverted) BOOL imageInverted; 22 | @property (nonatomic,assign) float imageAlpha; 23 | 24 | + (PIXELPerfect *)shared; 25 | 26 | /** 27 | Sets dictionary with keys as `UIViewController class` string and values as corresponding mockup image name 28 | The dictionary with structure @{NSStringFromClass([UIViewController class]) : @"image.png" } 29 | @param classesImagesDict - dictionary with `keys` - NSString of class, `values` - image name 30 | 31 | key - NSString representation of UIViewController subclass 32 | value - image name. Note that image should be added to bundle 33 | */ 34 | - (void)setControllersClassesAndImages:(NSDictionary *)classesImagesDict; 35 | 36 | /** 37 | Retrieves an image for specific UIViewController subclass 38 | 39 | @param aClass the subclass of UIViewController 40 | 41 | @return image of corresponding subclass of UIViewController 42 | */ 43 | - (UIImage *)imageForControllerClass:(Class)aClass; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /PixelPerfect-Example/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.perfectpixel.ios.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 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 | -------------------------------------------------------------------------------- /PixelPerfect-Example/classes/ExampleViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ExampleViewController.m 3 | // PixelPerfect-Example 4 | // 5 | // Created by Yuri on 5/14/15. 6 | // Copyright (c) 2015 Yuri Kobets. All rights reserved. 7 | // 8 | 9 | #import "ExampleViewController.h" 10 | 11 | @implementation ExampleViewController 12 | 13 | - (void)viewDidLoad 14 | { 15 | [super viewDidLoad]; 16 | 17 | self.title = @"New point"; 18 | 19 | self.navigationController.navigationBar.barTintColor = [UIColor colorWithRed:20/255. 20 | green:162./255. 21 | blue:218./255. 22 | alpha:1.0]; 23 | self.navigationController.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName : [UIColor whiteColor]}; 24 | 25 | UIBarButtonItem *addItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel 26 | target:nil 27 | action:nil]; 28 | addItem.tintColor = [UIColor whiteColor]; 29 | UIBarButtonItem *saveItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave 30 | target:nil 31 | action:nil]; 32 | saveItem.tintColor = [UIColor whiteColor]; 33 | 34 | self.navigationItem.leftBarButtonItem = addItem; 35 | self.navigationItem.rightBarButtonItem = saveItem; 36 | 37 | UIImageView *backgroundImageView = [[UIImageView alloc] initWithFrame:self.view.bounds]; 38 | [backgroundImageView setImage:[UIImage imageNamed:@"background.png"]]; 39 | 40 | self.tableView.backgroundView = backgroundImageView; 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PixelPerfect 2 | [![Supported Plateforms](https://img.shields.io/badge/platform-ios-brightgreen.svg)](https://github.com/ykobets/PixelPerfect) 3 | 4 | Compare mockup design images with a user interface on iOS, get the diff of images using inversion or transparency of design mockups. 5 | 6 | ##Features 7 | * show a mockup image imposed with a user interface 8 | * change a mockup image transparency 9 | * invert colors of a mockup image to see design difference 10 | 11 | ![](https://github.com/ykobets/PixelPerfect/blob/master/example.gif) 12 | 13 | ##Usage 14 | 15 | 1. Copy mockup design images to project. 16 | 2. Create dictionary with class name and corresponding mockup image name. 17 | 3. Instantiate `PIXELPerfect` with this dictionary in application delegate class. 18 | 19 | In the status bar there appears buttons "show/hide" and "settings". 20 | Now you can compare mockup image with actual user interface. 21 | 22 | `AppDelegate.m` 23 | 24 | `Objective-C` 25 | 26 | ``` 27 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 28 | 29 | #ifdef DEBUG 30 | NSDictionary *classesImagesDictionary = @{ NSStringFromClass([ExampleViewController class]) : @"viewcontroller-mockup.png" }; 31 | [[PIXELPerfect shared] setControllersClassesAndImages:classesImagesDictionary]; 32 | #endif 33 | 34 | return YES; 35 | } 36 | ``` 37 | 38 | `Swift` 39 | ``` 40 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 41 | 42 | let classesImagesDictionary = [NSStringFromClass(ViewController.self) : "viewcontroller-mockup.png"] 43 | PIXELPerfect.shared().setControllersClassesAndImages(classesImagesDictionary) 44 | 45 | return true 46 | } 47 | ``` 48 | 49 | ##Install 50 | 51 | Install with [CocoaPods](http://cocoapods.org/). Add next lines to `Podfile` 52 | 53 | ``` 54 | platform :ios, '7.0' 55 | 56 | pod 'PixelPerfect' 57 | ``` 58 | 59 | In case of using Swift project 60 | 61 | ``` 62 | platform :ios, '7.0' 63 | use_frameworks! 64 | 65 | pod 'PixelPerfect' 66 | ``` 67 | -------------------------------------------------------------------------------- /PixelPerfect-Example/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 | -------------------------------------------------------------------------------- /PixelPerfect/PIXELSettingsViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // PIXELSettingsViewController.m 3 | // PixelPerfect-Example 4 | // 5 | // Created by Yuri on 5/17/15. 6 | // Copyright (c) 2015 Yuri Kobets. All rights reserved. 7 | // 8 | 9 | #import "PIXELSettingsViewController.h" 10 | #import "PIXELPerfect.h" 11 | 12 | @interface PIXELSettingsViewController () 13 | 14 | @end 15 | 16 | @implementation PIXELSettingsViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | 21 | self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Back" 22 | style:UIBarButtonItemStylePlain 23 | target:self 24 | action:@selector(backPressed)]; 25 | } 26 | 27 | - (void)backPressed 28 | { 29 | [self dismissViewControllerAnimated:YES completion:nil]; 30 | } 31 | 32 | #pragma mark - Table view data source 33 | 34 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 35 | { 36 | return 3; 37 | } 38 | 39 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 40 | { 41 | return 1; 42 | } 43 | 44 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 45 | { 46 | UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]; 47 | 48 | if (indexPath.section == 0) { //invert cell 49 | 50 | cell.textLabel.text = @"Show inverted image"; 51 | 52 | UISwitch *invertSwitch = [[UISwitch alloc] init]; 53 | invertSwitch.center = cell.contentView.center; 54 | CGRect rect = invertSwitch.frame; 55 | rect.origin.x = CGRectGetWidth(self.view.frame) - CGRectGetWidth(rect) - 10.; 56 | invertSwitch.frame = rect; 57 | 58 | invertSwitch.on = [PIXELPerfect shared].isImageInverted; 59 | 60 | [invertSwitch addTarget:self action:@selector(didChangeInvertedSwitch:) forControlEvents:UIControlEventValueChanged]; 61 | 62 | [cell.contentView addSubview:invertSwitch]; 63 | 64 | } else if (indexPath.section == 1) { // alpha cell 65 | 66 | cell.textLabel.text = @"Alpha"; 67 | UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(80., 10., CGRectGetWidth(self.view.bounds) - 90., 20.)]; 68 | 69 | [slider addTarget:self action:@selector(didChangeSliderImageAlpha:) forControlEvents:UIControlEventValueChanged]; 70 | 71 | slider.value = [PIXELPerfect shared].imageAlpha; 72 | [cell.contentView addSubview:slider]; 73 | 74 | } else if (indexPath.section == 2) { // show on start 75 | 76 | cell.textLabel.text = @"Show mockup image on start"; 77 | 78 | UISwitch *showSwitch = [[UISwitch alloc] init]; 79 | showSwitch.center = cell.contentView.center; 80 | CGRect rect = showSwitch.frame; 81 | rect.origin.x = CGRectGetWidth(self.view.frame) - CGRectGetWidth(rect) - 10.; 82 | showSwitch.frame = rect; 83 | 84 | showSwitch.on = [PIXELPerfect shared].isShowingOnStart; 85 | 86 | [showSwitch addTarget:self action:@selector(didChangeShowOnStartSwitch:) forControlEvents:UIControlEventValueChanged]; 87 | 88 | [cell.contentView addSubview:showSwitch]; 89 | } 90 | 91 | return cell; 92 | } 93 | 94 | #pragma mark - 95 | 96 | - (void)didChangeInvertedSwitch:(UISwitch *)sender 97 | { 98 | [[PIXELPerfect shared] setImageInverted:sender.on]; 99 | } 100 | 101 | - (void)didChangeSliderImageAlpha:(UISlider *)sender 102 | { 103 | [[PIXELPerfect shared] setImageAlpha:sender.value]; 104 | } 105 | 106 | - (void)didChangeShowOnStartSwitch:(UISwitch *)sender 107 | { 108 | [[PIXELPerfect shared] setShowOnStart:sender.on]; 109 | } 110 | 111 | @end 112 | -------------------------------------------------------------------------------- /PixelPerfect/PIXELPerfect.m: -------------------------------------------------------------------------------- 1 | // 2 | // PPPerfectManager.m 3 | // PerfectPixel-Project 4 | // 5 | // Created by Yuri on 4/30/15. 6 | // Copyright (c) 2015 Yuri Kobets. All rights reserved. 7 | // 8 | 9 | #import "PIXELPerfect.h" 10 | #import 11 | #import 12 | #import "PIXELViewController.h" 13 | #import "PIXELWindow.h" 14 | 15 | static PIXELPerfect *_sharedInstance = nil; 16 | 17 | static NSString * const kPIXELImageInvertedImageKey = @"kPIXELImageInvertedImageKey"; 18 | static NSString * const kPIXELImageAlphaKey = @"kPIXELImageAlphaKey"; 19 | static NSString * const kPIXELShowOnStartKey = @"kPIXELShowOnStartKey"; 20 | 21 | static float const kPIXELDefaultImageAlpha = 0.5; 22 | 23 | static IMP viewDidLoadImplementation = NULL; 24 | static IMP viewWillDisappearImplementation = NULL; 25 | static IMP viewDidAppearImplementation = NULL; 26 | static IMP viewWillAppearImplementation = NULL; 27 | 28 | @interface PIXELPerfect () 29 | 30 | - (void)swizzleUIViewControllerMethods; 31 | 32 | @property (nonatomic,strong) NSDictionary * classesImagesDict; 33 | 34 | @end 35 | 36 | @implementation PIXELPerfect 37 | 38 | + (PIXELPerfect *)shared 39 | { 40 | static dispatch_once_t onceToken; 41 | dispatch_once(&onceToken, ^{ 42 | _sharedInstance = [PIXELPerfect new]; 43 | }); 44 | 45 | return _sharedInstance; 46 | } 47 | 48 | - (instancetype)init 49 | { 50 | if (self = [super init]) { 51 | [self swizzleUIViewControllerMethods]; 52 | } 53 | 54 | return self; 55 | } 56 | 57 | - (void)setImageInverted:(BOOL)imageInverted 58 | { 59 | [[NSUserDefaults standardUserDefaults] setBool:imageInverted forKey:kPIXELImageInvertedImageKey]; 60 | [[NSUserDefaults standardUserDefaults] synchronize]; 61 | } 62 | 63 | - (BOOL)isImageInverted 64 | { 65 | return [[NSUserDefaults standardUserDefaults] boolForKey:kPIXELImageInvertedImageKey]; 66 | } 67 | 68 | - (void)setImageAlpha:(float)imageAlpha 69 | { 70 | [[NSUserDefaults standardUserDefaults] setFloat:imageAlpha forKey:kPIXELImageAlphaKey]; 71 | [[NSUserDefaults standardUserDefaults] synchronize]; 72 | } 73 | 74 | - (float)imageAlpha 75 | { 76 | if ([[NSUserDefaults standardUserDefaults] objectForKey:kPIXELImageAlphaKey] == nil) { 77 | return kPIXELDefaultImageAlpha; 78 | } 79 | 80 | return [[NSUserDefaults standardUserDefaults] floatForKey:kPIXELImageAlphaKey]; 81 | } 82 | 83 | - (void)setShowOnStart:(BOOL)showOnStart 84 | { 85 | [[NSUserDefaults standardUserDefaults] setBool:showOnStart forKey:kPIXELShowOnStartKey]; 86 | [[NSUserDefaults standardUserDefaults] synchronize]; 87 | } 88 | 89 | - (BOOL)isShowingOnStart 90 | { 91 | return [[NSUserDefaults standardUserDefaults] boolForKey:kPIXELShowOnStartKey]; 92 | } 93 | 94 | - (void)swizzleUIViewControllerMethods 95 | { 96 | static dispatch_once_t onceToken; 97 | dispatch_once(&onceToken, ^{ 98 | 99 | SEL viewDidLoadSelector = @selector(viewDidLoad); 100 | SEL viewWillDisappearSelector = @selector(viewWillDisappear:); 101 | SEL viewDidAppearSelector = @selector(viewDidAppear:); 102 | SEL viewWillAppearSelector = @selector(viewWillAppear:); 103 | 104 | viewDidLoadImplementation = class_getMethodImplementation([UIViewController class], viewDidLoadSelector); 105 | viewWillDisappearImplementation = class_getMethodImplementation([UIViewController class], viewWillDisappearSelector); 106 | viewDidAppearImplementation = class_getMethodImplementation([UIViewController class], viewDidAppearSelector); 107 | viewWillAppearImplementation = class_getMethodImplementation([UIViewController class], viewWillAppearSelector); 108 | 109 | Method originalViewDidLoadMethod = class_getInstanceMethod([UIViewController class], viewDidLoadSelector); 110 | Method swizzledViewDidLoadMethod = class_getInstanceMethod([PIXELViewController class], viewDidLoadSelector); 111 | 112 | Method originalViewWillDisappearMethod = class_getInstanceMethod([UIViewController class], viewWillDisappearSelector); 113 | Method swizzledViewWillDisappearMethod = class_getInstanceMethod([PIXELViewController class], viewWillDisappearSelector); 114 | 115 | Method originalViewDidAppearMethod = class_getInstanceMethod([UIViewController class], viewDidAppearSelector); 116 | Method swizzledViewDidAppearMethod = class_getInstanceMethod([PIXELViewController class], viewDidAppearSelector); 117 | 118 | Method originalViewWillAppearMethod = class_getInstanceMethod([UIViewController class], viewWillAppearSelector); 119 | Method swizzledViewWillAppearMethod = class_getInstanceMethod([PIXELViewController class], viewWillAppearSelector); 120 | 121 | method_exchangeImplementations(originalViewDidLoadMethod, swizzledViewDidLoadMethod); 122 | method_exchangeImplementations(originalViewWillDisappearMethod, swizzledViewWillDisappearMethod); 123 | method_exchangeImplementations(originalViewDidAppearMethod, swizzledViewDidAppearMethod); 124 | method_exchangeImplementations(originalViewWillAppearMethod, swizzledViewWillAppearMethod); 125 | }); 126 | } 127 | 128 | - (void)viewDidLoad 129 | { 130 | viewDidLoadImplementation(); 131 | } 132 | 133 | - (void)viewWillDisappear:(BOOL)animated 134 | { 135 | viewWillDisappearImplementation(); 136 | } 137 | 138 | - (void)viewDidAppear:(BOOL)animated 139 | { 140 | viewDidAppearImplementation(); 141 | } 142 | 143 | - (void)viewWillAppear:(BOOL)animated 144 | { 145 | viewWillAppearImplementation(); 146 | } 147 | 148 | - (void)setControllersClassesAndImages:(NSDictionary *)classesImagesDict 149 | { 150 | _classesImagesDict = classesImagesDict; 151 | } 152 | 153 | - (UIImage *)imageForControllerClass:(Class)aClass 154 | { 155 | NSString *keyClass = NSStringFromClass(aClass); 156 | NSString *imageName = self.classesImagesDict[keyClass]; 157 | 158 | return [UIImage imageNamed:imageName]; 159 | } 160 | 161 | - (UIWindow *)overlayWindow 162 | { 163 | if (_overlayWindow == nil) { 164 | _overlayWindow = [[PIXELWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 165 | _overlayWindow.windowLevel = UIWindowLevelStatusBar; 166 | _overlayWindow.hidden = NO; 167 | _overlayWindow.backgroundColor = [UIColor clearColor]; 168 | } 169 | 170 | return _overlayWindow; 171 | } 172 | 173 | @end 174 | -------------------------------------------------------------------------------- /PixelPerfect/PIXELViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // PPPerfectViewController.m 3 | // PerfectPixel-Example 4 | // 5 | // Created by Yuri on 4/30/15. 6 | // Copyright (c) 2015 Yuri Kobets. All rights reserved. 7 | // 8 | 9 | #import "PIXELViewController.h" 10 | #import "PIXELPerfect.h" 11 | #import "PIXELWindow.h" 12 | #import "UIImage+ColorInverse.h" 13 | #import 14 | #import "PIXELSettingsViewController.h" 15 | 16 | static NSInteger const kPIXELShowButtonTag = 1001; 17 | static NSInteger const kPIXELSettingsButtonTag = 1002; 18 | static NSInteger const kPIXELMockupImageViewTag = 1003; 19 | 20 | @interface PIXELViewController () 21 | { 22 | UIImageView *_mockupImageView; 23 | } 24 | 25 | @end 26 | 27 | @implementation PIXELViewController 28 | 29 | 30 | - (void)viewDidLoad 31 | { 32 | Class class = object_getClass(self); 33 | 34 | SEL showMockupSelector = @selector(showOrHideMockupImageView); 35 | Method showMockupMethod = class_getInstanceMethod([PIXELViewController class], showMockupSelector); 36 | IMP showMockupImp = method_getImplementation(showMockupMethod); 37 | const char *showMockupMethodTypeEncoding = method_getTypeEncoding(showMockupMethod); 38 | class_addMethod(class, showMockupSelector, showMockupImp, showMockupMethodTypeEncoding); 39 | 40 | SEL showSettingsSelector = @selector(settingsPressed:); 41 | Method showSettingsMethod = class_getInstanceMethod([PIXELViewController class], showSettingsSelector); 42 | IMP showSettingsImp = method_getImplementation(showSettingsMethod); 43 | const char *showSettingsMethodTypeEncoding = method_getTypeEncoding(showSettingsMethod); 44 | class_addMethod(class, showSettingsSelector, showSettingsImp, showSettingsMethodTypeEncoding); 45 | 46 | UIImage *image = [[PIXELPerfect shared] imageForControllerClass:[self class]]; 47 | 48 | if (image) { 49 | 50 | [PIXELPerfect shared].recentUsedClass = [self class]; 51 | 52 | [PIXELPerfect shared].overlayWindow.hidden = NO; 53 | 54 | _mockupImageView = [[UIImageView alloc] initWithFrame:self.view.bounds]; 55 | _mockupImageView.tag = kPIXELMockupImageViewTag; 56 | _mockupImageView.image = [PIXELPerfect shared].isImageInverted ? image.inverseColors : image; 57 | _mockupImageView.alpha = 0.5; 58 | _mockupImageView.hidden = ![PIXELPerfect shared].isShowingOnStart; 59 | 60 | [[PIXELPerfect shared].overlayWindow makeKeyWindow]; 61 | [[PIXELPerfect shared].overlayWindow addSubview:_mockupImageView]; 62 | 63 | UIButton *showButton = [[UIButton alloc] initWithFrame:CGRectMake(CGRectGetWidth(self.view.bounds)/2. - 110., 64 | 0, 65 | 100.0, 66 | 20.)]; 67 | showButton.tag = kPIXELShowButtonTag; 68 | showButton.backgroundColor = [UIColor lightGrayColor]; 69 | showButton.layer.masksToBounds = YES; 70 | showButton.layer.cornerRadius = 5.; 71 | 72 | NSString *title = _mockupImageView.isHidden ? @"show" : @"hide"; 73 | 74 | [showButton setTitle:title forState:UIControlStateNormal]; 75 | [showButton addTarget:self action:@selector(showOrHideMockupImageView) forControlEvents:UIControlEventTouchUpInside]; 76 | 77 | [[PIXELPerfect shared].overlayWindow addSubview:showButton]; 78 | 79 | UIButton *settingsButton = [[UIButton alloc] initWithFrame:CGRectMake(CGRectGetWidth(self.view.bounds)/2. + 10., 80 | 0, 81 | 100.0, 82 | 20.)]; 83 | settingsButton.tag = kPIXELSettingsButtonTag; 84 | settingsButton.backgroundColor = [UIColor lightGrayColor]; 85 | settingsButton.layer.masksToBounds = YES; 86 | settingsButton.layer.cornerRadius = 5.; 87 | 88 | [settingsButton setTitle:@"Settings" forState:UIControlStateNormal]; 89 | [settingsButton addTarget:self action:@selector(settingsPressed:) forControlEvents:UIControlEventTouchUpInside]; 90 | 91 | [[PIXELPerfect shared].overlayWindow addSubview:settingsButton]; 92 | } 93 | } 94 | 95 | - (void)viewWillDisappear:(BOOL)animated 96 | { 97 | if ([self isKindOfClass:[PIXELPerfect shared].recentUsedClass]) { 98 | [PIXELPerfect shared].overlayWindow.hidden = YES; 99 | } 100 | } 101 | 102 | - (void)viewWillAppear:(BOOL)animated 103 | { 104 | if ([self isKindOfClass:[PIXELPerfect shared].recentUsedClass]) { 105 | [PIXELPerfect shared].overlayWindow.hidden = NO; 106 | } 107 | 108 | UIImage *image = [[PIXELPerfect shared] imageForControllerClass:[self class]]; 109 | 110 | if (image) { 111 | UIImageView *mockupImageView = (UIImageView *)[[PIXELPerfect shared].overlayWindow viewWithTag:kPIXELMockupImageViewTag]; 112 | mockupImageView.image = [PIXELPerfect shared].isImageInverted ? image.inverseColors : image; 113 | 114 | mockupImageView.alpha = [PIXELPerfect shared].imageAlpha; 115 | } 116 | } 117 | 118 | #pragma mark - 119 | 120 | - (void)showOrHideMockupImageView 121 | { 122 | _mockupImageView.hidden = !_mockupImageView.isHidden; 123 | 124 | if (_mockupImageView.isHidden) { 125 | __block CGRect frame = _mockupImageView.frame; 126 | frame.origin.y = -CGRectGetHeight(_mockupImageView.bounds); 127 | _mockupImageView.frame = frame; 128 | 129 | [UIView animateWithDuration:0.8 animations:^{ 130 | frame.origin.y = 0; 131 | _mockupImageView.frame = frame; 132 | }]; 133 | } 134 | 135 | NSString *title = _mockupImageView.isHidden ? @"show" : @"hide"; 136 | 137 | UIButton *showButton = (UIButton *)[[PIXELPerfect shared].overlayWindow viewWithTag:kPIXELShowButtonTag]; 138 | [showButton setTitle:title forState:UIControlStateNormal]; 139 | } 140 | 141 | - (void)settingsPressed:(id)sender 142 | { 143 | PIXELSettingsViewController *settingsViewController = [[PIXELSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; 144 | UINavigationController *navigationViewController = [[UINavigationController alloc] initWithRootViewController:settingsViewController]; 145 | [self presentViewController:navigationViewController animated:YES completion:nil]; 146 | } 147 | 148 | @end 149 | -------------------------------------------------------------------------------- /PixelPerfect-Example/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 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 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 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 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 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /PixelPerfect-Example.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 810BB50A1B1907EE0007746B /* CoreImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 810BB5091B1907EE0007746B /* CoreImage.framework */; }; 11 | 81355A6A1B04C459007C9830 /* PixelPerfectTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 81355A691B04C459007C9830 /* PixelPerfectTests.m */; }; 12 | 81355A9B1B04C50A007C9830 /* PIXELPerfect.m in Sources */ = {isa = PBXBuildFile; fileRef = 81355A741B04C50A007C9830 /* PIXELPerfect.m */; }; 13 | 81355A9C1B04C50A007C9830 /* PIXELViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 81355A761B04C50A007C9830 /* PIXELViewController.m */; }; 14 | 81355A9D1B04C50A007C9830 /* PIXELWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 81355A781B04C50A007C9830 /* PIXELWindow.m */; }; 15 | 81355A9E1B04C50A007C9830 /* UIImage+ColorInverse.m in Sources */ = {isa = PBXBuildFile; fileRef = 81355A7A1B04C50A007C9830 /* UIImage+ColorInverse.m */; }; 16 | 81355A9F1B04C50A007C9830 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 81355A7D1B04C50A007C9830 /* AppDelegate.m */; }; 17 | 81355AA01B04C50A007C9830 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 81355A7E1B04C50A007C9830 /* LaunchScreen.xib */; }; 18 | 81355AA11B04C50A007C9830 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81355A801B04C50A007C9830 /* Main.storyboard */; }; 19 | 81355AA21B04C50A007C9830 /* ExampleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 81355A841B04C50A007C9830 /* ExampleViewController.m */; }; 20 | 81355AA31B04C50A007C9830 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 81355A851B04C50A007C9830 /* Images.xcassets */; }; 21 | 81355AA51B04C50A007C9830 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 81355A871B04C50A007C9830 /* main.m */; }; 22 | 81355AA61B04C50A007C9830 /* add-point.png in Resources */ = {isa = PBXBuildFile; fileRef = 81355A891B04C50A007C9830 /* add-point.png */; }; 23 | 81355AA71B04C50A007C9830 /* add-password-icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 81355A8B1B04C50A007C9830 /* add-password-icon.png */; }; 24 | 81355AA81B04C50A007C9830 /* add-password-icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 81355A8C1B04C50A007C9830 /* add-password-icon@2x.png */; }; 25 | 81355AA91B04C50A007C9830 /* add-password-icon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 81355A8D1B04C50A007C9830 /* add-password-icon@3x.png */; }; 26 | 81355AAA1B04C50A007C9830 /* add-point-icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 81355A8E1B04C50A007C9830 /* add-point-icon.png */; }; 27 | 81355AAB1B04C50A007C9830 /* add-point-icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 81355A8F1B04C50A007C9830 /* add-point-icon@2x.png */; }; 28 | 81355AAC1B04C50A007C9830 /* add-point-icon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 81355A901B04C50A007C9830 /* add-point-icon@3x.png */; }; 29 | 81355AAD1B04C50A007C9830 /* background@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 81355A911B04C50A007C9830 /* background@2x.png */; }; 30 | 81355AAE1B04C50A007C9830 /* facebook-btn-normal.png in Resources */ = {isa = PBXBuildFile; fileRef = 81355A921B04C50A007C9830 /* facebook-btn-normal.png */; }; 31 | 81355AAF1B04C50A007C9830 /* facebook-btn-normal@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 81355A931B04C50A007C9830 /* facebook-btn-normal@2x.png */; }; 32 | 81355AB01B04C50A007C9830 /* facebook-btn-normal@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 81355A941B04C50A007C9830 /* facebook-btn-normal@3x.png */; }; 33 | 81355AB11B04C50A007C9830 /* facebook-btn-selected.png in Resources */ = {isa = PBXBuildFile; fileRef = 81355A951B04C50A007C9830 /* facebook-btn-selected.png */; }; 34 | 81355AB21B04C50A007C9830 /* facebook-btn-selected@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 81355A961B04C50A007C9830 /* facebook-btn-selected@2x.png */; }; 35 | 81355AB31B04C50A007C9830 /* facebook-btn-selected@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 81355A971B04C50A007C9830 /* facebook-btn-selected@3x.png */; }; 36 | 8190EA9D1B08913C0059465E /* PIXELSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8190EA9C1B08913C0059465E /* PIXELSettingsViewController.m */; }; 37 | /* End PBXBuildFile section */ 38 | 39 | /* Begin PBXContainerItemProxy section */ 40 | 81355A641B04C458007C9830 /* PBXContainerItemProxy */ = { 41 | isa = PBXContainerItemProxy; 42 | containerPortal = 8117763D1AF2A8E900D288A7 /* Project object */; 43 | proxyType = 1; 44 | remoteGlobalIDString = 81355A4A1B04C458007C9830; 45 | remoteInfo = PixelPerfect; 46 | }; 47 | /* End PBXContainerItemProxy section */ 48 | 49 | /* Begin PBXFileReference section */ 50 | 810BB5091B1907EE0007746B /* CoreImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreImage.framework; path = System/Library/Frameworks/CoreImage.framework; sourceTree = SDKROOT; }; 51 | 81355A4B1B04C458007C9830 /* PixelPerfect.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PixelPerfect.app; sourceTree = BUILT_PRODUCTS_DIR; }; 52 | 81355A631B04C458007C9830 /* PixelPerfectTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PixelPerfectTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 53 | 81355A681B04C459007C9830 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 54 | 81355A691B04C459007C9830 /* PixelPerfectTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PixelPerfectTests.m; sourceTree = ""; }; 55 | 81355A731B04C50A007C9830 /* PIXELPerfect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PIXELPerfect.h; sourceTree = ""; }; 56 | 81355A741B04C50A007C9830 /* PIXELPerfect.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PIXELPerfect.m; sourceTree = ""; }; 57 | 81355A751B04C50A007C9830 /* PIXELViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PIXELViewController.h; sourceTree = ""; }; 58 | 81355A761B04C50A007C9830 /* PIXELViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PIXELViewController.m; sourceTree = ""; }; 59 | 81355A771B04C50A007C9830 /* PIXELWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PIXELWindow.h; sourceTree = ""; }; 60 | 81355A781B04C50A007C9830 /* PIXELWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PIXELWindow.m; sourceTree = ""; }; 61 | 81355A791B04C50A007C9830 /* UIImage+ColorInverse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+ColorInverse.h"; sourceTree = ""; }; 62 | 81355A7A1B04C50A007C9830 /* UIImage+ColorInverse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+ColorInverse.m"; sourceTree = ""; }; 63 | 81355A7C1B04C50A007C9830 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 64 | 81355A7D1B04C50A007C9830 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 65 | 81355A7F1B04C50A007C9830 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 66 | 81355A811B04C50A007C9830 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 67 | 81355A831B04C50A007C9830 /* ExampleViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExampleViewController.h; sourceTree = ""; }; 68 | 81355A841B04C50A007C9830 /* ExampleViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExampleViewController.m; sourceTree = ""; }; 69 | 81355A851B04C50A007C9830 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = ../Images.xcassets; sourceTree = ""; }; 70 | 81355A861B04C50A007C9830 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 71 | 81355A871B04C50A007C9830 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 72 | 81355A891B04C50A007C9830 /* add-point.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "add-point.png"; sourceTree = ""; }; 73 | 81355A8B1B04C50A007C9830 /* add-password-icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "add-password-icon.png"; sourceTree = ""; }; 74 | 81355A8C1B04C50A007C9830 /* add-password-icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "add-password-icon@2x.png"; sourceTree = ""; }; 75 | 81355A8D1B04C50A007C9830 /* add-password-icon@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "add-password-icon@3x.png"; sourceTree = ""; }; 76 | 81355A8E1B04C50A007C9830 /* add-point-icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "add-point-icon.png"; sourceTree = ""; }; 77 | 81355A8F1B04C50A007C9830 /* add-point-icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "add-point-icon@2x.png"; sourceTree = ""; }; 78 | 81355A901B04C50A007C9830 /* add-point-icon@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "add-point-icon@3x.png"; sourceTree = ""; }; 79 | 81355A911B04C50A007C9830 /* background@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "background@2x.png"; sourceTree = ""; }; 80 | 81355A921B04C50A007C9830 /* facebook-btn-normal.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "facebook-btn-normal.png"; sourceTree = ""; }; 81 | 81355A931B04C50A007C9830 /* facebook-btn-normal@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "facebook-btn-normal@2x.png"; sourceTree = ""; }; 82 | 81355A941B04C50A007C9830 /* facebook-btn-normal@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "facebook-btn-normal@3x.png"; sourceTree = ""; }; 83 | 81355A951B04C50A007C9830 /* facebook-btn-selected.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "facebook-btn-selected.png"; sourceTree = ""; }; 84 | 81355A961B04C50A007C9830 /* facebook-btn-selected@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "facebook-btn-selected@2x.png"; sourceTree = ""; }; 85 | 81355A971B04C50A007C9830 /* facebook-btn-selected@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "facebook-btn-selected@3x.png"; sourceTree = ""; }; 86 | 814D4FF81B94F37800699ED9 /* PIXELPerfect+Public.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "PIXELPerfect+Public.h"; sourceTree = ""; }; 87 | 8190EA9B1B08913C0059465E /* PIXELSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PIXELSettingsViewController.h; sourceTree = ""; }; 88 | 8190EA9C1B08913C0059465E /* PIXELSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PIXELSettingsViewController.m; sourceTree = ""; }; 89 | /* End PBXFileReference section */ 90 | 91 | /* Begin PBXFrameworksBuildPhase section */ 92 | 81355A481B04C458007C9830 /* Frameworks */ = { 93 | isa = PBXFrameworksBuildPhase; 94 | buildActionMask = 2147483647; 95 | files = ( 96 | 810BB50A1B1907EE0007746B /* CoreImage.framework in Frameworks */, 97 | ); 98 | runOnlyForDeploymentPostprocessing = 0; 99 | }; 100 | 81355A601B04C458007C9830 /* Frameworks */ = { 101 | isa = PBXFrameworksBuildPhase; 102 | buildActionMask = 2147483647; 103 | files = ( 104 | ); 105 | runOnlyForDeploymentPostprocessing = 0; 106 | }; 107 | /* End PBXFrameworksBuildPhase section */ 108 | 109 | /* Begin PBXGroup section */ 110 | 810BB50B1B1908020007746B /* frameworks */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | 810BB5091B1907EE0007746B /* CoreImage.framework */, 114 | ); 115 | name = frameworks; 116 | sourceTree = ""; 117 | }; 118 | 8117763C1AF2A8E900D288A7 = { 119 | isa = PBXGroup; 120 | children = ( 121 | 81355A721B04C50A007C9830 /* PixelPerfect */, 122 | 81355A7B1B04C50A007C9830 /* PixelPerfect-Example */, 123 | 81355A661B04C459007C9830 /* PixelPerfectTests */, 124 | 811776461AF2A8E900D288A7 /* Products */, 125 | ); 126 | sourceTree = ""; 127 | }; 128 | 811776461AF2A8E900D288A7 /* Products */ = { 129 | isa = PBXGroup; 130 | children = ( 131 | 81355A4B1B04C458007C9830 /* PixelPerfect.app */, 132 | 81355A631B04C458007C9830 /* PixelPerfectTests.xctest */, 133 | ); 134 | name = Products; 135 | sourceTree = ""; 136 | }; 137 | 81355A661B04C459007C9830 /* PixelPerfectTests */ = { 138 | isa = PBXGroup; 139 | children = ( 140 | 81355A691B04C459007C9830 /* PixelPerfectTests.m */, 141 | 81355A671B04C459007C9830 /* Supporting Files */, 142 | ); 143 | path = PixelPerfectTests; 144 | sourceTree = ""; 145 | }; 146 | 81355A671B04C459007C9830 /* Supporting Files */ = { 147 | isa = PBXGroup; 148 | children = ( 149 | 81355A681B04C459007C9830 /* Info.plist */, 150 | ); 151 | name = "Supporting Files"; 152 | sourceTree = ""; 153 | }; 154 | 81355A721B04C50A007C9830 /* PixelPerfect */ = { 155 | isa = PBXGroup; 156 | children = ( 157 | 81355A731B04C50A007C9830 /* PIXELPerfect.h */, 158 | 81355A741B04C50A007C9830 /* PIXELPerfect.m */, 159 | 81355A751B04C50A007C9830 /* PIXELViewController.h */, 160 | 81355A761B04C50A007C9830 /* PIXELViewController.m */, 161 | 81355A771B04C50A007C9830 /* PIXELWindow.h */, 162 | 81355A781B04C50A007C9830 /* PIXELWindow.m */, 163 | 81355A791B04C50A007C9830 /* UIImage+ColorInverse.h */, 164 | 81355A7A1B04C50A007C9830 /* UIImage+ColorInverse.m */, 165 | 8190EA9B1B08913C0059465E /* PIXELSettingsViewController.h */, 166 | 8190EA9C1B08913C0059465E /* PIXELSettingsViewController.m */, 167 | 814D4FF81B94F37800699ED9 /* PIXELPerfect+Public.h */, 168 | ); 169 | path = PixelPerfect; 170 | sourceTree = ""; 171 | }; 172 | 81355A7B1B04C50A007C9830 /* PixelPerfect-Example */ = { 173 | isa = PBXGroup; 174 | children = ( 175 | 81355A7C1B04C50A007C9830 /* AppDelegate.h */, 176 | 81355A7D1B04C50A007C9830 /* AppDelegate.m */, 177 | 81355A7E1B04C50A007C9830 /* LaunchScreen.xib */, 178 | 81355A801B04C50A007C9830 /* Main.storyboard */, 179 | 81355A821B04C50A007C9830 /* classes */, 180 | 810BB50B1B1908020007746B /* frameworks */, 181 | 81355A881B04C50A007C9830 /* mockups */, 182 | 81355A8A1B04C50A007C9830 /* resources */, 183 | 81355AB51B04C518007C9830 /* Supporting Files */, 184 | ); 185 | path = "PixelPerfect-Example"; 186 | sourceTree = ""; 187 | }; 188 | 81355A821B04C50A007C9830 /* classes */ = { 189 | isa = PBXGroup; 190 | children = ( 191 | 81355A831B04C50A007C9830 /* ExampleViewController.h */, 192 | 81355A841B04C50A007C9830 /* ExampleViewController.m */, 193 | ); 194 | path = classes; 195 | sourceTree = ""; 196 | }; 197 | 81355A881B04C50A007C9830 /* mockups */ = { 198 | isa = PBXGroup; 199 | children = ( 200 | 81355A891B04C50A007C9830 /* add-point.png */, 201 | ); 202 | path = mockups; 203 | sourceTree = ""; 204 | }; 205 | 81355A8A1B04C50A007C9830 /* resources */ = { 206 | isa = PBXGroup; 207 | children = ( 208 | 81355A851B04C50A007C9830 /* Images.xcassets */, 209 | 81355A8B1B04C50A007C9830 /* add-password-icon.png */, 210 | 81355A8C1B04C50A007C9830 /* add-password-icon@2x.png */, 211 | 81355A8D1B04C50A007C9830 /* add-password-icon@3x.png */, 212 | 81355A8E1B04C50A007C9830 /* add-point-icon.png */, 213 | 81355A8F1B04C50A007C9830 /* add-point-icon@2x.png */, 214 | 81355A901B04C50A007C9830 /* add-point-icon@3x.png */, 215 | 81355A911B04C50A007C9830 /* background@2x.png */, 216 | 81355A921B04C50A007C9830 /* facebook-btn-normal.png */, 217 | 81355A931B04C50A007C9830 /* facebook-btn-normal@2x.png */, 218 | 81355A941B04C50A007C9830 /* facebook-btn-normal@3x.png */, 219 | 81355A951B04C50A007C9830 /* facebook-btn-selected.png */, 220 | 81355A961B04C50A007C9830 /* facebook-btn-selected@2x.png */, 221 | 81355A971B04C50A007C9830 /* facebook-btn-selected@3x.png */, 222 | ); 223 | path = resources; 224 | sourceTree = ""; 225 | }; 226 | 81355AB51B04C518007C9830 /* Supporting Files */ = { 227 | isa = PBXGroup; 228 | children = ( 229 | 81355A861B04C50A007C9830 /* Info.plist */, 230 | 81355A871B04C50A007C9830 /* main.m */, 231 | ); 232 | name = "Supporting Files"; 233 | sourceTree = ""; 234 | }; 235 | /* End PBXGroup section */ 236 | 237 | /* Begin PBXNativeTarget section */ 238 | 81355A4A1B04C458007C9830 /* PixelPerfect */ = { 239 | isa = PBXNativeTarget; 240 | buildConfigurationList = 81355A6B1B04C459007C9830 /* Build configuration list for PBXNativeTarget "PixelPerfect" */; 241 | buildPhases = ( 242 | 81355A471B04C458007C9830 /* Sources */, 243 | 81355A481B04C458007C9830 /* Frameworks */, 244 | 81355A491B04C458007C9830 /* Resources */, 245 | ); 246 | buildRules = ( 247 | ); 248 | dependencies = ( 249 | ); 250 | name = PixelPerfect; 251 | productName = PixelPerfect; 252 | productReference = 81355A4B1B04C458007C9830 /* PixelPerfect.app */; 253 | productType = "com.apple.product-type.application"; 254 | }; 255 | 81355A621B04C458007C9830 /* PixelPerfectTests */ = { 256 | isa = PBXNativeTarget; 257 | buildConfigurationList = 81355A6E1B04C459007C9830 /* Build configuration list for PBXNativeTarget "PixelPerfectTests" */; 258 | buildPhases = ( 259 | 81355A5F1B04C458007C9830 /* Sources */, 260 | 81355A601B04C458007C9830 /* Frameworks */, 261 | 81355A611B04C458007C9830 /* Resources */, 262 | ); 263 | buildRules = ( 264 | ); 265 | dependencies = ( 266 | 81355A651B04C458007C9830 /* PBXTargetDependency */, 267 | ); 268 | name = PixelPerfectTests; 269 | productName = PixelPerfectTests; 270 | productReference = 81355A631B04C458007C9830 /* PixelPerfectTests.xctest */; 271 | productType = "com.apple.product-type.bundle.unit-test"; 272 | }; 273 | /* End PBXNativeTarget section */ 274 | 275 | /* Begin PBXProject section */ 276 | 8117763D1AF2A8E900D288A7 /* Project object */ = { 277 | isa = PBXProject; 278 | attributes = { 279 | LastUpgradeCheck = 0630; 280 | ORGANIZATIONNAME = "Yuri Kobets"; 281 | TargetAttributes = { 282 | 81355A4A1B04C458007C9830 = { 283 | CreatedOnToolsVersion = 6.3.1; 284 | }; 285 | 81355A621B04C458007C9830 = { 286 | CreatedOnToolsVersion = 6.3.1; 287 | TestTargetID = 81355A4A1B04C458007C9830; 288 | }; 289 | }; 290 | }; 291 | buildConfigurationList = 811776401AF2A8E900D288A7 /* Build configuration list for PBXProject "PixelPerfect-Example" */; 292 | compatibilityVersion = "Xcode 3.2"; 293 | developmentRegion = English; 294 | hasScannedForEncodings = 0; 295 | knownRegions = ( 296 | en, 297 | Base, 298 | ); 299 | mainGroup = 8117763C1AF2A8E900D288A7; 300 | productRefGroup = 811776461AF2A8E900D288A7 /* Products */; 301 | projectDirPath = ""; 302 | projectRoot = ""; 303 | targets = ( 304 | 81355A4A1B04C458007C9830 /* PixelPerfect */, 305 | 81355A621B04C458007C9830 /* PixelPerfectTests */, 306 | ); 307 | }; 308 | /* End PBXProject section */ 309 | 310 | /* Begin PBXResourcesBuildPhase section */ 311 | 81355A491B04C458007C9830 /* Resources */ = { 312 | isa = PBXResourcesBuildPhase; 313 | buildActionMask = 2147483647; 314 | files = ( 315 | 81355AAB1B04C50A007C9830 /* add-point-icon@2x.png in Resources */, 316 | 81355AAA1B04C50A007C9830 /* add-point-icon.png in Resources */, 317 | 81355AA71B04C50A007C9830 /* add-password-icon.png in Resources */, 318 | 81355AA61B04C50A007C9830 /* add-point.png in Resources */, 319 | 81355AAC1B04C50A007C9830 /* add-point-icon@3x.png in Resources */, 320 | 81355AAF1B04C50A007C9830 /* facebook-btn-normal@2x.png in Resources */, 321 | 81355AA81B04C50A007C9830 /* add-password-icon@2x.png in Resources */, 322 | 81355AA31B04C50A007C9830 /* Images.xcassets in Resources */, 323 | 81355AB01B04C50A007C9830 /* facebook-btn-normal@3x.png in Resources */, 324 | 81355AB21B04C50A007C9830 /* facebook-btn-selected@2x.png in Resources */, 325 | 81355AB31B04C50A007C9830 /* facebook-btn-selected@3x.png in Resources */, 326 | 81355AA91B04C50A007C9830 /* add-password-icon@3x.png in Resources */, 327 | 81355AA01B04C50A007C9830 /* LaunchScreen.xib in Resources */, 328 | 81355AAD1B04C50A007C9830 /* background@2x.png in Resources */, 329 | 81355AB11B04C50A007C9830 /* facebook-btn-selected.png in Resources */, 330 | 81355AA11B04C50A007C9830 /* Main.storyboard in Resources */, 331 | 81355AAE1B04C50A007C9830 /* facebook-btn-normal.png in Resources */, 332 | ); 333 | runOnlyForDeploymentPostprocessing = 0; 334 | }; 335 | 81355A611B04C458007C9830 /* Resources */ = { 336 | isa = PBXResourcesBuildPhase; 337 | buildActionMask = 2147483647; 338 | files = ( 339 | ); 340 | runOnlyForDeploymentPostprocessing = 0; 341 | }; 342 | /* End PBXResourcesBuildPhase section */ 343 | 344 | /* Begin PBXSourcesBuildPhase section */ 345 | 81355A471B04C458007C9830 /* Sources */ = { 346 | isa = PBXSourcesBuildPhase; 347 | buildActionMask = 2147483647; 348 | files = ( 349 | 81355A9E1B04C50A007C9830 /* UIImage+ColorInverse.m in Sources */, 350 | 81355A9B1B04C50A007C9830 /* PIXELPerfect.m in Sources */, 351 | 8190EA9D1B08913C0059465E /* PIXELSettingsViewController.m in Sources */, 352 | 81355A9D1B04C50A007C9830 /* PIXELWindow.m in Sources */, 353 | 81355AA21B04C50A007C9830 /* ExampleViewController.m in Sources */, 354 | 81355A9C1B04C50A007C9830 /* PIXELViewController.m in Sources */, 355 | 81355AA51B04C50A007C9830 /* main.m in Sources */, 356 | 81355A9F1B04C50A007C9830 /* AppDelegate.m in Sources */, 357 | ); 358 | runOnlyForDeploymentPostprocessing = 0; 359 | }; 360 | 81355A5F1B04C458007C9830 /* Sources */ = { 361 | isa = PBXSourcesBuildPhase; 362 | buildActionMask = 2147483647; 363 | files = ( 364 | 81355A6A1B04C459007C9830 /* PixelPerfectTests.m in Sources */, 365 | ); 366 | runOnlyForDeploymentPostprocessing = 0; 367 | }; 368 | /* End PBXSourcesBuildPhase section */ 369 | 370 | /* Begin PBXTargetDependency section */ 371 | 81355A651B04C458007C9830 /* PBXTargetDependency */ = { 372 | isa = PBXTargetDependency; 373 | target = 81355A4A1B04C458007C9830 /* PixelPerfect */; 374 | targetProxy = 81355A641B04C458007C9830 /* PBXContainerItemProxy */; 375 | }; 376 | /* End PBXTargetDependency section */ 377 | 378 | /* Begin PBXVariantGroup section */ 379 | 81355A7E1B04C50A007C9830 /* LaunchScreen.xib */ = { 380 | isa = PBXVariantGroup; 381 | children = ( 382 | 81355A7F1B04C50A007C9830 /* Base */, 383 | ); 384 | name = LaunchScreen.xib; 385 | sourceTree = ""; 386 | }; 387 | 81355A801B04C50A007C9830 /* Main.storyboard */ = { 388 | isa = PBXVariantGroup; 389 | children = ( 390 | 81355A811B04C50A007C9830 /* Base */, 391 | ); 392 | name = Main.storyboard; 393 | sourceTree = ""; 394 | }; 395 | /* End PBXVariantGroup section */ 396 | 397 | /* Begin XCBuildConfiguration section */ 398 | 811776661AF2A8EA00D288A7 /* Debug */ = { 399 | isa = XCBuildConfiguration; 400 | buildSettings = { 401 | ALWAYS_SEARCH_USER_PATHS = NO; 402 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 403 | CLANG_CXX_LIBRARY = "libc++"; 404 | CLANG_ENABLE_MODULES = YES; 405 | CLANG_ENABLE_OBJC_ARC = YES; 406 | CLANG_WARN_BOOL_CONVERSION = YES; 407 | CLANG_WARN_CONSTANT_CONVERSION = YES; 408 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 409 | CLANG_WARN_EMPTY_BODY = YES; 410 | CLANG_WARN_ENUM_CONVERSION = YES; 411 | CLANG_WARN_INT_CONVERSION = YES; 412 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 413 | CLANG_WARN_UNREACHABLE_CODE = YES; 414 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 415 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 416 | COPY_PHASE_STRIP = NO; 417 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 418 | ENABLE_STRICT_OBJC_MSGSEND = YES; 419 | GCC_C_LANGUAGE_STANDARD = gnu99; 420 | GCC_DYNAMIC_NO_PIC = NO; 421 | GCC_NO_COMMON_BLOCKS = YES; 422 | GCC_OPTIMIZATION_LEVEL = 0; 423 | GCC_PREPROCESSOR_DEFINITIONS = ( 424 | "DEBUG=1", 425 | "$(inherited)", 426 | ); 427 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 428 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 429 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 430 | GCC_WARN_UNDECLARED_SELECTOR = YES; 431 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 432 | GCC_WARN_UNUSED_FUNCTION = YES; 433 | GCC_WARN_UNUSED_VARIABLE = YES; 434 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 435 | MTL_ENABLE_DEBUG_INFO = YES; 436 | ONLY_ACTIVE_ARCH = YES; 437 | SDKROOT = iphoneos; 438 | TARGETED_DEVICE_FAMILY = "1,2"; 439 | }; 440 | name = Debug; 441 | }; 442 | 811776671AF2A8EA00D288A7 /* Release */ = { 443 | isa = XCBuildConfiguration; 444 | buildSettings = { 445 | ALWAYS_SEARCH_USER_PATHS = NO; 446 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 447 | CLANG_CXX_LIBRARY = "libc++"; 448 | CLANG_ENABLE_MODULES = YES; 449 | CLANG_ENABLE_OBJC_ARC = YES; 450 | CLANG_WARN_BOOL_CONVERSION = YES; 451 | CLANG_WARN_CONSTANT_CONVERSION = YES; 452 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 453 | CLANG_WARN_EMPTY_BODY = YES; 454 | CLANG_WARN_ENUM_CONVERSION = YES; 455 | CLANG_WARN_INT_CONVERSION = YES; 456 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 457 | CLANG_WARN_UNREACHABLE_CODE = YES; 458 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 459 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 460 | COPY_PHASE_STRIP = NO; 461 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 462 | ENABLE_NS_ASSERTIONS = NO; 463 | ENABLE_STRICT_OBJC_MSGSEND = YES; 464 | GCC_C_LANGUAGE_STANDARD = gnu99; 465 | GCC_NO_COMMON_BLOCKS = YES; 466 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 467 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 468 | GCC_WARN_UNDECLARED_SELECTOR = YES; 469 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 470 | GCC_WARN_UNUSED_FUNCTION = YES; 471 | GCC_WARN_UNUSED_VARIABLE = YES; 472 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 473 | MTL_ENABLE_DEBUG_INFO = NO; 474 | SDKROOT = iphoneos; 475 | TARGETED_DEVICE_FAMILY = "1,2"; 476 | VALIDATE_PRODUCT = YES; 477 | }; 478 | name = Release; 479 | }; 480 | 81355A6C1B04C459007C9830 /* Debug */ = { 481 | isa = XCBuildConfiguration; 482 | buildSettings = { 483 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 484 | GCC_PREPROCESSOR_DEFINITIONS = ( 485 | "DEBUG=1", 486 | "$(inherited)", 487 | ); 488 | INFOPLIST_FILE = "PixelPerfect-Example/Info.plist"; 489 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 490 | PRODUCT_NAME = "$(TARGET_NAME)"; 491 | }; 492 | name = Debug; 493 | }; 494 | 81355A6D1B04C459007C9830 /* Release */ = { 495 | isa = XCBuildConfiguration; 496 | buildSettings = { 497 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 498 | INFOPLIST_FILE = "PixelPerfect-Example/Info.plist"; 499 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 500 | PRODUCT_NAME = "$(TARGET_NAME)"; 501 | }; 502 | name = Release; 503 | }; 504 | 81355A6F1B04C459007C9830 /* Debug */ = { 505 | isa = XCBuildConfiguration; 506 | buildSettings = { 507 | BUNDLE_LOADER = "$(TEST_HOST)"; 508 | FRAMEWORK_SEARCH_PATHS = ( 509 | "$(SDKROOT)/Developer/Library/Frameworks", 510 | "$(inherited)", 511 | ); 512 | GCC_PREPROCESSOR_DEFINITIONS = ( 513 | "DEBUG=1", 514 | "$(inherited)", 515 | ); 516 | INFOPLIST_FILE = PixelPerfectTests/Info.plist; 517 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 518 | PRODUCT_NAME = "$(TARGET_NAME)"; 519 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PixelPerfect.app/PixelPerfect"; 520 | }; 521 | name = Debug; 522 | }; 523 | 81355A701B04C459007C9830 /* Release */ = { 524 | isa = XCBuildConfiguration; 525 | buildSettings = { 526 | BUNDLE_LOADER = "$(TEST_HOST)"; 527 | FRAMEWORK_SEARCH_PATHS = ( 528 | "$(SDKROOT)/Developer/Library/Frameworks", 529 | "$(inherited)", 530 | ); 531 | INFOPLIST_FILE = PixelPerfectTests/Info.plist; 532 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 533 | PRODUCT_NAME = "$(TARGET_NAME)"; 534 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PixelPerfect.app/PixelPerfect"; 535 | }; 536 | name = Release; 537 | }; 538 | /* End XCBuildConfiguration section */ 539 | 540 | /* Begin XCConfigurationList section */ 541 | 811776401AF2A8E900D288A7 /* Build configuration list for PBXProject "PixelPerfect-Example" */ = { 542 | isa = XCConfigurationList; 543 | buildConfigurations = ( 544 | 811776661AF2A8EA00D288A7 /* Debug */, 545 | 811776671AF2A8EA00D288A7 /* Release */, 546 | ); 547 | defaultConfigurationIsVisible = 0; 548 | defaultConfigurationName = Release; 549 | }; 550 | 81355A6B1B04C459007C9830 /* Build configuration list for PBXNativeTarget "PixelPerfect" */ = { 551 | isa = XCConfigurationList; 552 | buildConfigurations = ( 553 | 81355A6C1B04C459007C9830 /* Debug */, 554 | 81355A6D1B04C459007C9830 /* Release */, 555 | ); 556 | defaultConfigurationIsVisible = 0; 557 | defaultConfigurationName = Release; 558 | }; 559 | 81355A6E1B04C459007C9830 /* Build configuration list for PBXNativeTarget "PixelPerfectTests" */ = { 560 | isa = XCConfigurationList; 561 | buildConfigurations = ( 562 | 81355A6F1B04C459007C9830 /* Debug */, 563 | 81355A701B04C459007C9830 /* Release */, 564 | ); 565 | defaultConfigurationIsVisible = 0; 566 | defaultConfigurationName = Release; 567 | }; 568 | /* End XCConfigurationList section */ 569 | }; 570 | rootObject = 8117763D1AF2A8E900D288A7 /* Project object */; 571 | } 572 | --------------------------------------------------------------------------------