├── GIKPopoverBackgroundView-Example ├── en.lproj │ └── InfoPlist.strings ├── Default.png ├── Default@2x.png ├── Default-568h@2x.png ├── Images │ ├── PopoverBackgroundArrowUp.png │ ├── PopoverBackgroundArrowDown.png │ ├── PopoverBackgroundArrowSide.png │ ├── PopoverBackgroundArrowUp@2x.png │ ├── PopoverBackgroundArrowDown@2x.png │ ├── PopoverBackgroundArrowSide@2x.png │ ├── PopoverBackgroundArrowSideTop.png │ ├── PopoverBackgroundArrowUpRight.png │ ├── PopoverBackgroundArrowDownRight.png │ ├── PopoverBackgroundArrowSideBottom.png │ ├── PopoverBackgroundArrowSideTop@2x.png │ ├── PopoverBackgroundArrowUpRight@2x.png │ ├── PopoverBackgroundArrowDownRight@2x.png │ └── PopoverBackgroundArrowSideBottom@2x.png ├── GIKImageFilesViewController.h ├── GIKRenderedImagesViewController.h ├── GIKAppDelegate.h ├── GIKImageFilesPopoverBackgroundView.h ├── GIKRenderedImagesPopoverBackgroundView.h ├── GIKPopoverBackgroundView-Prefix.pch ├── main.m ├── GIKRenderedImagesPopoverBackgroundView.m ├── GIKImageFilesPopoverBackgroundView.m ├── GIKPopoverBackgroundView-Info.plist ├── GIKAppDelegate.m ├── GIKImageFilesViewController.m ├── GIKRenderedImagesViewController.m └── MainStoryboard.storyboard ├── Photoshop Source └── GIKPopoverBackgroundViewArrows.psd ├── .gitignore ├── GIKPopoverBackgroundView.podspec ├── GIKPopoverBackgroundView ├── GIKPopoverBackgroundView.podspec ├── GIKPopoverBackgroundView.h └── GIKPopoverBackgroundView.m ├── LICENSE ├── README.md └── GIKPopoverBackgroundView.xcodeproj └── project.pbxproj /GIKPopoverBackgroundView-Example/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiK/GIKPopoverBackgroundView/HEAD/GIKPopoverBackgroundView-Example/Default.png -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiK/GIKPopoverBackgroundView/HEAD/GIKPopoverBackgroundView-Example/Default@2x.png -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiK/GIKPopoverBackgroundView/HEAD/GIKPopoverBackgroundView-Example/Default-568h@2x.png -------------------------------------------------------------------------------- /Photoshop Source/GIKPopoverBackgroundViewArrows.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiK/GIKPopoverBackgroundView/HEAD/Photoshop Source/GIKPopoverBackgroundViewArrows.psd -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowUp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiK/GIKPopoverBackgroundView/HEAD/GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowUp.png -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowDown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiK/GIKPopoverBackgroundView/HEAD/GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowDown.png -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowSide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiK/GIKPopoverBackgroundView/HEAD/GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowSide.png -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowUp@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiK/GIKPopoverBackgroundView/HEAD/GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowUp@2x.png -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowDown@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiK/GIKPopoverBackgroundView/HEAD/GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowDown@2x.png -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowSide@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiK/GIKPopoverBackgroundView/HEAD/GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowSide@2x.png -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowSideTop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiK/GIKPopoverBackgroundView/HEAD/GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowSideTop.png -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowUpRight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiK/GIKPopoverBackgroundView/HEAD/GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowUpRight.png -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowDownRight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiK/GIKPopoverBackgroundView/HEAD/GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowDownRight.png -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowSideBottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiK/GIKPopoverBackgroundView/HEAD/GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowSideBottom.png -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowSideTop@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiK/GIKPopoverBackgroundView/HEAD/GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowSideTop@2x.png -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowUpRight@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiK/GIKPopoverBackgroundView/HEAD/GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowUpRight@2x.png -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowDownRight@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiK/GIKPopoverBackgroundView/HEAD/GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowDownRight@2x.png -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowSideBottom@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GiK/GIKPopoverBackgroundView/HEAD/GIKPopoverBackgroundView-Example/Images/PopoverBackgroundArrowSideBottom@2x.png -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/GIKImageFilesViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // GIKImageFilesViewController.h 3 | // GIKPopoverBackgroundView 4 | // 5 | // Created by Gordon Hughes on 1/7/13. 6 | // Copyright (c) 2013 Gordon Hughes. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface GIKImageFilesViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/GIKRenderedImagesViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // GIKImageFilesViewController.h 3 | // GIKPopoverBackgroundView 4 | // 5 | // Created by Gordon Hughes on 1/7/13. 6 | // Copyright (c) 2013 Gordon Hughes. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface GIKRenderedImagesViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/GIKAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // GIKAppDelegate.h 3 | // GIKPopoverBackgroundView 4 | // 5 | // Created by Gordon Hughes on 1/7/13. 6 | // Copyright (c) 2013 Gordon Hughes. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface GIKAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/GIKImageFilesPopoverBackgroundView.h: -------------------------------------------------------------------------------- 1 | // 2 | // GIKImageFilesPopoverBackgroundView.h 3 | // GIKPopoverBackgroundView 4 | // 5 | // Created by Chris Flesner on 3/18/13. 6 | // Copyright (c) 2013 Gordon Hughes. All rights reserved. 7 | // 8 | 9 | #import "GIKPopoverBackgroundView.h" 10 | 11 | @interface GIKImageFilesPopoverBackgroundView : GIKPopoverBackgroundView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/GIKRenderedImagesPopoverBackgroundView.h: -------------------------------------------------------------------------------- 1 | // 2 | // GIKRenderedImagesPopoverBackgroundView.h 3 | // GIKPopoverBackgroundView 4 | // 5 | // Created by Chris Flesner on 3/18/13. 6 | // Copyright (c) 2013 Gordon Hughes. All rights reserved. 7 | // 8 | 9 | #import "GIKPopoverBackgroundView.h" 10 | 11 | @interface GIKRenderedImagesPopoverBackgroundView : GIKPopoverBackgroundView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X folder attributes 2 | .DS_Store 3 | 4 | # Thumbnails 5 | ._* 6 | 7 | # Files that might appear on external disk 8 | .Spotlight-V100 9 | .Trashes 10 | 11 | # Xcode 12 | build/* 13 | *.pbxuser 14 | !default.pbxuser 15 | *.mode1v3 16 | !default.mode1v3 17 | *.mode2v3 18 | !default.mode2v3 19 | *.perspectivev3 20 | !default.perspectivev3 21 | *.xcworkspace 22 | !default.xcworkspace 23 | xcuserdata 24 | profile 25 | *.moved-aside 26 | DerivedData -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/GIKPopoverBackgroundView-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'GIKPopoverBackgroundView' target in the 'GIKPopoverBackgroundView' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_5_0 8 | #warning "This project uses features only available in iOS SDK 5.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // GIKPopoverBackgroundView 4 | // 5 | // Created by Gordon Hughes on 1/7/13. 6 | // Copyright (c) 2013 Gordon Hughes. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "GIKAppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([GIKAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /GIKPopoverBackgroundView.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'GIKPopoverBackgroundView' 3 | s.version = '0.0.1' 4 | s.license = 'MIT' 5 | s.platform = :ios, '5.0' 6 | 7 | s.summary = 'GIKPopoverBackgroundView is a UIPopoverBackgroundView subclass which shows how to customise the background of a UIPopoverController.' 8 | s.homepage = 'https://github.com/GiK/GIKPopoverBackgroundView' 9 | s.author = { 'Gordon Hughes' => 'gordon@geeksinkilts.com' } 10 | s.source = { :git => 'https://github.com/GiK/GIKPopoverBackgroundView.git' } 11 | 12 | s.source_files = 'GIKPopoverBackgroundView/*.{h,m}' 13 | 14 | s.requires_arc = true 15 | end 16 | -------------------------------------------------------------------------------- /GIKPopoverBackgroundView/GIKPopoverBackgroundView.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'GIKPopoverBackgroundView' 3 | s.version = '1.0.1' 4 | s.platform = :ios 5 | s.license = 'MIT' 6 | s.summary = 'Custom popover backgrounds. UIKit quality.' 7 | s.homepage = 'https://github.com/GiK/GIKPopoverBackgroundView.git' 8 | s.author = { 'Gordon Hughes' => 'gordon@geeksinkilts.com' } 9 | s.source = { :git => 'https://github.com/GiK/GIKPopoverBackgroundView.git', :tag => s.version.to_s } 10 | s.source_files = 'GIKPopoverBackgroundView.{h,m}' 11 | s.framework = 'QuartzCore' 12 | s.requires_arc = true 13 | 14 | s.ios.deployment_target = '5.0' 15 | s.ios.frameworks = 'QuartzCore' -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/GIKRenderedImagesPopoverBackgroundView.m: -------------------------------------------------------------------------------- 1 | // 2 | // GIKRenderedImagesPopoverBackgroundView.m 3 | // GIKPopoverBackgroundView 4 | // 5 | // Created by Chris Flesner on 3/18/13. 6 | // Copyright (c) 2013 Gordon Hughes. All rights reserved. 7 | // 8 | 9 | #import "GIKRenderedImagesPopoverBackgroundView.h" 10 | 11 | @implementation GIKRenderedImagesPopoverBackgroundView 12 | 13 | - (UIColor *)popoverBorderColor 14 | { 15 | return [UIColor colorWithRed:0.439216 green:0.431373 blue:0.407843 alpha:1]; 16 | } 17 | 18 | - (UIColor *)popoverGradientFromColor 19 | { 20 | return [UIColor colorWithRed:0.980392 green:0.976471 blue:0.964706 alpha:1]; 21 | } 22 | 23 | - (UIColor *)popoverGradientToColor 24 | { 25 | return [UIColor colorWithRed:0.858824 green:0.835294 blue:0.807843 alpha:1]; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Geeks In Kilts (http://geeksinkilts.com/) 2 | All rights reserved. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/GIKImageFilesPopoverBackgroundView.m: -------------------------------------------------------------------------------- 1 | // 2 | // GIKImageFilesPopoverBackgroundView.m 3 | // GIKPopoverBackgroundView 4 | // 5 | // Created by Chris Flesner on 3/18/13. 6 | // Copyright (c) 2013 Gordon Hughes. All rights reserved. 7 | // 8 | 9 | #import "GIKImageFilesPopoverBackgroundView.h" 10 | 11 | @implementation GIKImageFilesPopoverBackgroundView 12 | 13 | - (UIEdgeInsets)arrowSideTopInsets 14 | { 15 | UIEdgeInsets insets = {43.0, 9.0, 9.0, 27.0}; 16 | return insets; 17 | } 18 | 19 | - (UIImage *)arrowUpImage 20 | { 21 | return [UIImage imageNamed:@"PopoverBackgroundArrowUp.png"]; 22 | } 23 | 24 | - (UIImage *)arrowUpRightImage 25 | { 26 | return [UIImage imageNamed:@"PopoverBackgroundArrowUpRight.png"]; 27 | } 28 | 29 | - (UIImage *)arrowDownImage 30 | { 31 | return [UIImage imageNamed:@"PopoverBackgroundArrowDown.png"]; 32 | } 33 | 34 | - (UIImage *)arrowDownRightImage 35 | { 36 | return [UIImage imageNamed:@"PopoverBackgroundArrowDownRight.png"]; 37 | } 38 | 39 | - (UIImage *)arrowSideImage 40 | { 41 | return [UIImage imageNamed:@"PopoverBackgroundArrowSide.png"]; 42 | } 43 | 44 | - (UIImage *)arrowSideTopImage 45 | { 46 | return [UIImage imageNamed:@"PopoverBackgroundArrowSideTop.png"]; 47 | } 48 | 49 | - (UIImage *)arrowSideBottomImage 50 | { 51 | return [UIImage imageNamed:@"PopoverBackgroundArrowSideBottom.png"]; 52 | } 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/GIKPopoverBackgroundView-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIMainStoryboardFile 28 | MainStoryboard 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations~ipad 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationPortraitUpsideDown 37 | UIInterfaceOrientationLandscapeLeft 38 | UIInterfaceOrientationLandscapeRight 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/GIKAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // GIKAppDelegate.m 3 | // GIKPopoverBackgroundView 4 | // 5 | // Created by Gordon Hughes on 1/7/13. 6 | // Copyright (c) 2013 Gordon Hughes. All rights reserved. 7 | // 8 | 9 | #import "GIKAppDelegate.h" 10 | 11 | @implementation GIKAppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 14 | { 15 | // Override point for customization after application launch. 16 | return YES; 17 | } 18 | 19 | - (void)applicationWillResignActive:(UIApplication *)application 20 | { 21 | // 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. 22 | // 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. 23 | } 24 | 25 | - (void)applicationDidEnterBackground:(UIApplication *)application 26 | { 27 | // 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. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | - (void)applicationWillEnterForeground:(UIApplication *)application 32 | { 33 | // 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. 34 | } 35 | 36 | - (void)applicationDidBecomeActive:(UIApplication *)application 37 | { 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 | { 43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/GIKImageFilesViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // GIKImageFilesViewController.m 3 | // GIKPopoverBackgroundView 4 | // 5 | // Created by Gordon Hughes on 1/7/13. 6 | // Copyright (c) 2013 Gordon Hughes. All rights reserved. 7 | // 8 | 9 | #import "GIKImageFilesViewController.h" 10 | #import "GIKImageFilesPopoverBackgroundView.h" 11 | 12 | @interface GIKImageFilesViewController () { 13 | UIPopoverController *popoverController; 14 | NSString *segueIdentifier; 15 | } 16 | 17 | @end 18 | 19 | @implementation GIKImageFilesViewController 20 | 21 | - (void)viewDidLoad 22 | { 23 | [super viewDidLoad]; 24 | // Do any additional setup after loading the view, typically from a nib. 25 | } 26 | 27 | - (void)didReceiveMemoryWarning 28 | { 29 | [super didReceiveMemoryWarning]; 30 | // Dispose of any resources that can be recreated. 31 | } 32 | 33 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 34 | { 35 | if ([segue isKindOfClass:[UIStoryboardPopoverSegue class]]) 36 | { 37 | segueIdentifier = segue.identifier; 38 | popoverController = [(UIStoryboardPopoverSegue *)segue popoverController]; 39 | popoverController.popoverBackgroundViewClass = [GIKImageFilesPopoverBackgroundView class]; 40 | 41 | if ([segue.identifier isEqualToString:@"popover2"]) 42 | { 43 | UINavigationBar *navBar = [(UINavigationController *)popoverController.contentViewController navigationBar]; 44 | [self applyTitleTextAttributesToNavigationBar:navBar]; 45 | } 46 | } 47 | } 48 | 49 | - (void)applyTitleTextAttributesToNavigationBar:(UINavigationBar *)navBar 50 | { 51 | NSDictionary *attributes = @{ UITextAttributeTextColor : [UIColor colorWithRed:122.0/255.0 green:120.0/255.0 blue:114.0/255.0 alpha:1.0], 52 | UITextAttributeTextShadowColor : [UIColor whiteColor], 53 | UITextAttributeTextShadowOffset : [NSValue valueWithCGSize:(CGSize){ .width = 0.0, .height = 1.0}] }; 54 | 55 | [navBar setTitleTextAttributes:attributes]; 56 | } 57 | 58 | - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation 59 | { 60 | if (popoverController && popoverController.popoverVisible) 61 | { 62 | [popoverController dismissPopoverAnimated:YES]; 63 | [self performSegueWithIdentifier:segueIdentifier sender:nil]; 64 | } 65 | } 66 | 67 | 68 | #pragma mark - iOS 6 rotation 69 | 70 | - (BOOL)shouldAutorotate 71 | { 72 | return YES; 73 | } 74 | 75 | - (UIInterfaceOrientationMask)supportedInterfaceOrientations 76 | { 77 | return UIInterfaceOrientationMaskAll; 78 | } 79 | 80 | 81 | #pragma mark - iOS 5 rotation 82 | 83 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation 84 | { 85 | return YES; 86 | } 87 | 88 | @end 89 | -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/GIKRenderedImagesViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // GIKRenderedImagesViewController.m 3 | // GIKPopoverBackgroundView 4 | // 5 | // Created by Gordon Hughes on 1/7/13. 6 | // Copyright (c) 2013 Gordon Hughes. All rights reserved. 7 | // 8 | 9 | #import "GIKRenderedImagesViewController.h" 10 | #import "GIKRenderedImagesPopoverBackgroundView.h" 11 | 12 | @interface GIKRenderedImagesViewController () { 13 | UIPopoverController *popoverController; 14 | NSString *segueIdentifier; 15 | } 16 | 17 | @end 18 | 19 | @implementation GIKRenderedImagesViewController 20 | 21 | - (void)viewDidLoad 22 | { 23 | [super viewDidLoad]; 24 | // Do any additional setup after loading the view, typically from a nib. 25 | } 26 | 27 | - (void)didReceiveMemoryWarning 28 | { 29 | [super didReceiveMemoryWarning]; 30 | // Dispose of any resources that can be recreated. 31 | } 32 | 33 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 34 | { 35 | if ([segue isKindOfClass:[UIStoryboardPopoverSegue class]]) 36 | { 37 | segueIdentifier = segue.identifier; 38 | popoverController = [(UIStoryboardPopoverSegue *)segue popoverController]; 39 | popoverController.popoverBackgroundViewClass = [GIKRenderedImagesPopoverBackgroundView class]; 40 | 41 | if ([segue.identifier isEqualToString:@"popover2"]) 42 | { 43 | UINavigationBar *navBar = [(UINavigationController *)popoverController.contentViewController navigationBar]; 44 | [self applyTitleTextAttributesToNavigationBar:navBar]; 45 | } 46 | } 47 | } 48 | 49 | - (void)applyTitleTextAttributesToNavigationBar:(UINavigationBar *)navBar 50 | { 51 | NSDictionary *attributes = @{ UITextAttributeTextColor : [UIColor colorWithRed:122.0/255.0 green:120.0/255.0 blue:114.0/255.0 alpha:1.0], 52 | UITextAttributeTextShadowColor : [UIColor whiteColor], 53 | UITextAttributeTextShadowOffset : [NSValue valueWithCGSize:(CGSize){ .width = 0.0, .height = 1.0}] }; 54 | 55 | [navBar setTitleTextAttributes:attributes]; 56 | } 57 | 58 | - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation 59 | { 60 | if (popoverController && popoverController.popoverVisible) 61 | { 62 | [popoverController dismissPopoverAnimated:YES]; 63 | [self performSegueWithIdentifier:segueIdentifier sender:nil]; 64 | } 65 | } 66 | 67 | - (IBAction)switchToUsingFiles:(id)sender 68 | { 69 | [self.presentingViewController dismissViewControllerAnimated:YES completion:NULL]; 70 | } 71 | 72 | #pragma mark - iOS 6 rotation 73 | 74 | - (BOOL)shouldAutorotate 75 | { 76 | return YES; 77 | } 78 | 79 | - (UIInterfaceOrientationMask)supportedInterfaceOrientations 80 | { 81 | return UIInterfaceOrientationMaskAll; 82 | } 83 | 84 | 85 | #pragma mark - iOS 5 rotation 86 | 87 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation 88 | { 89 | return YES; 90 | } 91 | 92 | @end 93 | -------------------------------------------------------------------------------- /GIKPopoverBackgroundView/GIKPopoverBackgroundView.h: -------------------------------------------------------------------------------- 1 | // 2 | // GIKPopoverBackgroundView.h 3 | // 4 | // Created by Gordon Hughes on 1/7/13. 5 | // Copyright (c) 2013 Gordon Hughes. All rights reserved. 6 | // 7 | 8 | // To use, import this header in your class and add the following after the popover controller's declaration/instantiation: 9 | 10 | // popoverController.popoverBackgroundViewClass = [GIKPopoverBackgroundView class]; 11 | 12 | // To change the colors used for rendering, create a subclass of GIKPopoverBackgroundView and override the color methods. 13 | // You can also provide custom image files instead of rendering by subclassing and overriding the image methods and the appropriate size and inset methods. 14 | 15 | // Layout of images will be handled automatically, and it works with all values of UIPopoverArrowDirection. 16 | 17 | #import 18 | 19 | /** 20 | Image-specific values for calulating the background's layout. 21 | */ 22 | static const CGFloat kPopoverArrowWidth = 37.0; // Returned by +arrowBase, irrespective of orientation. The length of the base of the arrow's triangle. 23 | static const CGFloat kPopoverArrowHeight = 19.0; // Returned by +arrowHeight, irrespective of orientation. The height of the arrow from base to tip. 24 | static const CGFloat kPopoverCornerRadius = 7.0; // Used in a bounds check to determine if the arrow is too close to the popover's edge. 25 | static const CGFloat kSideArrowCenterOffset = 7.0; // Added to the arrow's center for ...Side.png image to account for the taller top half. 26 | 27 | /** 28 | Content and background insets. 29 | */ 30 | static const UIEdgeInsets kPopoverEdgeInsets = { 8.0, 8.0, 8.0, 8.0}; // Distance between the edge of the background view and the edge of the content view. 31 | 32 | /** 33 | Image-specific cap insets which specify a 1 point by 1 point area to be stretched. Changing the background images will likely require a different set of insets. 34 | */ 35 | static const UIEdgeInsets kArrowUpInsets = {41.0, 9.0, 9.0, 47.0}; 36 | static const UIEdgeInsets kArrowUpRightInsets = {41.0, 9.0, 9.0, 42.0}; 37 | static const UIEdgeInsets kArrowDownInsets = {23.0, 9.0, 27.0, 47.0}; 38 | static const UIEdgeInsets kArrowDownRightInsets = {23.0, 9.0, 27.0, 42.0}; 39 | static const UIEdgeInsets kArrowSideInsets = {24.0, 9.0, 47.0, 27.0}; 40 | static const UIEdgeInsets kArrowSideTopInsets = {43.0, 9.0, 23.0, 27.0}; 41 | static const UIEdgeInsets kArrowSideBottomInsets = {23.0, 9.0, 43.0, 27.0}; 42 | 43 | static const CGFloat kSecondHalfBottomInset = 9.0; // Value for .bottom inset in the second half of a two-part vertical stretch operation. 44 | static const CGFloat kSecondHalfRightInset = 9.0; // Value for .right inset in the seconf half of a two-part horizontal stretch operation. 45 | 46 | @interface GIKPopoverBackgroundView : UIPopoverBackgroundView 47 | { 48 | CGFloat _arrowOffset; 49 | UIPopoverArrowDirection _arrowDirection; 50 | } 51 | 52 | @property (nonatomic, assign) CGFloat arrowOffset; 53 | @property (nonatomic, assign) UIPopoverArrowDirection arrowDirection; 54 | 55 | 56 | 57 | /** 58 | Colors to be used when rendering the popover images. Override these methods in a subclass to provide custom colors. 59 | */ 60 | - (UIColor *)popoverBorderColor; 61 | - (UIColor *)popoverGradientFromColor; 62 | - (UIColor *)popoverGradientToColor; 63 | 64 | /** 65 | Override these methods in a subclass if you'd rather provide your own images than have them rendered. If your images are different dimensions than the 66 | ones rendered by this class, you will need to override the appropriate size and inset methods as well. 67 | */ 68 | - (UIImage *)arrowUpImage; 69 | - (UIImage *)arrowUpRightImage; 70 | - (UIImage *)arrowDownImage; 71 | - (UIImage *)arrowDownRightImage; 72 | - (UIImage *)arrowSideImage; 73 | - (UIImage *)arrowSideTopImage; 74 | - (UIImage *)arrowSideBottomImage; 75 | 76 | /** 77 | Sizing and inset information to override in your subclass if you provide custom images with different dimensions. 78 | */ 79 | + (CGFloat)arrowHeight; 80 | + (CGFloat)arrowBase; 81 | + (UIEdgeInsets)contentViewInsets; 82 | 83 | - (CGFloat)popoverCornerRadius; 84 | - (CGFloat)sideArrowCenterOffset; 85 | 86 | - (UIEdgeInsets)arrowUpInsets; 87 | - (UIEdgeInsets)arrowUpRightInsets; 88 | - (UIEdgeInsets)arrowDownInsets; 89 | - (UIEdgeInsets)arrowDownRightInsets; 90 | - (UIEdgeInsets)arrowSideInsets; 91 | - (UIEdgeInsets)arrowSideTopInsets; 92 | - (UIEdgeInsets)arrowSideBottomInsets; 93 | 94 | - (CGFloat)secondHalfBottomInset; 95 | - (CGFloat)secondHalfRightInset; 96 | 97 | @end 98 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GIKPopoverBackgroundView 2 | 3 | GIKPopoverBackgroundView is a UIPopoverBackgroundView subclass which uses images similar to those found in UIKit to customise the background of a UIPopoverController. 4 | 5 | Unlike most other third-party implementations, GIKPopoverBackgroundView doesn't use separate background and arrow images, so the appearance is seamless for all orientations. Images can be rendered by using a border color, a gradient from color, and a gradient to color, or they can be provided as files. 6 | 7 | ## Source Images 8 | 9 | The figure below shows the background images used by Apple's default implementation: 10 | 11 | Images making up Apple's default UIPopoverController background 12 | 13 | The DownRight, UpRight, SideBottom, and SideTop images are used when the popover is anchored to a control or rect in the corner or edge of a view. A point in the solid dark blue area is defined as the stretchable region using standard `UIEdgeInsets`. 14 | 15 | The Down, Up, and Side images require special handling. To draw a background with an up arrow centered horizontally, the Up image must be stretched twice - once on either side of the arrow. 16 | 17 | ## Photoshop Source 18 | 19 | Arrows were created using shape layers and layer styles in Photoshop. The .PSD contains both 1x and 2x shapes for each arrow. Notes for each layer document the Gradient Overlay style's colour stops and values. 20 | 21 | The file is [Slicy](http://macrabbit.com/slicy/) ready for easy exporting to .PNG. 22 | 23 | ## In Action 24 | 25 | [This short screencast](http://d.pr/v/49MN) of the example app demonstrates popovers drawn in a number of orientations from various anchor points. The navigation bar and toolbar of a popover controller take on the appearance of the background view with no additional development effort. 26 | 27 | ## Implementation Details 28 | 29 | ### To render or not to render 30 | 31 | The default behavior of GIKPopoverBackgroundView is to render the images needed using three colors. You can change the colors used by creating a custom subclass and overriding the following methods: 32 | 33 | ``` objective-c 34 | - (UIColor *)popoverBorderColor; 35 | - (UIColor *)popoverGradientFromColor; 36 | - (UIColor *)popoverGradientToColor; 37 | ``` 38 | 39 | Alternatively, if you would rather provide custom artwork for the images instead of rendering them you can override the following methods in your subclass: 40 | 41 | ``` objective-c 42 | - (UIImage *)arrowUpImage; 43 | - (UIImage *)arrowUpRightImage; 44 | - (UIImage *)arrowDownImage; 45 | - (UIImage *)arrowDownRightImage; 46 | - (UIImage *)arrowSideImage; 47 | - (UIImage *)arrowSideTopImage; 48 | - (UIImage *)arrowSideBottomImage; 49 | 50 | ``` 51 | 52 | If you do provide your own image files, and they do not match the dimensions of the rendered images, you will need to override some or all of the following methods: 53 | 54 | ```objective-c 55 | + (CGFloat)arrowHeight; 56 | + (CGFloat)arrowBase; 57 | + (UIEdgeInsets)contentViewInsets; 58 | 59 | - (CGFloat)popoverCornerRadius; 60 | - (CGFloat)sideArrowCenterOffset; 61 | 62 | - (UIEdgeInsets)arrowUpInsets; 63 | - (UIEdgeInsets)arrowUpRightInsets; 64 | - (UIEdgeInsets)arrowDownInsets; 65 | - (UIEdgeInsets)arrowDownRightInsets; 66 | - (UIEdgeInsets)arrowSideInsets; 67 | - (UIEdgeInsets)arrowSideTopInsets; 68 | - (UIEdgeInsets)arrowSideBottomInsets; 69 | 70 | - (CGFloat)secondHalfBottomInset; 71 | - (CGFloat)secondHalfRightInset; 72 | ``` 73 | 74 | ### Measure once, stretch twice 75 | 76 | Unsurprisingly, judicious use of UIImage's `-resizableImageWithCapInsets:` method is made throughout. For popovers which require two stretching operations, naively applying cap insets twice won't work. Specifying a stretchable region doesn't affect the underlying image until the image is drawn into a context or a view. 77 | 78 | The approach taken in GIKPopoverBackgroundView is to draw a stretchable image into a bitmap-based graphics context with appropriate size: 79 | 80 | ``` objective-c 81 | - (UIImage *)imageFromImageContextWithSourceImage:(UIImage *)image size:(CGSize)size 82 | { 83 | UIGraphicsBeginImageContextWithOptions(size, NO, 0.0); 84 | [image drawInRect:(CGRect){ .origin = CGPointZero, .size = size }]; 85 | UIImage *result = UIGraphicsGetImageFromCurrentImageContext(); 86 | UIGraphicsEndImageContext(); 87 | return result; 88 | } 89 | ``` 90 | 91 | A second set of cap insets are added to the resultant image and it's this new resizable image which is applied to the popover background's `UIImageView`. 92 | 93 | ### Mirror, mirror 94 | 95 | The same technique is used for popover backgrounds with any left-facing 'Side' arrows, 'UpLeft', or 'DownLeft' arrows. The source image is flipped horizontally and drawn into a bitmap-based graphics context before having cap insets applied: 96 | 97 | ``` objective-c 98 | - (UIImage *)mirroredImage:(UIImage *)image 99 | { 100 | UIImage *mirror = [UIImage imageWithCGImage:image.CGImage scale:[[UIScreen mainScreen] scale] orientation:UIImageOrientationUpMirrored]; 101 | return [self imageFromImageContextWithSourceImage:mirror size:mirror.size]; 102 | } 103 | ``` 104 | 105 | ### Drop shadows and iOS 5.x 106 | 107 | Background drop shadows don't work on subclasses of UIPopoverBackgroundView if the deployment target is iOS 5.x. If iOS 5 is detected, the drop shadow is drawn using the `shadowPath` of the background layer. 108 | 109 | Further complicating matters on iOS 5, the `shadowPath` property of `CALayer` doesn't respond to implicit animations such as changes to a layer's bounds. If the popover's geometry changes, an explicit animation must be added to the background layer to animate the shadow. 110 | 111 | The documentation for `UIPopoverBackgroundView` states that `-setArrowOffset:` is called inside an animation block managed by the UIPopoverController. This would seem to be the ideal place to sync the bounds and shadowPath animations. When `-setArrowOffset:` is called, we check the `animationKeys` array of the layer for the existance of a `bounds` key. If found, we know the background's frame is changing - possibly as the result of the keyboard appearing or disappearing. We apply the `timingFunction` and `duration` properties of the bounds animation to a new `CABasicAnimation` for the `shadowPath`. 112 | 113 | ``` objective-c 114 | - (void)addShadowPathAnimationIfNecessary:(CGPathRef)pathRef 115 | { 116 | NSArray *animationKeys = [self.popoverBackground.layer animationKeys]; 117 | if ([animationKeys containsObject:@"bounds"]) 118 | { 119 | CAAnimation *boundsAnimation = [self.popoverBackground.layer animationForKey:@"bounds"]; 120 | CABasicAnimation *shadowPathAnimation = [CABasicAnimation animationWithKeyPath:@"shadowPath"]; 121 | shadowPathAnimation.toValue = [NSValue valueWithPointer:pathRef]; 122 | shadowPathAnimation.timingFunction = boundsAnimation.timingFunction; 123 | shadowPathAnimation.duration = boundsAnimation.duration; 124 | [self.popoverBackground.layer addAnimation:shadowPathAnimation forKey:@"shadowPath"]; 125 | } 126 | } 127 | ``` 128 | 129 | ## Usage 130 | 131 | To use, add GIKPopoverBackgroundView.h and GIKPopoverBackgroundView.m to your Xcode project. Feel free to use the supplied images (found in the example project) and their default `UIEdgeInsets` values. In the view controller which manages your popover controller, set the popover controller's `popoverBackgroundViewClass` property: 132 | 133 | ``` objective-c 134 | popoverController = [(UIStoryboardPopoverSegue *)segue popoverController]; 135 | popoverController.popoverBackgroundViewClass = [GIKPopoverBackgroundView class]; 136 | ``` 137 | 138 | To change the colors of the rendered images, or to use image files, simply subclass GIKPopoverBackgroundView and override the appropriate methods. 139 | 140 | ## Sample Project 141 | 142 | The included sample project covers a number of scenarios where source images are stretched twice, mirrored, and animated in response to keyboard appearance. It also demonstrates the use of subclassing to override the colors used in rendering, or to override the images used for the popover background. 143 | 144 | ## Requirements 145 | 146 | GIKPopoverBackgroundView uses ARC and requires iOS 5.0 or above. 147 | 148 | ## //TODO: 149 | 150 | - ~~Add source .PSD files for the backgrounds to the repository.~~ 151 | - Discuss how cap insets were chosen to effect two-stage stretching. 152 | 153 | ## Credits 154 | 155 | GIKPopoverBackgroundView was created by [Gordon Hughes](https://github.com/gik/). 156 | 157 | ## Contact 158 | 159 | [Gordon Hughes](https://github.com/gik/) 160 | 161 | [@gordonhughes](http://twitter.com/gordonhughes) 162 | 163 | ## License 164 | 165 | GIKPopoverBackgroundView is available under the MIT license. See the LICENSE file for more information. 166 | -------------------------------------------------------------------------------- /GIKPopoverBackgroundView/GIKPopoverBackgroundView.m: -------------------------------------------------------------------------------- 1 | // 2 | // GIKPopoverBackgroundView.m 3 | // 4 | // Created by Gordon Hughes on 1/7/13. 5 | // Copyright (c) 2013 Gordon Hughes. All rights reserved. 6 | // 7 | 8 | #import "GIKPopoverBackgroundView.h" 9 | #import 10 | 11 | /** 12 | Types for the seven required background images. If a popover's arrowDirection is UIPopoverArrowDirectionLeft, the equivalent right-facing image will be mirrored. 13 | */ 14 | typedef enum { 15 | kArrowUp, 16 | kArrowUpRight, 17 | kArrowDown, 18 | kArrowDownRight, 19 | kArrowSide, 20 | kArrowSideTop, 21 | kArrowSideBottom 22 | } GIKPopoverBackgroundImageType; 23 | 24 | 25 | // A struct containing the min and max horizontal and vertical positions for the popover arrow. If the arrow's position exceeds these limits, the PopoverBackgroundArrow[UpRight|DownRight|SideTop|SideBottom].png images are drawn. 26 | struct GIKPopoverExtents { 27 | CGFloat left; 28 | CGFloat right; 29 | CGFloat top; 30 | CGFloat bottom; 31 | }; 32 | typedef struct GIKPopoverExtents GIKPopoverExtents; 33 | 34 | @interface GIKPopoverBackgroundView () { 35 | GIKPopoverExtents _popoverExtents; 36 | CGFloat _halfBase; 37 | CGFloat _arrowCenter; 38 | } 39 | 40 | @property (strong, nonatomic) UIImageView *popoverBackground; 41 | 42 | @end 43 | 44 | 45 | @implementation GIKPopoverBackgroundView 46 | 47 | @synthesize arrowOffset = _arrowOffset; 48 | @synthesize arrowDirection = _arrowDirection; 49 | 50 | 51 | #pragma mark - UIPopoverBackgroundView required values 52 | 53 | + (UIEdgeInsets)contentViewInsets 54 | { 55 | return kPopoverEdgeInsets; 56 | } 57 | 58 | + (CGFloat)arrowHeight 59 | { 60 | return kPopoverArrowHeight; 61 | } 62 | 63 | + (CGFloat)arrowBase 64 | { 65 | return kPopoverArrowWidth; 66 | } 67 | 68 | - (CGFloat)halfArrowBase 69 | { 70 | return [GIKPopoverBackgroundView arrowBase] / 2; 71 | } 72 | 73 | - (id)initWithFrame:(CGRect)frame 74 | { 75 | self = [super initWithFrame:frame]; 76 | if (self) 77 | { 78 | _popoverBackground = [[UIImageView alloc] initWithFrame:(CGRect){ .origin = CGPointZero, .size = frame.size }]; 79 | [self addSubview:_popoverBackground]; 80 | } 81 | return self; 82 | } 83 | 84 | - (void)setArrowOffset:(CGFloat)arrowOffset 85 | { 86 | _arrowOffset = arrowOffset; 87 | 88 | if (![UIPopoverBackgroundView respondsToSelector:@selector(wantsDefaultContentAppearance)]) 89 | { 90 | // -setArrowOffset is called inside an animation block managed by the UIPopoverController. If the frame of our popover is changing because, say, the keyboard is appearing or disappearing, we need to explicitly animate the shadowPath; implicit - in this case, UIKit - animations don't work on the shadowPath - the path will jump to its final value with no inbetweening. 91 | CGPathRef shadowPathRef = [self shadowPath]; 92 | [self addShadowPathAnimationIfNecessary:shadowPathRef]; // Comment out this line to see the effect of no explicit animation on the shadowPath. 93 | self.popoverBackground.layer.shadowPath = shadowPathRef; 94 | } 95 | [self setNeedsLayout]; 96 | } 97 | 98 | - (void)addShadowPathAnimationIfNecessary:(CGPathRef)pathRef 99 | { 100 | // If the layer's animationKeys array contains a string with the value "bounds", we know its frame is changing. Get the timingFunction and duration properties of that animation, and apply them to the shadowPath animation so that the two are in sync. 101 | NSArray *animationKeys = [self.popoverBackground.layer animationKeys]; 102 | if ([animationKeys containsObject:@"bounds"]) 103 | { 104 | CAAnimation *boundsAnimation = [self.popoverBackground.layer animationForKey:@"bounds"]; 105 | CABasicAnimation *shadowPathAnimation = [CABasicAnimation animationWithKeyPath:@"shadowPath"]; 106 | shadowPathAnimation.toValue = [NSValue valueWithPointer:pathRef]; 107 | shadowPathAnimation.timingFunction = boundsAnimation.timingFunction; 108 | shadowPathAnimation.duration = boundsAnimation.duration; 109 | [self.popoverBackground.layer addAnimation:shadowPathAnimation forKey:@"shadowPath"]; 110 | } 111 | } 112 | 113 | - (void)setArrowDirection:(UIPopoverArrowDirection)arrowDirection 114 | { 115 | _arrowDirection = arrowDirection; 116 | [self addDropShadowIfNecessary]; // Once we know the arrow's direction, we can add a drop shadow manually if we're on iOS 5.x. 117 | [self setNeedsLayout]; 118 | } 119 | 120 | - (void)addDropShadowIfNecessary 121 | { 122 | // Popover background drop shadows don't appear to work on iOS 5.x, so we have to draw the shadow manually. iOS 6.0 adds the +wantsDefaultAppearance class method. Check for the existence (or absence) of this method. 123 | if (![UIPopoverBackgroundView respondsToSelector:@selector(wantsDefaultContentAppearance)]) 124 | { 125 | CALayer *layer = self.popoverBackground.layer; 126 | layer.shadowColor = [UIColor blackColor].CGColor; 127 | layer.shadowOpacity = 0.9; 128 | layer.shadowRadius = 20.0; 129 | layer.shadowOffset = (CGSize){ .width = 0.0, .height = 10.0 }; 130 | } 131 | } 132 | 133 | - (void)layoutSubviews 134 | { 135 | [super layoutSubviews]; 136 | 137 | CGFloat popoverCornerRadius = [self popoverCornerRadius]; 138 | _popoverExtents = (GIKPopoverExtents){ 139 | .left = CGRectGetMinX(self.bounds) + popoverCornerRadius, 140 | .right = CGRectGetMaxX(self.bounds) - popoverCornerRadius, 141 | .top = CGRectGetMinY(self.bounds) + popoverCornerRadius, 142 | .bottom = CGRectGetMaxY(self.bounds) - popoverCornerRadius 143 | }; 144 | 145 | _halfBase = [self halfArrowBase]; 146 | _arrowCenter = [self arrowCenter]; 147 | 148 | // Because layoutSubviews is called on device rotation, the popoverBackground's center and bounds are reset so that any left arrow adjustments or frame resizing can be recalculated from their initial values. 149 | self.popoverBackground.center = self.center; 150 | self.popoverBackground.bounds = self.bounds; 151 | 152 | self.popoverBackground.image = [self wantsUpOrDownArrow] ? [self upOrDownArrowImage] : [self sideArrowImage]; 153 | } 154 | 155 | 156 | #pragma mark - Custom Layout 157 | 158 | - (CGPathRef)shadowPath 159 | { 160 | CGRect pathRect = self.bounds; 161 | 162 | CGFloat popoverArrowHeight = [[self class] arrowHeight]; 163 | if ([self wantsUpOrDownArrow]) 164 | { 165 | pathRect.origin.y = [self wantsUpArrow] ? popoverArrowHeight : 0.0; 166 | pathRect.size.height -= popoverArrowHeight; 167 | } 168 | else 169 | { 170 | pathRect.origin.x = (self.arrowDirection == UIPopoverArrowDirectionLeft) ? popoverArrowHeight : 0.0; 171 | pathRect.size.width -= popoverArrowHeight; 172 | } 173 | 174 | return [UIBezierPath bezierPathWithRect:pathRect].CGPath; 175 | } 176 | 177 | - (UIImage *)upOrDownArrowImage 178 | { 179 | GIKPopoverBackgroundImageType imageType; 180 | UIEdgeInsets insets; 181 | BOOL wantsUpArrow = [self wantsUpArrow]; 182 | 183 | if ([self isArrowBetweenLeftAndRightEdgesOfPopover]) 184 | { 185 | imageType = (wantsUpArrow) ? kArrowUp : kArrowDown; 186 | insets = (wantsUpArrow) ? [self arrowUpInsets] : [self arrowDownInsets]; 187 | return [self twoPartStretchableImageWithType:imageType insets:insets]; 188 | } 189 | else 190 | { 191 | imageType = (wantsUpArrow) ? kArrowUpRight : kArrowDownRight; 192 | insets = (wantsUpArrow) ? [self arrowUpRightInsets] : [self arrowDownRightInsets]; 193 | return [self stretchableImageWithType:imageType insets:insets mirrored:[self isArrowAtLeftEdgeOfPopover]]; 194 | } 195 | } 196 | 197 | - (UIImage *)sideArrowImage 198 | { 199 | [self adjustCentersIfNecessary]; 200 | 201 | if ([self isArrowBetweenTopAndBottomEdgesOfPopover]) 202 | { 203 | return [self twoPartStretchableImageWithType:kArrowSide insets:[self arrowSideInsets]]; 204 | } 205 | else 206 | { 207 | GIKPopoverBackgroundImageType imageType = [self isArrowAtTopEdgeOfPopover] ? kArrowSideTop : kArrowSideBottom; 208 | UIEdgeInsets insets = [self isArrowAtTopEdgeOfPopover] ? [self arrowSideTopInsets] : [self arrowSideBottomInsets]; 209 | return [self stretchableImageWithType:imageType insets:insets mirrored:(self.arrowDirection == UIPopoverArrowDirectionLeft)]; 210 | } 211 | } 212 | 213 | - (CGFloat)arrowCenter 214 | { 215 | CGFloat mid = ([self wantsUpOrDownArrow]) ? CGRectGetMidX(self.bounds) : CGRectGetMidY(self.bounds); 216 | return mid + self.arrowOffset; 217 | } 218 | 219 | 220 | - (BOOL)wantsUpOrDownArrow { return ([self wantsUpArrow] || self.arrowDirection == UIPopoverArrowDirectionDown); } 221 | 222 | - (BOOL)wantsUpArrow { return (self.arrowDirection == UIPopoverArrowDirectionUp); } 223 | 224 | - (BOOL)isArrowBetweenLeftAndRightEdgesOfPopover { return ![self isArrowAtRightEdgeOfPopover] && ![self isArrowAtLeftEdgeOfPopover]; } 225 | 226 | - (BOOL)isArrowAtLeftEdgeOfPopover { return (_arrowCenter - _halfBase < _popoverExtents.left); } 227 | 228 | - (BOOL)isArrowAtRightEdgeOfPopover { return (_arrowCenter + _halfBase > _popoverExtents.right); } 229 | 230 | - (BOOL)isArrowBetweenTopAndBottomEdgesOfPopover { return ![self isArrowAtTopEdgeOfPopover] && ![self isArrowAtBottomEdgeOfPopover]; } 231 | 232 | - (BOOL)isArrowAtTopEdgeOfPopover { return (_arrowCenter - _halfBase < _popoverExtents.top); } 233 | 234 | - (BOOL)isArrowAtBottomEdgeOfPopover { return (_arrowCenter + _halfBase > _popoverExtents.bottom); } 235 | 236 | 237 | - (void)adjustCentersIfNecessary 238 | { 239 | // fix centers of left-pointing popovers so that their shadows are drawn correctly. 240 | if (self.arrowDirection == UIPopoverArrowDirectionLeft) 241 | { 242 | self.center = (CGPoint){ .x = self.center.x + [GIKPopoverBackgroundView arrowHeight], .y = self.center.y }; 243 | self.popoverBackground.center = (CGPoint){ .x = self.popoverBackground.center.x - [GIKPopoverBackgroundView arrowHeight], .y = self.popoverBackground.center.y }; 244 | } 245 | } 246 | 247 | #pragma mark - Sizing and Insets 248 | 249 | - (CGFloat)popoverCornerRadius 250 | { 251 | return kPopoverCornerRadius; 252 | } 253 | 254 | - (CGFloat)sideArrowCenterOffset 255 | { 256 | return kSideArrowCenterOffset; 257 | } 258 | 259 | - (UIEdgeInsets)arrowUpInsets 260 | { 261 | return kArrowUpInsets; 262 | } 263 | 264 | - (UIEdgeInsets)arrowUpRightInsets 265 | { 266 | return kArrowUpRightInsets; 267 | } 268 | 269 | - (UIEdgeInsets)arrowDownInsets 270 | { 271 | return kArrowDownInsets; 272 | } 273 | 274 | - (UIEdgeInsets)arrowDownRightInsets 275 | { 276 | return kArrowDownRightInsets; 277 | } 278 | 279 | - (UIEdgeInsets)arrowSideInsets 280 | { 281 | return kArrowSideInsets; 282 | } 283 | 284 | - (UIEdgeInsets)arrowSideTopInsets 285 | { 286 | return kArrowSideTopInsets; 287 | } 288 | 289 | - (UIEdgeInsets)arrowSideBottomInsets 290 | { 291 | return kArrowSideBottomInsets; 292 | } 293 | 294 | - (CGFloat)secondHalfBottomInset 295 | { 296 | return kSecondHalfBottomInset; 297 | } 298 | 299 | - (CGFloat)secondHalfRightInset 300 | { 301 | return kSecondHalfRightInset; 302 | } 303 | 304 | #pragma mark - Stretching 305 | 306 | - (UIImage *)stretchableImageWithType:(GIKPopoverBackgroundImageType)imageType insets:(UIEdgeInsets)insets mirrored:(BOOL)mirrored 307 | { 308 | UIImage *image; 309 | 310 | switch (imageType) { 311 | case kArrowDown: 312 | image = [self arrowDownImage]; 313 | break; 314 | 315 | case kArrowDownRight: 316 | image = [self arrowDownRightImage]; 317 | break; 318 | 319 | case kArrowSide: 320 | image = [self arrowSideImage]; 321 | break; 322 | 323 | case kArrowSideBottom: 324 | image = [self arrowSideBottomImage]; 325 | break; 326 | 327 | case kArrowSideTop: 328 | image = [self arrowSideTopImage]; 329 | break; 330 | 331 | case kArrowUp: 332 | image = [self arrowUpImage]; 333 | break; 334 | 335 | case kArrowUpRight: 336 | image = [self arrowUpRightImage]; 337 | break; 338 | } 339 | 340 | return (mirrored) ? [[self mirroredImage:image] resizableImageWithCapInsets:[self mirroredInsets:insets]] : [image resizableImageWithCapInsets:insets]; 341 | } 342 | 343 | - (UIImage *)twoPartStretchableImageWithType:(GIKPopoverBackgroundImageType)imageType insets:(UIEdgeInsets)insets 344 | { 345 | UIImage *image; 346 | 347 | switch (imageType) { 348 | case kArrowDown: 349 | image = [self arrowDownImage]; 350 | break; 351 | 352 | case kArrowDownRight: 353 | image = [self arrowDownRightImage]; 354 | break; 355 | 356 | case kArrowSide: 357 | image = [self arrowSideImage]; 358 | break; 359 | 360 | case kArrowSideBottom: 361 | image = [self arrowSideBottomImage]; 362 | break; 363 | 364 | case kArrowSideTop: 365 | image = [self arrowSideTopImage]; 366 | break; 367 | 368 | case kArrowUp: 369 | image = [self arrowUpImage]; 370 | break; 371 | 372 | case kArrowUpRight: 373 | image = [self arrowUpRightImage]; 374 | break; 375 | } 376 | 377 | if (self.arrowDirection == UIPopoverArrowDirectionLeft) 378 | { 379 | image = [self mirroredImage:image]; 380 | insets = [self mirroredInsets:insets]; 381 | } 382 | 383 | UIImage *firstHalfImage = [image resizableImageWithCapInsets:insets]; 384 | UIImage *stretchedImage = [self imageFromImageContextWithSourceImage:firstHalfImage size:[self contextSizeForFirstHalfImage:image]]; 385 | return [stretchedImage resizableImageWithCapInsets:[self secondHalfInsetsForStretchedImage:stretchedImage insets:insets]]; 386 | } 387 | 388 | - (CGFloat)firstHalfStretchAmountForImage:(UIImage *)image 389 | { 390 | return roundf([self wantsUpOrDownArrow] ? _arrowCenter + (image.size.width - 1) / 2.0 : _arrowCenter + (image.size.height / 2) - 1 - [self sideArrowCenterOffset]); 391 | } 392 | 393 | - (CGSize)contextSizeForFirstHalfImage:(UIImage *)image 394 | { 395 | CGFloat stretch = [self firstHalfStretchAmountForImage:image]; 396 | return [self wantsUpOrDownArrow] ? (CGSize){ .width = stretch, .height = image.size.height } : (CGSize){ .width = image.size.width, .height = stretch }; 397 | } 398 | 399 | - (UIEdgeInsets)secondHalfInsetsForStretchedImage:(UIImage *)stretchedImage insets:(UIEdgeInsets)insets 400 | { 401 | return [self wantsUpOrDownArrow] ? [self horizontalInsetsForStretchedImage:stretchedImage insets:insets] : [self verticalInsetsForStretchedImage:stretchedImage insets:insets]; 402 | } 403 | 404 | - (UIEdgeInsets)horizontalInsetsForStretchedImage:(UIImage *)stretchedImage insets:(UIEdgeInsets)insets 405 | { 406 | CGFloat secondHalfRightInset = [self secondHalfRightInset]; 407 | return (UIEdgeInsets){ .top = insets.top, .left = stretchedImage.size.width - (secondHalfRightInset + 1), .bottom = insets.bottom, .right = secondHalfRightInset }; 408 | } 409 | 410 | - (UIEdgeInsets)verticalInsetsForStretchedImage:(UIImage *)stretchedImage insets:(UIEdgeInsets)insets 411 | { 412 | CGFloat secondHalfBottomInset = [self secondHalfBottomInset]; 413 | return (UIEdgeInsets){ .top = stretchedImage.size.height - (secondHalfBottomInset + 1), .left = insets.left, .bottom = secondHalfBottomInset, .right = insets.right }; 414 | } 415 | 416 | - (UIImage *)mirroredImage:(UIImage *)image 417 | { 418 | UIImage *mirror = [UIImage imageWithCGImage:image.CGImage scale:[[UIScreen mainScreen] scale] orientation:UIImageOrientationUpMirrored]; 419 | return [self imageFromImageContextWithSourceImage:mirror size:mirror.size]; 420 | } 421 | 422 | - (UIEdgeInsets)mirroredInsets:(UIEdgeInsets)insets 423 | { 424 | // Swap left and right insets for a mirrored image. 425 | return UIEdgeInsetsMake(insets.top, insets.right, insets.bottom, insets.left); 426 | } 427 | 428 | - (UIImage *)imageFromImageContextWithSourceImage:(UIImage *)image size:(CGSize)size 429 | { 430 | // Stretching/tiling only takes place when the image is drawn, so the mirrored or stretched image is first drawn into a context before applying additional stretching. 431 | UIGraphicsBeginImageContextWithOptions(size, NO, 0.0); 432 | [image drawInRect:(CGRect){ .origin = CGPointZero, .size = size }]; 433 | UIImage *result = UIGraphicsGetImageFromCurrentImageContext(); 434 | UIGraphicsEndImageContext(); 435 | return result; 436 | } 437 | 438 | 439 | #pragma mark - Image Generation 440 | 441 | - (void)drawUpArrowPopoverImageInPath:(CGMutablePathRef)path withTransform:(CGAffineTransform *)transform 442 | { 443 | CGPathMoveToPoint(path, transform, 28, 1); 444 | CGPathAddLineToPoint(path, transform, 46, 19); 445 | CGPathAddLineToPoint(path, transform, 48, 19); 446 | CGPathAddArcToPoint(path, transform, 55, 19, 55, 26, 7); 447 | CGPathAddLineToPoint(path, transform, 55, 42); 448 | CGPathAddArcToPoint(path, transform, 55, 49, 48, 49, 7); 449 | CGPathAddLineToPoint(path, transform, 8, 49); 450 | CGPathAddArcToPoint(path, transform, 1, 49, 1, 42, 7); 451 | CGPathAddLineToPoint(path, transform, 1, 26); 452 | CGPathAddArcToPoint(path, transform, 1, 19, 8, 19, 7); 453 | CGPathAddLineToPoint(path, transform, 10, 19); 454 | CGPathCloseSubpath(path); 455 | } 456 | 457 | - (void)drawUpRightArrowPopoverImageInPath:(CGMutablePathRef)path withTransform:(CGAffineTransform *)transform 458 | { 459 | CGPathMoveToPoint(path, transform, 28, 1); 460 | CGPathAddLineToPoint(path, transform, 46, 19); 461 | CGPathAddCurveToPoint(path, transform, 49, 21, 50, 23, 50, 26); 462 | CGPathAddLineToPoint(path, transform, 50, 42); 463 | CGPathAddArcToPoint(path, transform, 50, 49, 43, 49, 7); 464 | CGPathAddLineToPoint(path, transform, 8, 49); 465 | CGPathAddArcToPoint(path, transform, 1, 49, 1, 42, 7); 466 | CGPathAddLineToPoint(path, transform, 1, 26); 467 | CGPathAddArcToPoint(path, transform, 1, 19, 8, 19, 7); 468 | CGPathAddLineToPoint(path, transform, 10, 19); 469 | CGPathCloseSubpath(path); 470 | } 471 | 472 | - (void)drawSideArrowPopoverImageInPath:(CGMutablePathRef)path withTransform:(CGAffineTransform *)transform 473 | { 474 | CGPathMoveToPoint(path, transform, 35, 43); 475 | CGPathAddLineToPoint(path, transform, 17, 61); 476 | CGPathAddLineToPoint(path, transform, 17, 63); 477 | CGPathAddArcToPoint(path, transform, 17, 70, 10, 70, 7); 478 | CGPathAddLineToPoint(path, transform, 8, 70); 479 | CGPathAddArcToPoint(path, transform, 1, 70, 1, 63, 7); 480 | CGPathAddLineToPoint(path, transform, 1, 8); 481 | CGPathAddArcToPoint(path, transform, 1, 1, 8, 1, 7); 482 | CGPathAddLineToPoint(path, transform, 10, 1); 483 | CGPathAddArcToPoint(path, transform, 17, 1, 17, 8, 7); 484 | CGPathAddLineToPoint(path, transform, 17, 25); 485 | CGPathCloseSubpath(path); 486 | } 487 | 488 | - (void)drawSideBottomArrowPopoverImageInPath:(CGMutablePathRef)path withTransform:(CGAffineTransform *)transform 489 | { 490 | CGPathMoveToPoint(path, transform, 35, 43); 491 | CGPathAddLineToPoint(path, transform, 17, 61); 492 | CGPathAddCurveToPoint(path, transform, 15, 64, 13, 65, 10, 65); 493 | CGPathAddLineToPoint(path, transform, 8, 65); 494 | CGPathAddArcToPoint(path, transform, 1, 65, 1, 58, 7); 495 | CGPathAddLineToPoint(path, transform, 1, 8); 496 | CGPathAddArcToPoint(path, transform, 1, 1, 8, 1, 7); 497 | CGPathAddLineToPoint(path, transform, 10, 1); 498 | CGPathAddArcToPoint(path, transform, 17, 1, 17, 8, 7); 499 | CGPathAddLineToPoint(path, transform, 17, 25); 500 | CGPathCloseSubpath(path); 501 | 502 | } 503 | 504 | // Subclass can override these methods to provide custom artwork 505 | - (UIImage *)arrowUpImage 506 | { 507 | CGMutablePathRef path = CGPathCreateMutable(); 508 | 509 | [self drawUpArrowPopoverImageInPath:path withTransform:NULL]; 510 | UIImage *image = [self imageForPath:path withSize:CGSizeMake(57,51)]; 511 | 512 | CGPathRelease(path); 513 | return image; 514 | } 515 | 516 | - (UIImage *)arrowUpRightImage 517 | { 518 | CGMutablePathRef path = CGPathCreateMutable(); 519 | 520 | [self drawUpRightArrowPopoverImageInPath:path withTransform:NULL]; 521 | UIImage *image = [self imageForPath:path withSize:CGSizeMake(52, 51)]; 522 | 523 | CGPathRelease(path); 524 | return image; 525 | } 526 | 527 | - (UIImage *)arrowDownImage 528 | { 529 | CGMutablePathRef path = CGPathCreateMutable(); 530 | CGAffineTransform flip = CGAffineTransformMake(1, 0, 0, -1, 0, 51); 531 | 532 | [self drawUpArrowPopoverImageInPath:path withTransform:&flip]; 533 | UIImage *image = [self imageForPath:path withSize:CGSizeMake(57,51)]; 534 | 535 | CGPathRelease(path); 536 | return image; 537 | } 538 | 539 | - (UIImage *)arrowDownRightImage 540 | { 541 | CGMutablePathRef path = CGPathCreateMutable(); 542 | CGAffineTransform flip = CGAffineTransformMake(1, 0, 0, -1, 0, 51); 543 | 544 | [self drawUpRightArrowPopoverImageInPath:path withTransform:&flip]; 545 | UIImage *image = [self imageForPath:path withSize:CGSizeMake(52,51)]; 546 | 547 | CGPathRelease(path); 548 | return image; 549 | } 550 | 551 | - (UIImage *)arrowSideImage 552 | { 553 | CGMutablePathRef path = CGPathCreateMutable(); 554 | 555 | [self drawSideArrowPopoverImageInPath:path withTransform:NULL]; 556 | UIImage *image = [self imageForPath:path withSize:CGSizeMake(37, 72)]; 557 | 558 | CGPathRelease(path); 559 | return image; 560 | } 561 | 562 | - (UIImage *)arrowSideTopImage 563 | { 564 | CGMutablePathRef path = CGPathCreateMutable(); 565 | CGAffineTransform flip = CGAffineTransformMake(1, 0, 0, -1, 0, 67); 566 | 567 | [self drawSideBottomArrowPopoverImageInPath:path withTransform:&flip]; 568 | UIImage *image = [self imageForPath:path withSize:CGSizeMake(37, 67)]; 569 | 570 | CGPathRelease(path); 571 | return image; 572 | } 573 | 574 | - (UIImage *)arrowSideBottomImage 575 | { 576 | CGMutablePathRef path = CGPathCreateMutable(); 577 | 578 | [self drawSideBottomArrowPopoverImageInPath:path withTransform:NULL]; 579 | UIImage *image = [self imageForPath:path withSize:CGSizeMake(37, 67)]; 580 | 581 | CGPathRelease(path); 582 | return image; 583 | } 584 | 585 | 586 | - (UIImage *)imageForPath:(CGPathRef)path withSize:(CGSize)size 587 | { 588 | UIGraphicsBeginImageContextWithOptions(size, NO, 0); 589 | CGContextRef context = UIGraphicsGetCurrentContext(); 590 | 591 | // Draw a gradient 592 | CGContextAddPath(context, path); 593 | CGContextClip(context); 594 | 595 | CGColorRef colors[] = { [self popoverGradientFromColor].CGColor, [self popoverGradientToColor].CGColor }; 596 | CFArrayRef colorsArray = CFArrayCreate(NULL, (const void**)colors, sizeof(colors) / sizeof(CGColorRef), &kCFTypeArrayCallBacks); 597 | 598 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 599 | CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, colorsArray, NULL); 600 | CFRelease(colorSpace); 601 | CFRelease(colorsArray); 602 | 603 | CGPoint gradientStart = CGPointMake(size.width / 2, 0); 604 | CGPoint gradientEnd = CGPointMake(size.width / 2, size.height); 605 | CGContextDrawLinearGradient(context, gradient, gradientStart, gradientEnd, 0); 606 | CGGradientRelease(gradient); 607 | 608 | // Draw the border 609 | [[self popoverBorderColor] setStroke]; 610 | CGContextAddPath(context, path); 611 | CGContextStrokePath(context); 612 | 613 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 614 | UIGraphicsEndImageContext(); 615 | 616 | return image; 617 | } 618 | 619 | 620 | // Subclass can override these methods to provide custom colors 621 | - (UIColor *)popoverBorderColor 622 | { 623 | return [UIColor blackColor]; 624 | } 625 | 626 | - (UIColor *)popoverGradientFromColor 627 | { 628 | // In your subclass, use an alpha of 0.8 to get about the same amount of transparency as the default UIKit popovers 629 | return [UIColor colorWithRed:0.8 green:0.8 blue:0.8 alpha:0.8]; 630 | } 631 | 632 | - (UIColor *)popoverGradientToColor 633 | { 634 | return [UIColor darkGrayColor]; 635 | } 636 | 637 | @end 638 | -------------------------------------------------------------------------------- /GIKPopoverBackgroundView.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 60EE6245169BD75E00BCC23D /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 60EE6244169BD75E00BCC23D /* UIKit.framework */; }; 11 | 60EE6247169BD75E00BCC23D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 60EE6246169BD75E00BCC23D /* Foundation.framework */; }; 12 | 60EE6249169BD75E00BCC23D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 60EE6248169BD75E00BCC23D /* CoreGraphics.framework */; }; 13 | 60EE6251169BD75F00BCC23D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 60EE6250169BD75F00BCC23D /* main.m */; }; 14 | 60EE6255169BD75F00BCC23D /* GIKAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 60EE6254169BD75F00BCC23D /* GIKAppDelegate.m */; }; 15 | 60EE6257169BD75F00BCC23D /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 60EE6256169BD75F00BCC23D /* Default.png */; }; 16 | 60EE6259169BD75F00BCC23D /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 60EE6258169BD75F00BCC23D /* Default@2x.png */; }; 17 | 60EE625B169BD75F00BCC23D /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 60EE625A169BD75F00BCC23D /* Default-568h@2x.png */; }; 18 | 60EE6276169BDC7700BCC23D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 60EE6274169BDC7700BCC23D /* InfoPlist.strings */; }; 19 | 60EE627A169BDCE100BCC23D /* GIKPopoverBackgroundView.m in Sources */ = {isa = PBXBuildFile; fileRef = 60EE6279169BDCE100BCC23D /* GIKPopoverBackgroundView.m */; }; 20 | 60EE6280169BDD4700BCC23D /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 60EE627F169BDD4700BCC23D /* QuartzCore.framework */; }; 21 | 60EE6294169BDE2400BCC23D /* PopoverBackgroundArrowDown.png in Resources */ = {isa = PBXBuildFile; fileRef = 60EE6286169BDE2400BCC23D /* PopoverBackgroundArrowDown.png */; }; 22 | 60EE6295169BDE2400BCC23D /* PopoverBackgroundArrowDown@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 60EE6287169BDE2400BCC23D /* PopoverBackgroundArrowDown@2x.png */; }; 23 | 60EE6296169BDE2400BCC23D /* PopoverBackgroundArrowDownRight.png in Resources */ = {isa = PBXBuildFile; fileRef = 60EE6288169BDE2400BCC23D /* PopoverBackgroundArrowDownRight.png */; }; 24 | 60EE6297169BDE2400BCC23D /* PopoverBackgroundArrowDownRight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 60EE6289169BDE2400BCC23D /* PopoverBackgroundArrowDownRight@2x.png */; }; 25 | 60EE6298169BDE2400BCC23D /* PopoverBackgroundArrowSide.png in Resources */ = {isa = PBXBuildFile; fileRef = 60EE628A169BDE2400BCC23D /* PopoverBackgroundArrowSide.png */; }; 26 | 60EE6299169BDE2400BCC23D /* PopoverBackgroundArrowSide@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 60EE628B169BDE2400BCC23D /* PopoverBackgroundArrowSide@2x.png */; }; 27 | 60EE629A169BDE2400BCC23D /* PopoverBackgroundArrowSideBottom.png in Resources */ = {isa = PBXBuildFile; fileRef = 60EE628C169BDE2400BCC23D /* PopoverBackgroundArrowSideBottom.png */; }; 28 | 60EE629B169BDE2400BCC23D /* PopoverBackgroundArrowSideBottom@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 60EE628D169BDE2400BCC23D /* PopoverBackgroundArrowSideBottom@2x.png */; }; 29 | 60EE629C169BDE2400BCC23D /* PopoverBackgroundArrowSideTop.png in Resources */ = {isa = PBXBuildFile; fileRef = 60EE628E169BDE2400BCC23D /* PopoverBackgroundArrowSideTop.png */; }; 30 | 60EE629D169BDE2400BCC23D /* PopoverBackgroundArrowSideTop@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 60EE628F169BDE2400BCC23D /* PopoverBackgroundArrowSideTop@2x.png */; }; 31 | 60EE629E169BDE2400BCC23D /* PopoverBackgroundArrowUp.png in Resources */ = {isa = PBXBuildFile; fileRef = 60EE6290169BDE2400BCC23D /* PopoverBackgroundArrowUp.png */; }; 32 | 60EE629F169BDE2400BCC23D /* PopoverBackgroundArrowUp@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 60EE6291169BDE2400BCC23D /* PopoverBackgroundArrowUp@2x.png */; }; 33 | 60EE62A0169BDE2400BCC23D /* PopoverBackgroundArrowUpRight.png in Resources */ = {isa = PBXBuildFile; fileRef = 60EE6292169BDE2400BCC23D /* PopoverBackgroundArrowUpRight.png */; }; 34 | 60EE62A1169BDE2400BCC23D /* PopoverBackgroundArrowUpRight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 60EE6293169BDE2400BCC23D /* PopoverBackgroundArrowUpRight@2x.png */; }; 35 | 83C7116E16F8C3AE00C97BDD /* MainStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 83C7116D16F8C3AE00C97BDD /* MainStoryboard.storyboard */; }; 36 | 83C7117316F8C3CD00C97BDD /* GIKImageFilesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 83C7117016F8C3CD00C97BDD /* GIKImageFilesViewController.m */; }; 37 | 83C7117416F8C3CD00C97BDD /* GIKRenderedImagesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 83C7117216F8C3CD00C97BDD /* GIKRenderedImagesViewController.m */; }; 38 | 83C7117A16F8C3E600C97BDD /* GIKImageFilesPopoverBackgroundView.m in Sources */ = {isa = PBXBuildFile; fileRef = 83C7117716F8C3E600C97BDD /* GIKImageFilesPopoverBackgroundView.m */; }; 39 | 83C7117B16F8C3E600C97BDD /* GIKRenderedImagesPopoverBackgroundView.m in Sources */ = {isa = PBXBuildFile; fileRef = 83C7117916F8C3E600C97BDD /* GIKRenderedImagesPopoverBackgroundView.m */; }; 40 | F86BD86316ED83A400E78040 /* GIKPopoverBackgroundView.podspec in Resources */ = {isa = PBXBuildFile; fileRef = F86BD86216ED83A400E78040 /* GIKPopoverBackgroundView.podspec */; }; 41 | /* End PBXBuildFile section */ 42 | 43 | /* Begin PBXFileReference section */ 44 | 60EE6240169BD75E00BCC23D /* GIKPopoverBackgroundView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GIKPopoverBackgroundView.app; sourceTree = BUILT_PRODUCTS_DIR; }; 45 | 60EE6244169BD75E00BCC23D /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 46 | 60EE6246169BD75E00BCC23D /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 47 | 60EE6248169BD75E00BCC23D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 48 | 60EE624C169BD75F00BCC23D /* GIKPopoverBackgroundView-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GIKPopoverBackgroundView-Info.plist"; sourceTree = ""; }; 49 | 60EE6250169BD75F00BCC23D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 50 | 60EE6252169BD75F00BCC23D /* GIKPopoverBackgroundView-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "GIKPopoverBackgroundView-Prefix.pch"; sourceTree = ""; }; 51 | 60EE6253169BD75F00BCC23D /* GIKAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GIKAppDelegate.h; sourceTree = ""; }; 52 | 60EE6254169BD75F00BCC23D /* GIKAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GIKAppDelegate.m; sourceTree = ""; }; 53 | 60EE6256169BD75F00BCC23D /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; 54 | 60EE6258169BD75F00BCC23D /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; 55 | 60EE625A169BD75F00BCC23D /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 56 | 60EE6275169BDC7700BCC23D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 57 | 60EE6278169BDCE100BCC23D /* GIKPopoverBackgroundView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GIKPopoverBackgroundView.h; sourceTree = ""; }; 58 | 60EE6279169BDCE100BCC23D /* GIKPopoverBackgroundView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GIKPopoverBackgroundView.m; sourceTree = ""; }; 59 | 60EE627F169BDD4700BCC23D /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 60 | 60EE6286169BDE2400BCC23D /* PopoverBackgroundArrowDown.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = PopoverBackgroundArrowDown.png; sourceTree = ""; }; 61 | 60EE6287169BDE2400BCC23D /* PopoverBackgroundArrowDown@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "PopoverBackgroundArrowDown@2x.png"; sourceTree = ""; }; 62 | 60EE6288169BDE2400BCC23D /* PopoverBackgroundArrowDownRight.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = PopoverBackgroundArrowDownRight.png; sourceTree = ""; }; 63 | 60EE6289169BDE2400BCC23D /* PopoverBackgroundArrowDownRight@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "PopoverBackgroundArrowDownRight@2x.png"; sourceTree = ""; }; 64 | 60EE628A169BDE2400BCC23D /* PopoverBackgroundArrowSide.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = PopoverBackgroundArrowSide.png; sourceTree = ""; }; 65 | 60EE628B169BDE2400BCC23D /* PopoverBackgroundArrowSide@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "PopoverBackgroundArrowSide@2x.png"; sourceTree = ""; }; 66 | 60EE628C169BDE2400BCC23D /* PopoverBackgroundArrowSideBottom.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = PopoverBackgroundArrowSideBottom.png; sourceTree = ""; }; 67 | 60EE628D169BDE2400BCC23D /* PopoverBackgroundArrowSideBottom@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "PopoverBackgroundArrowSideBottom@2x.png"; sourceTree = ""; }; 68 | 60EE628E169BDE2400BCC23D /* PopoverBackgroundArrowSideTop.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = PopoverBackgroundArrowSideTop.png; sourceTree = ""; }; 69 | 60EE628F169BDE2400BCC23D /* PopoverBackgroundArrowSideTop@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "PopoverBackgroundArrowSideTop@2x.png"; sourceTree = ""; }; 70 | 60EE6290169BDE2400BCC23D /* PopoverBackgroundArrowUp.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = PopoverBackgroundArrowUp.png; sourceTree = ""; }; 71 | 60EE6291169BDE2400BCC23D /* PopoverBackgroundArrowUp@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "PopoverBackgroundArrowUp@2x.png"; sourceTree = ""; }; 72 | 60EE6292169BDE2400BCC23D /* PopoverBackgroundArrowUpRight.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = PopoverBackgroundArrowUpRight.png; sourceTree = ""; }; 73 | 60EE6293169BDE2400BCC23D /* PopoverBackgroundArrowUpRight@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "PopoverBackgroundArrowUpRight@2x.png"; sourceTree = ""; }; 74 | 83C7116D16F8C3AE00C97BDD /* MainStoryboard.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = MainStoryboard.storyboard; sourceTree = ""; }; 75 | 83C7116F16F8C3CD00C97BDD /* GIKImageFilesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GIKImageFilesViewController.h; sourceTree = ""; }; 76 | 83C7117016F8C3CD00C97BDD /* GIKImageFilesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GIKImageFilesViewController.m; sourceTree = ""; }; 77 | 83C7117116F8C3CD00C97BDD /* GIKRenderedImagesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GIKRenderedImagesViewController.h; sourceTree = ""; }; 78 | 83C7117216F8C3CD00C97BDD /* GIKRenderedImagesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GIKRenderedImagesViewController.m; sourceTree = ""; }; 79 | 83C7117616F8C3E600C97BDD /* GIKImageFilesPopoverBackgroundView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GIKImageFilesPopoverBackgroundView.h; sourceTree = ""; }; 80 | 83C7117716F8C3E600C97BDD /* GIKImageFilesPopoverBackgroundView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GIKImageFilesPopoverBackgroundView.m; sourceTree = ""; }; 81 | 83C7117816F8C3E600C97BDD /* GIKRenderedImagesPopoverBackgroundView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GIKRenderedImagesPopoverBackgroundView.h; sourceTree = ""; }; 82 | 83C7117916F8C3E600C97BDD /* GIKRenderedImagesPopoverBackgroundView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GIKRenderedImagesPopoverBackgroundView.m; sourceTree = ""; }; 83 | F86BD86216ED83A400E78040 /* GIKPopoverBackgroundView.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = GIKPopoverBackgroundView.podspec; sourceTree = ""; }; 84 | F878510C1CCEB2E50071B3F6 /* GIKPopoverBackgroundViewArrows.psd */ = {isa = PBXFileReference; lastKnownFileType = file; name = GIKPopoverBackgroundViewArrows.psd; path = "Photoshop Source/GIKPopoverBackgroundViewArrows.psd"; sourceTree = ""; }; 85 | /* End PBXFileReference section */ 86 | 87 | /* Begin PBXFrameworksBuildPhase section */ 88 | 60EE623D169BD75E00BCC23D /* Frameworks */ = { 89 | isa = PBXFrameworksBuildPhase; 90 | buildActionMask = 2147483647; 91 | files = ( 92 | 60EE6280169BDD4700BCC23D /* QuartzCore.framework in Frameworks */, 93 | 60EE6245169BD75E00BCC23D /* UIKit.framework in Frameworks */, 94 | 60EE6247169BD75E00BCC23D /* Foundation.framework in Frameworks */, 95 | 60EE6249169BD75E00BCC23D /* CoreGraphics.framework in Frameworks */, 96 | ); 97 | runOnlyForDeploymentPostprocessing = 0; 98 | }; 99 | /* End PBXFrameworksBuildPhase section */ 100 | 101 | /* Begin PBXGroup section */ 102 | 60EE6235169BD75E00BCC23D = { 103 | isa = PBXGroup; 104 | children = ( 105 | 60EE624A169BD75E00BCC23D /* GIKPopoverBackgroundView-Example */, 106 | 60EE6277169BDCE100BCC23D /* GIKPopoverBackgroundView */, 107 | F878510B1CCEB2B40071B3F6 /* Photoshop Source */, 108 | 60EE6243169BD75E00BCC23D /* Frameworks */, 109 | 60EE6241169BD75E00BCC23D /* Products */, 110 | ); 111 | sourceTree = ""; 112 | }; 113 | 60EE6241169BD75E00BCC23D /* Products */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | 60EE6240169BD75E00BCC23D /* GIKPopoverBackgroundView.app */, 117 | ); 118 | name = Products; 119 | sourceTree = ""; 120 | }; 121 | 60EE6243169BD75E00BCC23D /* Frameworks */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 60EE627F169BDD4700BCC23D /* QuartzCore.framework */, 125 | 60EE6244169BD75E00BCC23D /* UIKit.framework */, 126 | 60EE6246169BD75E00BCC23D /* Foundation.framework */, 127 | 60EE6248169BD75E00BCC23D /* CoreGraphics.framework */, 128 | ); 129 | name = Frameworks; 130 | sourceTree = ""; 131 | }; 132 | 60EE624A169BD75E00BCC23D /* GIKPopoverBackgroundView-Example */ = { 133 | isa = PBXGroup; 134 | children = ( 135 | 83C7117516F8C3D000C97BDD /* Background View Subclasses */, 136 | 60EE6285169BDE2400BCC23D /* Images */, 137 | 83C7116D16F8C3AE00C97BDD /* MainStoryboard.storyboard */, 138 | 60EE6253169BD75F00BCC23D /* GIKAppDelegate.h */, 139 | 60EE6254169BD75F00BCC23D /* GIKAppDelegate.m */, 140 | 83C7116F16F8C3CD00C97BDD /* GIKImageFilesViewController.h */, 141 | 83C7117016F8C3CD00C97BDD /* GIKImageFilesViewController.m */, 142 | 83C7117116F8C3CD00C97BDD /* GIKRenderedImagesViewController.h */, 143 | 83C7117216F8C3CD00C97BDD /* GIKRenderedImagesViewController.m */, 144 | 60EE624B169BD75F00BCC23D /* Supporting Files */, 145 | ); 146 | path = "GIKPopoverBackgroundView-Example"; 147 | sourceTree = ""; 148 | }; 149 | 60EE624B169BD75F00BCC23D /* Supporting Files */ = { 150 | isa = PBXGroup; 151 | children = ( 152 | 60EE6274169BDC7700BCC23D /* InfoPlist.strings */, 153 | 60EE624C169BD75F00BCC23D /* GIKPopoverBackgroundView-Info.plist */, 154 | 60EE6250169BD75F00BCC23D /* main.m */, 155 | 60EE6252169BD75F00BCC23D /* GIKPopoverBackgroundView-Prefix.pch */, 156 | 60EE6256169BD75F00BCC23D /* Default.png */, 157 | 60EE6258169BD75F00BCC23D /* Default@2x.png */, 158 | 60EE625A169BD75F00BCC23D /* Default-568h@2x.png */, 159 | ); 160 | name = "Supporting Files"; 161 | sourceTree = ""; 162 | }; 163 | 60EE6277169BDCE100BCC23D /* GIKPopoverBackgroundView */ = { 164 | isa = PBXGroup; 165 | children = ( 166 | 60EE6278169BDCE100BCC23D /* GIKPopoverBackgroundView.h */, 167 | 60EE6279169BDCE100BCC23D /* GIKPopoverBackgroundView.m */, 168 | F86BD86216ED83A400E78040 /* GIKPopoverBackgroundView.podspec */, 169 | ); 170 | path = GIKPopoverBackgroundView; 171 | sourceTree = ""; 172 | }; 173 | 60EE6285169BDE2400BCC23D /* Images */ = { 174 | isa = PBXGroup; 175 | children = ( 176 | 60EE6286169BDE2400BCC23D /* PopoverBackgroundArrowDown.png */, 177 | 60EE6287169BDE2400BCC23D /* PopoverBackgroundArrowDown@2x.png */, 178 | 60EE6288169BDE2400BCC23D /* PopoverBackgroundArrowDownRight.png */, 179 | 60EE6289169BDE2400BCC23D /* PopoverBackgroundArrowDownRight@2x.png */, 180 | 60EE628A169BDE2400BCC23D /* PopoverBackgroundArrowSide.png */, 181 | 60EE628B169BDE2400BCC23D /* PopoverBackgroundArrowSide@2x.png */, 182 | 60EE628C169BDE2400BCC23D /* PopoverBackgroundArrowSideBottom.png */, 183 | 60EE628D169BDE2400BCC23D /* PopoverBackgroundArrowSideBottom@2x.png */, 184 | 60EE628E169BDE2400BCC23D /* PopoverBackgroundArrowSideTop.png */, 185 | 60EE628F169BDE2400BCC23D /* PopoverBackgroundArrowSideTop@2x.png */, 186 | 60EE6290169BDE2400BCC23D /* PopoverBackgroundArrowUp.png */, 187 | 60EE6291169BDE2400BCC23D /* PopoverBackgroundArrowUp@2x.png */, 188 | 60EE6292169BDE2400BCC23D /* PopoverBackgroundArrowUpRight.png */, 189 | 60EE6293169BDE2400BCC23D /* PopoverBackgroundArrowUpRight@2x.png */, 190 | ); 191 | path = Images; 192 | sourceTree = ""; 193 | }; 194 | 83C7117516F8C3D000C97BDD /* Background View Subclasses */ = { 195 | isa = PBXGroup; 196 | children = ( 197 | 83C7117616F8C3E600C97BDD /* GIKImageFilesPopoverBackgroundView.h */, 198 | 83C7117716F8C3E600C97BDD /* GIKImageFilesPopoverBackgroundView.m */, 199 | 83C7117816F8C3E600C97BDD /* GIKRenderedImagesPopoverBackgroundView.h */, 200 | 83C7117916F8C3E600C97BDD /* GIKRenderedImagesPopoverBackgroundView.m */, 201 | ); 202 | name = "Background View Subclasses"; 203 | sourceTree = ""; 204 | }; 205 | F878510B1CCEB2B40071B3F6 /* Photoshop Source */ = { 206 | isa = PBXGroup; 207 | children = ( 208 | F878510C1CCEB2E50071B3F6 /* GIKPopoverBackgroundViewArrows.psd */, 209 | ); 210 | name = "Photoshop Source"; 211 | sourceTree = ""; 212 | }; 213 | /* End PBXGroup section */ 214 | 215 | /* Begin PBXNativeTarget section */ 216 | 60EE623F169BD75E00BCC23D /* GIKPopoverBackgroundView */ = { 217 | isa = PBXNativeTarget; 218 | buildConfigurationList = 60EE6264169BD75F00BCC23D /* Build configuration list for PBXNativeTarget "GIKPopoverBackgroundView" */; 219 | buildPhases = ( 220 | 60EE623C169BD75E00BCC23D /* Sources */, 221 | 60EE623D169BD75E00BCC23D /* Frameworks */, 222 | 60EE623E169BD75E00BCC23D /* Resources */, 223 | ); 224 | buildRules = ( 225 | ); 226 | dependencies = ( 227 | ); 228 | name = GIKPopoverBackgroundView; 229 | productName = GIKPopoverBackgroundView; 230 | productReference = 60EE6240169BD75E00BCC23D /* GIKPopoverBackgroundView.app */; 231 | productType = "com.apple.product-type.application"; 232 | }; 233 | /* End PBXNativeTarget section */ 234 | 235 | /* Begin PBXProject section */ 236 | 60EE6237169BD75E00BCC23D /* Project object */ = { 237 | isa = PBXProject; 238 | attributes = { 239 | CLASSPREFIX = GIK; 240 | LastUpgradeCheck = 0730; 241 | ORGANIZATIONNAME = "Gordon Hughes"; 242 | }; 243 | buildConfigurationList = 60EE623A169BD75E00BCC23D /* Build configuration list for PBXProject "GIKPopoverBackgroundView" */; 244 | compatibilityVersion = "Xcode 3.2"; 245 | developmentRegion = English; 246 | hasScannedForEncodings = 0; 247 | knownRegions = ( 248 | en, 249 | ); 250 | mainGroup = 60EE6235169BD75E00BCC23D; 251 | productRefGroup = 60EE6241169BD75E00BCC23D /* Products */; 252 | projectDirPath = ""; 253 | projectRoot = ""; 254 | targets = ( 255 | 60EE623F169BD75E00BCC23D /* GIKPopoverBackgroundView */, 256 | ); 257 | }; 258 | /* End PBXProject section */ 259 | 260 | /* Begin PBXResourcesBuildPhase section */ 261 | 60EE623E169BD75E00BCC23D /* Resources */ = { 262 | isa = PBXResourcesBuildPhase; 263 | buildActionMask = 2147483647; 264 | files = ( 265 | 60EE6257169BD75F00BCC23D /* Default.png in Resources */, 266 | 60EE6259169BD75F00BCC23D /* Default@2x.png in Resources */, 267 | 60EE625B169BD75F00BCC23D /* Default-568h@2x.png in Resources */, 268 | 60EE6276169BDC7700BCC23D /* InfoPlist.strings in Resources */, 269 | 60EE6294169BDE2400BCC23D /* PopoverBackgroundArrowDown.png in Resources */, 270 | 60EE6295169BDE2400BCC23D /* PopoverBackgroundArrowDown@2x.png in Resources */, 271 | 60EE6296169BDE2400BCC23D /* PopoverBackgroundArrowDownRight.png in Resources */, 272 | 60EE6297169BDE2400BCC23D /* PopoverBackgroundArrowDownRight@2x.png in Resources */, 273 | 60EE6298169BDE2400BCC23D /* PopoverBackgroundArrowSide.png in Resources */, 274 | 60EE6299169BDE2400BCC23D /* PopoverBackgroundArrowSide@2x.png in Resources */, 275 | 60EE629A169BDE2400BCC23D /* PopoverBackgroundArrowSideBottom.png in Resources */, 276 | 60EE629B169BDE2400BCC23D /* PopoverBackgroundArrowSideBottom@2x.png in Resources */, 277 | 60EE629C169BDE2400BCC23D /* PopoverBackgroundArrowSideTop.png in Resources */, 278 | 60EE629D169BDE2400BCC23D /* PopoverBackgroundArrowSideTop@2x.png in Resources */, 279 | 60EE629E169BDE2400BCC23D /* PopoverBackgroundArrowUp.png in Resources */, 280 | 60EE629F169BDE2400BCC23D /* PopoverBackgroundArrowUp@2x.png in Resources */, 281 | 60EE62A0169BDE2400BCC23D /* PopoverBackgroundArrowUpRight.png in Resources */, 282 | 60EE62A1169BDE2400BCC23D /* PopoverBackgroundArrowUpRight@2x.png in Resources */, 283 | F86BD86316ED83A400E78040 /* GIKPopoverBackgroundView.podspec in Resources */, 284 | 83C7116E16F8C3AE00C97BDD /* MainStoryboard.storyboard in Resources */, 285 | ); 286 | runOnlyForDeploymentPostprocessing = 0; 287 | }; 288 | /* End PBXResourcesBuildPhase section */ 289 | 290 | /* Begin PBXSourcesBuildPhase section */ 291 | 60EE623C169BD75E00BCC23D /* Sources */ = { 292 | isa = PBXSourcesBuildPhase; 293 | buildActionMask = 2147483647; 294 | files = ( 295 | 60EE6251169BD75F00BCC23D /* main.m in Sources */, 296 | 60EE6255169BD75F00BCC23D /* GIKAppDelegate.m in Sources */, 297 | 60EE627A169BDCE100BCC23D /* GIKPopoverBackgroundView.m in Sources */, 298 | 83C7117316F8C3CD00C97BDD /* GIKImageFilesViewController.m in Sources */, 299 | 83C7117416F8C3CD00C97BDD /* GIKRenderedImagesViewController.m in Sources */, 300 | 83C7117A16F8C3E600C97BDD /* GIKImageFilesPopoverBackgroundView.m in Sources */, 301 | 83C7117B16F8C3E600C97BDD /* GIKRenderedImagesPopoverBackgroundView.m in Sources */, 302 | ); 303 | runOnlyForDeploymentPostprocessing = 0; 304 | }; 305 | /* End PBXSourcesBuildPhase section */ 306 | 307 | /* Begin PBXVariantGroup section */ 308 | 60EE6274169BDC7700BCC23D /* InfoPlist.strings */ = { 309 | isa = PBXVariantGroup; 310 | children = ( 311 | 60EE6275169BDC7700BCC23D /* en */, 312 | ); 313 | name = InfoPlist.strings; 314 | sourceTree = ""; 315 | }; 316 | /* End PBXVariantGroup section */ 317 | 318 | /* Begin XCBuildConfiguration section */ 319 | 60EE6262169BD75F00BCC23D /* Debug */ = { 320 | isa = XCBuildConfiguration; 321 | buildSettings = { 322 | ALWAYS_SEARCH_USER_PATHS = NO; 323 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 324 | CLANG_CXX_LIBRARY = "libc++"; 325 | CLANG_ENABLE_OBJC_ARC = YES; 326 | CLANG_WARN_EMPTY_BODY = YES; 327 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 328 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 329 | COPY_PHASE_STRIP = NO; 330 | ENABLE_TESTABILITY = YES; 331 | GCC_C_LANGUAGE_STANDARD = gnu99; 332 | GCC_DYNAMIC_NO_PIC = NO; 333 | GCC_OPTIMIZATION_LEVEL = 0; 334 | GCC_PREPROCESSOR_DEFINITIONS = ( 335 | "DEBUG=1", 336 | "$(inherited)", 337 | ); 338 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 339 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 340 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 341 | GCC_WARN_UNUSED_VARIABLE = YES; 342 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 343 | ONLY_ACTIVE_ARCH = YES; 344 | SDKROOT = iphoneos; 345 | TARGETED_DEVICE_FAMILY = 2; 346 | }; 347 | name = Debug; 348 | }; 349 | 60EE6263169BD75F00BCC23D /* Release */ = { 350 | isa = XCBuildConfiguration; 351 | buildSettings = { 352 | ALWAYS_SEARCH_USER_PATHS = NO; 353 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 354 | CLANG_CXX_LIBRARY = "libc++"; 355 | CLANG_ENABLE_OBJC_ARC = YES; 356 | CLANG_WARN_EMPTY_BODY = YES; 357 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 358 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 359 | COPY_PHASE_STRIP = YES; 360 | GCC_C_LANGUAGE_STANDARD = gnu99; 361 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 362 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 363 | GCC_WARN_UNUSED_VARIABLE = YES; 364 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 365 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 366 | SDKROOT = iphoneos; 367 | TARGETED_DEVICE_FAMILY = 2; 368 | VALIDATE_PRODUCT = YES; 369 | }; 370 | name = Release; 371 | }; 372 | 60EE6265169BD75F00BCC23D /* Debug */ = { 373 | isa = XCBuildConfiguration; 374 | buildSettings = { 375 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 376 | GCC_PREFIX_HEADER = "GIKPopoverBackgroundView-Example/GIKPopoverBackgroundView-Prefix.pch"; 377 | INFOPLIST_FILE = "GIKPopoverBackgroundView-Example/GIKPopoverBackgroundView-Info.plist"; 378 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 379 | PRODUCT_BUNDLE_IDENTIFIER = "com.GeeksInKilts.${PRODUCT_NAME:rfc1034identifier}"; 380 | PRODUCT_NAME = "$(TARGET_NAME)"; 381 | WRAPPER_EXTENSION = app; 382 | }; 383 | name = Debug; 384 | }; 385 | 60EE6266169BD75F00BCC23D /* Release */ = { 386 | isa = XCBuildConfiguration; 387 | buildSettings = { 388 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 389 | GCC_PREFIX_HEADER = "GIKPopoverBackgroundView-Example/GIKPopoverBackgroundView-Prefix.pch"; 390 | INFOPLIST_FILE = "GIKPopoverBackgroundView-Example/GIKPopoverBackgroundView-Info.plist"; 391 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 392 | PRODUCT_BUNDLE_IDENTIFIER = "com.GeeksInKilts.${PRODUCT_NAME:rfc1034identifier}"; 393 | PRODUCT_NAME = "$(TARGET_NAME)"; 394 | WRAPPER_EXTENSION = app; 395 | }; 396 | name = Release; 397 | }; 398 | /* End XCBuildConfiguration section */ 399 | 400 | /* Begin XCConfigurationList section */ 401 | 60EE623A169BD75E00BCC23D /* Build configuration list for PBXProject "GIKPopoverBackgroundView" */ = { 402 | isa = XCConfigurationList; 403 | buildConfigurations = ( 404 | 60EE6262169BD75F00BCC23D /* Debug */, 405 | 60EE6263169BD75F00BCC23D /* Release */, 406 | ); 407 | defaultConfigurationIsVisible = 0; 408 | defaultConfigurationName = Release; 409 | }; 410 | 60EE6264169BD75F00BCC23D /* Build configuration list for PBXNativeTarget "GIKPopoverBackgroundView" */ = { 411 | isa = XCConfigurationList; 412 | buildConfigurations = ( 413 | 60EE6265169BD75F00BCC23D /* Debug */, 414 | 60EE6266169BD75F00BCC23D /* Release */, 415 | ); 416 | defaultConfigurationIsVisible = 0; 417 | defaultConfigurationName = Release; 418 | }; 419 | /* End XCConfigurationList section */ 420 | }; 421 | rootObject = 60EE6237169BD75E00BCC23D /* Project object */; 422 | } 423 | -------------------------------------------------------------------------------- /GIKPopoverBackgroundView-Example/MainStoryboard.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 32 | 49 | 66 | 83 | 100 | 117 | 134 | 151 | 168 | 185 | 202 | 219 | 236 | 253 | 270 | 287 | 294 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 418 | 435 | 452 | 469 | 486 | 503 | 520 | 537 | 554 | 571 | 588 | 605 | 622 | 639 | 656 | 673 | 680 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | 771 | 772 | 773 | 774 | 775 | 776 | 777 | 778 | 779 | 780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 | 788 | 789 | 790 | --------------------------------------------------------------------------------