├── .gitignore ├── LICENSE ├── README.md ├── SWSnapshotStackView.h ├── SWSnapshotStackView.m ├── SWSnapshotStackViewDemo ├── SWSnapshotStackViewDemo.xcodeproj │ └── project.pbxproj └── SWSnapshotStackViewDemo │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Resources │ ├── 350D_IMG_3157_20071030w.jpg │ ├── IMG_2777_080216w6s.jpg │ └── IMG_5737_081229w7sq.jpg │ ├── RootViewController.h │ ├── RootViewController.m │ ├── SWSnapshotStackViewDemo-Info.plist │ ├── SWSnapshotStackViewDemo-Prefix.pch │ ├── en.lproj │ ├── InfoPlist.strings │ └── RootViewController.xib │ └── main.m ├── Screenshot.png └── ScreenshotDemo.png /.gitignore: -------------------------------------------------------------------------------- 1 | # osx noise 2 | .DS_Store 3 | profile 4 | 5 | # xcode noise 6 | build/* 7 | *.mode1 8 | *.mode1v3 9 | *.mode2v3 10 | *.perspective 11 | *.perspectivev3 12 | *.pbxuser 13 | *.xcworkspace 14 | xcuserdata 15 | 16 | # svn & cvs 17 | .svn 18 | CVS 19 | 20 | # Screen Shot generation application 21 | SWSnapshotStackViewDemoSS/* 22 | 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Open Source Initiative OSI - The MIT License 2 | http://www.opensource.org/licenses/MIT 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. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Snapshot Stack View 2 | 3 | Snapshot Stack View provides an easy means of decorating your `UIImage`'s of any aspect ratio with a rendered matte frame and associated drop shadow. It also may render your image to look as though it is the top photograph (or snapshot) within a stack (or pile) of shots. Best described with a screenshot: 4 | 5 | ![Screenshot](http://github.com/snwau/SWSnapshotStackView/raw/master/Screenshot.png) 6 | 7 | Features: 8 | 9 | * Multiple display modes; single or stacked. 10 | * Respects image aspect, scaling snapshots to fit within the views frame 11 | * Supports all image aspects (landscape, square, portrait) 12 | * Supports dynamic modification of views frame, the image to display as the top snapshot and display mode. 13 | 14 | Background 15 | ---------- 16 | 17 | Snapshot Stack View was developed for use in an iOS application I'm currently developing to decorate a UIImage for presentation to the user. The application must display images of unknown and varying aspect ratios. 18 | 19 | Normally the effects rendered within the Snapshot Stack View to decorate a UIImage for display could easily generated be within Photoshop as a layer to sit over/under the `UIImage`, however the aspect and dimensions of the image must be known and static, hence not possible. 20 | 21 | An alternative approach often used is to crop the images to a fixed aspect, however this can lead to cropping important information from the image or destroying the general composition of a photograph, which I also did not want to risk. 22 | 23 | I use Snapshot Stack View to display a thumbnail to the user within an article for touching which then launches into a full screen image viewer. I've tried to convey the availability of either a single image or multiple using the Snapshot Stack View display modes (single or stacked). 24 | 25 | Compatability 26 | ------------- 27 | 28 | Snapshot Stack View has been developed to run on iOS 3.1 or later (Deployment Target) and was developed using iOS SDK 5.0, Xcode 4.2.1 (Base SDK). 29 | 30 | Support for iOS 3 was required for the target application I initially developed Snapshot Stack View for and hence Snapshot Stack View does NOT make use of any of the newer iOS features such as blocks or more importantly Automatic Reference Counting (ARC). 31 | 32 | If using Snapshot Stack View within a newer ARC enabled project, disable ARC selectively for compilation of Snapshot Stack View source files: 33 | 34 | 1. Select the project within Xcode project navigator 35 | 2. Select the required target from the list of Targets 36 | 3. Select the Build Phases tab 37 | 4. Expand the list of Compile Sources and double-click on the `SWSnapshotStackView.m` file to modify the compiler flags for this file. 38 | 5. Add `-fno-objc-arc` to the compiler flags 39 | 40 | Usage 41 | ----- 42 | 43 | To use Snapshot Stack View within your project: 44 | 45 | 1. Add `SWSnapshotStackView.h` and `SWSnapshotStackView.m` to project your Xcode project. 46 | 2. Ensure `QuartzCore.framework` framework is added to the project if not already. 47 | 3. Import the Snapshot Stack View header file to the destination View Controller source using `#import "SWSnapshotStackView.h"`. 48 | 4. Create an instance of the Snapshot Stack View class either within a XIB using Interface Builder (IB) or programatically as you would any other view. 49 | 5. Set the desired image (an existing `UIImage`) to display using the `image` property within code. 50 | 6. Set the desired display mode using the `displayAsStack` property within code. 51 | 52 | Refer to the Demonstration application `SWSnapshotStackViewDemo/` for example of use. 53 | 54 | Demonstration 55 | ------------- 56 | 57 | A demonstration application is provided to illustrate (and test) the use of Snapshot Stack View, demonstrating support for; 58 | 59 | * Multiple images of differing aspect ratios (Image 1 - landscape, Image 2 - square, Image 3 - portrait). 60 | * Dynamic resizing of view's frame via slider. 61 | * Selection and rendering of display mode (single or stack) via switch. 62 | 63 | 64 | ![Screenshot](http://github.com/snwau/SWSnapshotStackView/raw/master/ScreenshotDemo.png) 65 | 66 | Known Issues 67 | ------------ 68 | 69 | At time of release: 70 | 71 | * Matte and shadow effects require scaling to suit smaller frame sizes, otherwise effects can look exaggerated. 72 | 73 | For an updated list of issues/bugs, refer to [Issues on GitHub](https://github.com/snwau/SWSnapshotStackView/issues?labels=Bug&sort=created&direction=desc&state=open&page=1). 74 | 75 | Future Work 76 | ----------- 77 | 78 | A list of future enhancements is being maintained within the [GitHub Issue Tracker](https://github.com/snwau/SWSnapshotStackView/issues?labels=Enhancement&sort=created&direction=desc&state=open&page=1), under the `Enhancement` label. 79 | 80 | If there is a particular enhancement you would like to "up-vote" to increase priority for completion, please leave a comment within the respective enhancement issue. 81 | 82 | Contributing 83 | ------------ 84 | 85 | If you find an problem you are welcome to raise a [new issue](https://github.com/snwau/SWSnapshotStackView/issues/new) otherwise fork the repository, make the required changes and submit a pull request for merge consideration. 86 | 87 | Also don't hesitate to email me with any suggestions or feedback. 88 | 89 | License (Source Code) 90 | --------------------- 91 | 92 | Copyright (c) 2012 Scott White. All rights reserved. 93 | 94 | MIT License 95 | 96 | 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: 97 | 98 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 99 | 100 | 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. 101 | 102 | Refer to the LICENSE file for a copy of the MIT License 103 | along with this program. Otherwise, see . 104 | 105 | License (Images) 106 | ---------------- 107 | 108 | The images (`350D_IMG_3157_20071030w.jpg`, `IMG_2777_080216w6s.jpg`, and `IMG_5737_081229w7sq.jpg`) used within the Snapshot Stack View demonstration application are exceptions to the aforementioned Source Code license and hence not covered by MIT. 109 | 110 | Copyright (c) 2012 Scott White. All rights reserved. 111 | 112 | No reproduction in any form or by any means, graphic, electronic or mechanical is authorised outside of the Snapshot Stack View demonstration application, without the express permission of Scott White. 113 | 114 | Contact 115 | ------- 116 | 117 | * Email: Refer to source code file header for email address. 118 | * Twitter: [@snwau](http://www.twitter.com/snwau) 119 | * GitHub: [snwau](http://github.com/snwau) 120 | -------------------------------------------------------------------------------- /SWSnapshotStackView.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | /*! 3 | ** \file SWSnapshotStackView.h 4 | ** \brief Snapshot Stack Image View class definition file 5 | ** \author Scott White (support@scottwhite.id.au, http://github.com/snwau) 6 | ** 7 | ** Snapshot Stack View provides an easy means of decorating your UIImage's 8 | ** of any aspect ratio with a rendered matte frame and associated drop 9 | ** shadow. It also may render your image to look as though it is the top 10 | ** photograph (or snapshot) within a stack of shots. 11 | ** 12 | ** Copyright (c) 2012 Scott White. All rights reserved. 13 | ** 14 | ** Permission is hereby granted, free of charge, to any person obtaining a 15 | ** copy of this software and associated documentation files (the "Software"), 16 | ** to deal in the Software without restriction, including without limitation 17 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 18 | ** and/or sell copies of the Software, and to permit persons to whom the 19 | ** Software is furnished to do so, subject to the following conditions: 20 | ** 21 | ** The above copyright notice and this permission notice shall be included 22 | ** in all copies or substantial portions of the Software. 23 | ** 24 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 25 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 27 | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 28 | ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 29 | ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 30 | ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 31 | ** 32 | ** MIT License, see . 33 | ** 34 | ** \see SNWSnapshotStackView.m 35 | */ 36 | // Documentation of the code is formatted for use with the documentation 37 | // package Doxygen (see http://www.doxygen.org/). 38 | // 39 | // Project : iOS Common Components 40 | // Component : GUI/Views 41 | // Platform : iOS SDK 3.1+ 42 | // 43 | //////////////////////////////////////////////////////////////////////////// 44 | 45 | #import 46 | 47 | 48 | // ********************************************************************** // 49 | // TYPE DEFINITIONS 50 | // ********************************************************************** // 51 | 52 | //! Snapshot Position data structure 53 | /*! 54 | Defines the centre position and angle of rotation about the centre of 55 | a snapshot. Multiple snapshots at slightly varying positions then form 56 | a stack. 57 | 58 | Structure stores pre-calculated positions (which in future may be 59 | randomised upon initialisation of the view if configured to do so), 60 | which also allows the pre-calculation of the bounding rectangles of 61 | the snapshots in their specified positions (rotated and off-centre). 62 | */ 63 | typedef struct 64 | { 65 | //! Centre point of rectangle (currently unused) 66 | //! Had thoughts of randomising and offsetting the centre points of 67 | //! underlying snapshots in the stack within a small radius of the views 68 | //! centre for make their placement look a little more adhoc and hence 69 | //! more natural. May update to make this functionality optional in the 70 | //! future. 71 | //CGPoint centre; 72 | 73 | //! Angle of rotation about the centre point, positive angle clockwise, 74 | //! negative angle counter-clockwise, specified in degrees. 75 | CGFloat angleRotation; 76 | 77 | //! Calculated size of bounding rectangle after rotation, as width and 78 | //! height protude outside the non-rotated base rectangle. The bounding 79 | //! rectangle size is used to determine the required scaling to fit the 80 | //! snapshot within the views frame. 81 | CGSize boundingRectSize; 82 | } 83 | SnapshotPosition_t; 84 | 85 | 86 | // ********************************************************************** // 87 | // SNAPSHOT STACK VIEW CLASS 88 | // ********************************************************************** // 89 | 90 | #pragma mark Snapshot Stack View class 91 | 92 | //! Snapshot Stack Image View 93 | @interface SWSnapshotStackView : UIView 94 | { 95 | // ******************************************************************** // 96 | // CONSTANTS 97 | 98 | #pragma mark Constants 99 | 100 | //! Number of snapshots to display within the stack of shots 101 | #define SWSnapshotStackViewSnapshotsPerStack 3 102 | 103 | 104 | // ******************************************************************** // 105 | // MEMBER VARIABLES 106 | 107 | BOOL m_displayStack; // property (displayAsStack) 108 | UIImage *m_image; // property (image) 109 | 110 | //! Aspect Ratio of current image (Width/Height) 111 | CGFloat m_imageAspect; 112 | 113 | //! Array of defining the position of each snapshot in the stack, 114 | //! defined from bottom of stack to the top, where the top image in 115 | //! the stack always has zero rotation. 116 | SnapshotPosition_t m_snapshotPositions[SWSnapshotStackViewSnapshotsPerStack]; 117 | //! Index to snapshot within the positions array, requiring most scaling //! (minimum scaling factor) to fit within views frame. 118 | NSInteger m_minScaleShotIdx; 119 | //! Minimum scaling factor was calculated using image width (YES) otherwise 120 | //! height (NO), stored to avoid recalculation and comparison when drawing. 121 | BOOL m_scaledUsingWidth; 122 | 123 | //! Shadow Direction Sign 124 | //! Support for inversion of shadow base translation, y-axis in iOS 3.2+ 125 | //! Stored to avoid having to recheck system OS version during redrawing etc. 126 | //! In <3.2, positive y, translates shadow DOWN 127 | //! In 3.2+, positive y, translates shadow UP 128 | //! NOTE: Not required if you do not wish to support iOS <3.2 129 | CGFloat m_shadowDirSign; 130 | } 131 | 132 | 133 | // ********************************************************************** // 134 | // PROPERTIES 135 | 136 | #pragma mark Properties 137 | 138 | //! Display as a stack of multiple snapshots 139 | /*! 140 | Display a stack of snapshots (YES) with the image provided within the 141 | image property as the top most snapshot, othwerwise display image as 142 | a single snapshot (NO). 143 | */ 144 | @property (nonatomic, assign) BOOL displayAsStack; 145 | 146 | //! Image to display within the snapshot stack view 147 | @property (nonatomic, retain) UIImage *image; 148 | 149 | 150 | // ********************************************************************** // 151 | 152 | @end // @SWSnapshotStackView 153 | 154 | // ********************************************************************** // 155 | 156 | // End of File 157 | -------------------------------------------------------------------------------- /SWSnapshotStackView.m: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | /*! 3 | ** \file SWSnapshotStackView.m 4 | ** \brief Snapshot Stack Image View class implementation file 5 | ** \author Scott White (support@scottwhite.id.au, http://github.com/snwau) 6 | ** 7 | ** Snapshot Stack View provides an easy means of decorating your UIImage's 8 | ** of any aspect ratio with a rendered matte frame and associated drop 9 | ** shadow. It also may render your image to look as though it is the top 10 | ** photograph (or snapshot) within a stack of shots. 11 | ** 12 | ** Copyright (c) 2012 Scott White. All rights reserved. 13 | ** 14 | ** Permission is hereby granted, free of charge, to any person obtaining a 15 | ** copy of this software and associated documentation files (the "Software"), 16 | ** to deal in the Software without restriction, including without limitation 17 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 18 | ** and/or sell copies of the Software, and to permit persons to whom the 19 | ** Software is furnished to do so, subject to the following conditions: 20 | ** 21 | ** The above copyright notice and this permission notice shall be included 22 | ** in all copies or substantial portions of the Software. 23 | ** 24 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 25 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 27 | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 28 | ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 29 | ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 30 | ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 31 | ** 32 | ** MIT License, see . 33 | ** 34 | ** \see SWSnapshotStackView.h 35 | */ 36 | // Documentation of the code is formatted for use with the documentation 37 | // package Doxygen (see http://www.doxygen.org/). 38 | // 39 | // Project : iOS Common Components 40 | // Component : GUI/Views 41 | // Platform : iOS SDK 3.1+ 42 | // 43 | //////////////////////////////////////////////////////////////////////////// 44 | 45 | #import "SWSnapshotStackView.h" 46 | 47 | 48 | // ********************************************************************** // 49 | // SNAPSHOT STACK VIEW CLASS (PRIVATE METHODS) 50 | // ********************************************************************** // 51 | 52 | #pragma mark Snapshot Stack View class (Private Interface) 53 | 54 | @interface SWSnapshotStackView (Private) 55 | 56 | //! Perform common initialisation activities 57 | - (void)commonInitialisation; 58 | //! Calculate the scaling required to fit the rotated snapshots in views frame 59 | - (void)calculateScalingToFitStack; 60 | 61 | @end 62 | 63 | 64 | // ********************************************************************** // 65 | // SNAPSHOT STACK VIEW CLASS 66 | // ********************************************************************** // 67 | 68 | #pragma mark - Snapshot Stack View class 69 | 70 | @implementation SWSnapshotStackView 71 | 72 | // ********************************************************************** // 73 | // CONSTANTS 74 | 75 | #pragma mark Constants 76 | 77 | //! Defines the width of the matte border around a snapshot (each side) 78 | #define SWSnapshotStackViewMatteWidth 7.0 79 | 80 | // SINGLE DISPLAY MODE CONSTANTS 81 | //! Defines X offset for either edge to indent shadow effect (single mode) 82 | #define SWSnapshotStackViewSingleShadowXOffset 5.0 83 | //! Defines Y offset to drop shadow below snapshot matte frame 84 | #define SWSnapshotStackViewSingleShadowYOffset 5.0 85 | //! Defines radius of the shadow (results in magnitude and softness of shadow) 86 | #define SWSnapshotStackViewSingleShadowRadius 5.0 87 | #define SWSnapshotStackViewSingleShadowTotalHeight (SWSnapshotStackViewSingleShadowYOffset + SWSnapshotStackViewSingleShadowRadius) 88 | 89 | // STACK DISPLAY MODE CONSTANTS 90 | //! Defines Y offset to drop shadow below snapshot matte frame 91 | #define SWSnapshotStackViewStackShadowYOffset 2.0 92 | //! Defines radius of the shadow (results in magnitude and softness of shadow) 93 | #define SWSnapshotStackViewStackShadowRadius 6.0 94 | #define SWSnapshotStackViewStackShadowTotalHeight ((2 * SWSnapshotStackViewStackShadowRadius) - SWSnapshotStackViewStackShadowYOffset) 95 | 96 | 97 | // ********************************************************************** // 98 | // PROPERTIES 99 | 100 | #pragma mark Properties 101 | 102 | @dynamic image; 103 | @dynamic displayAsStack; 104 | 105 | 106 | // ********************************************************************** // 107 | // DYNAMIC PROPERTY METHODS 108 | 109 | #pragma mark Dynamic Property Methods 110 | 111 | - (UIImage *)image 112 | { 113 | return (m_image); 114 | } 115 | 116 | - (void)setImage:(UIImage *)image 117 | { 118 | // Release previous image, assign and retain new image 119 | [m_image release]; 120 | m_image = [image retain]; 121 | 122 | // If an image is provided, perform some pre-calculations to assist 123 | // drawing that remain constant for a given image 124 | if (nil != m_image) 125 | { 126 | // Calculate the image aspect ratio, used to determine aspect of 127 | // image (landscape, square, portrait) which determines the larger 128 | // dimension required for calculating required scaling 129 | m_imageAspect = m_image.size.width / m_image.size.height; 130 | 131 | // When display mode is Stack, rotation of snapshot/image rectangles 132 | // changes dimensions of bounding rectangle, perform calculations to 133 | // discover largest bounding rectangle requiring most scaling 134 | if (YES == m_displayStack) 135 | { 136 | [self calculateScalingToFitStack]; 137 | } 138 | } 139 | 140 | // Image has change, redraw the view 141 | [self setNeedsDisplay]; 142 | } 143 | 144 | 145 | // ********************************************************************** // 146 | 147 | - (BOOL)displayAsStack 148 | { 149 | return (m_displayStack); 150 | } 151 | 152 | - (void)setDisplayAsStack:(BOOL)displayAsStack 153 | { 154 | // Take action only if the requested display mode is differs from current 155 | if (displayAsStack != m_displayStack) 156 | { 157 | m_displayStack = displayAsStack; 158 | 159 | // Rotation of snapshot/image rectangles changes dimensions of bounding 160 | // rectangle, perform calculations to discover largest bounding rectangle 161 | // requiring most scaling 162 | if ((YES == m_displayStack) && (nil != m_image)) 163 | { 164 | [self calculateScalingToFitStack]; 165 | } 166 | 167 | // Display mode has changed, redraw the view 168 | [self setNeedsDisplay]; 169 | } 170 | } 171 | 172 | 173 | // ********************************************************************** // 174 | // INSTANCE METHODS 175 | 176 | #pragma mark Instance Methods 177 | 178 | - (id)initWithFrame:(CGRect)frame 179 | { 180 | if (nil != (self = [super initWithFrame:frame])) 181 | { 182 | [self commonInitialisation]; 183 | } 184 | 185 | return (self); 186 | } 187 | 188 | 189 | // ********************************************************************** // 190 | 191 | - (void)awakeFromNib 192 | { 193 | [super awakeFromNib]; 194 | [self commonInitialisation]; 195 | } 196 | 197 | 198 | // ********************************************************************** // 199 | 200 | // METHOD: commonInitialisation 201 | /*! 202 | Perform initialisation activities common to all forms of instantiation; 203 | programatically via initWithFrame: or from XIB instantiation via 204 | awakeFromNib: method. 205 | */ 206 | - (void)commonInitialisation 207 | { 208 | // Initialise the positions of all snapshots in a stack 209 | // Offsetting centre of snapshots about the view frame centre is 210 | // reserved for future functionality and currently the rotations are 211 | // static, may be optionally randomised in future updates. 212 | /* 213 | for (NSInteger idx = 0; idx < SWSnapshotStackViewSnapshotsPerStack; idx++) 214 | { 215 | m_snapshotPositions[idx].centre = CGPointMake (x,y); 216 | } 217 | */ 218 | m_snapshotPositions[0].angleRotation = 2.5; // 2.0 // 3.0 219 | m_snapshotPositions[1].angleRotation = -3.0; // 4.0 // -5.0 220 | // Top most shot must always have zero rotation 221 | m_snapshotPositions[2].angleRotation = 0.0; 222 | 223 | // View's background is transparent underneath the rendered snapshot(s) 224 | self.backgroundColor = [UIColor clearColor]; 225 | 226 | // Check system (iOS) version, invert sign of shadow direction when 227 | // running on iOS <3.2 228 | m_shadowDirSign = 1.0; 229 | if (NSOrderedAscending == [[[UIDevice currentDevice] systemVersion] compare:@"3.2" options:NSNumericSearch]) 230 | { 231 | m_shadowDirSign = -1.0; 232 | } 233 | } 234 | 235 | 236 | // ********************************************************************** // 237 | 238 | - (void)dealloc 239 | { 240 | [m_image release], m_image = nil; 241 | 242 | [super dealloc]; 243 | } 244 | 245 | 246 | // ********************************************************************** // 247 | 248 | - (void)drawRect:(CGRect)rect 249 | { 250 | // Do nothing if no image is available to display 251 | if (nil == m_image) 252 | { 253 | return; 254 | } 255 | 256 | CGContextRef context = UIGraphicsGetCurrentContext (); 257 | 258 | CGPoint viewCenter = 259 | CGPointMake (CGRectGetMidX (self.bounds), CGRectGetMidY (self.bounds)); 260 | 261 | // Initialise to shut static analyser up, gets confused by stacked display 262 | // mode processing 'for' loop and conditional 'if (0 == angle of rotation)' 263 | // where this is initialised for stacked display mode (last snapshot ALWAYS 264 | // zero rotation) 265 | CGRect matteFrameRect = rect; 266 | 267 | // Set fill & stroke colour and stroke line width for rendering of the 268 | // matte frame around snapshots 269 | UIColor *colour = [UIColor whiteColor]; 270 | [colour setFill]; 271 | colour = [UIColor grayColor]; 272 | [colour setStroke]; 273 | CGContextSetLineWidth (context, 1.0); 274 | 275 | CGFloat MatteWidthTotal = 2.0 * SWSnapshotStackViewMatteWidth; 276 | 277 | if (NO == m_displayStack) 278 | { 279 | // SINGLE SNAPSHOT DISPLAY MODE 280 | 281 | CGSize scaledImageSize; 282 | 283 | // Calculate required scaling of image to fit within the views frame, 284 | // leaving room for matte frame and shadow. As the views frame may 285 | // have differing aspect ratio to image, scaling factors must be 286 | // calculated for each dimension and the dimension requiring the 287 | // most scaling is used to determine the resulting scaled image size 288 | CGFloat targetWidth = self.frame.size.width - MatteWidthTotal; 289 | CGFloat requiredWidthScaling = targetWidth / self.image.size.width; 290 | CGFloat targetHeight = self.frame.size.height - MatteWidthTotal - SWSnapshotStackViewSingleShadowTotalHeight; 291 | CGFloat requiredHeightScaling = targetHeight / self.image.size.height; 292 | 293 | if (requiredWidthScaling <= requiredHeightScaling) 294 | { 295 | scaledImageSize = CGSizeMake (targetWidth, targetWidth / m_imageAspect); 296 | 297 | } 298 | else 299 | { 300 | scaledImageSize = CGSizeMake (targetHeight * m_imageAspect, targetHeight); 301 | } 302 | 303 | // Create the matte frame rectangle 304 | matteFrameRect = CGRectMake (floorf (viewCenter.x - ((scaledImageSize.width / 2.0) + SWSnapshotStackViewMatteWidth)) + 0.5, 305 | floorf (viewCenter.y - ((scaledImageSize.height / 2.0) + SWSnapshotStackViewMatteWidth + (SWSnapshotStackViewSingleShadowTotalHeight / 2.0))) + 0.5, 306 | floorf (scaledImageSize.width + MatteWidthTotal) - 1.0, 307 | floorf (scaledImageSize.height + MatteWidthTotal) - 1.0); 308 | 309 | CGContextSaveGState (context); 310 | 311 | // Render the curved drop shadow, path is defined from top left hand 312 | // corner in a clockwise direction 313 | CGMutablePathRef shadowPath = CGPathCreateMutable (); 314 | CGPathMoveToPoint (shadowPath, NULL, 315 | matteFrameRect.origin.x + SWSnapshotStackViewSingleShadowXOffset, 316 | matteFrameRect.origin.y + matteFrameRect.size.height - SWSnapshotStackViewSingleShadowTotalHeight); 317 | CGPathAddLineToPoint (shadowPath, NULL, 318 | matteFrameRect.origin.x + matteFrameRect.size.width - SWSnapshotStackViewSingleShadowXOffset, 319 | matteFrameRect.origin.y + matteFrameRect.size.height - SWSnapshotStackViewSingleShadowTotalHeight); 320 | CGPathAddLineToPoint (shadowPath, NULL, 321 | matteFrameRect.origin.x + matteFrameRect.size.width - SWSnapshotStackViewSingleShadowXOffset, 322 | matteFrameRect.origin.y + matteFrameRect.size.height); 323 | CGPathAddQuadCurveToPoint (shadowPath, NULL, 324 | (matteFrameRect.origin.x + matteFrameRect.size.width) / 2.0, 325 | matteFrameRect.origin.y + matteFrameRect.size.height - SWSnapshotStackViewSingleShadowTotalHeight, 326 | matteFrameRect.origin.x + SWSnapshotStackViewSingleShadowXOffset, 327 | matteFrameRect.origin.y + matteFrameRect.size.height); 328 | CGPathCloseSubpath (shadowPath); 329 | 330 | // Draw the shadow using it's calculated path 331 | colour = [UIColor colorWithRed:0 green:0 blue:0.0 alpha:0.6]; 332 | CGContextSetShadowWithColor (context, CGSizeMake (0, (SWSnapshotStackViewSingleShadowYOffset * m_shadowDirSign)), 333 | SWSnapshotStackViewSingleShadowRadius, colour.CGColor); 334 | CGContextAddPath (context, shadowPath); 335 | CGContextFillPath (context); 336 | CGPathRelease (shadowPath); 337 | 338 | CGContextRestoreGState (context); 339 | 340 | // Draw the matte frame 341 | CGPathRef matteFramePath = CGPathCreateWithRect (matteFrameRect, NULL); 342 | CGContextAddPath (context, matteFramePath); 343 | CGContextDrawPath (context, kCGPathFillStroke); 344 | CGPathRelease (matteFramePath); 345 | } 346 | else 347 | { 348 | // STACK DISPLAY MODE 349 | 350 | // Using the snapshot within the stack of rotated snapshots which 351 | // has the largest bounding rectangle (calculated via 352 | // calculateScalingToFitStack:) determine the required scaling to 353 | // fit the snapshot within the views frame, leaving room for shadows 354 | CGFloat requiredScaling; 355 | if (YES == m_scaledUsingWidth) 356 | { 357 | requiredScaling = (self.frame.size.width - 1 - SWSnapshotStackViewStackShadowTotalHeight) / 358 | m_snapshotPositions[m_minScaleShotIdx].boundingRectSize.width; 359 | } 360 | else 361 | { 362 | requiredScaling = (self.frame.size.height - 1 - SWSnapshotStackViewStackShadowTotalHeight) / 363 | m_snapshotPositions[m_minScaleShotIdx].boundingRectSize.height; 364 | } 365 | 366 | CGSize matteSize = CGSizeMake (m_image.size.width * requiredScaling, 367 | m_image.size.height * requiredScaling); 368 | 369 | // Draw each snapshot in the stack 370 | for (NSInteger shotIdx = 0; shotIdx < SWSnapshotStackViewSnapshotsPerStack; shotIdx++) 371 | { 372 | CGContextSaveGState (context); 373 | 374 | CGMutablePathRef matteFramePath = CGPathCreateMutable (); 375 | 376 | CGFloat angleRotation = (m_snapshotPositions[shotIdx].angleRotation) * (M_PI / 180.0); 377 | 378 | // snapshots containing no rotation don't require the complex 379 | // drawing of rotated rectangles 380 | if (0.0 == angleRotation) 381 | { 382 | matteFrameRect = 383 | CGRectMake (floorf (viewCenter.x - (matteSize.width / 2.0)) + 0.5, 384 | floorf (viewCenter.y - (matteSize.height / 2.0)) + 0.5, 385 | floorf (matteSize.width), floorf (matteSize.height)); 386 | CGPathAddRect (matteFramePath, NULL, matteFrameRect); 387 | } 388 | else 389 | { 390 | // Points define rectangle from top-left corner in clockwise direction 391 | CGPoint P1; 392 | CGPoint P2; 393 | CGPoint P3; 394 | CGPoint P4; 395 | 396 | // Scale the bounding rectangle that contains the rotated snapshot 397 | // rectangle by the calculated required scaling factor 398 | CGSize scaledBoudingRectSize = CGSizeMake ((m_snapshotPositions[shotIdx].boundingRectSize.width * requiredScaling), 399 | (m_snapshotPositions[shotIdx].boundingRectSize.height * requiredScaling)); 400 | 401 | CGFloat halfScaledBoundingRectWidth = (scaledBoudingRectSize.width / 2.0); 402 | CGFloat halfScaledBoundingRectHeight = (scaledBoudingRectSize.height / 2.0); 403 | CGFloat adjacentOnXAxis = scaledBoudingRectSize.height * sin (angleRotation); 404 | CGFloat adjacentOnYAxis = scaledBoudingRectSize.width * sin (angleRotation); 405 | 406 | // Calculate position of rotated rectangle points P1 to P4, 407 | // using trigonometry and the triangles made by the points against 408 | // the sides of the bounding rectangle 409 | if (angleRotation < 0.0) 410 | { 411 | // Counter-clockwise rotation 412 | 413 | P1 = CGPointMake (viewCenter.x - halfScaledBoundingRectWidth, 414 | viewCenter.y - halfScaledBoundingRectHeight - adjacentOnYAxis); 415 | P2 = CGPointMake (viewCenter.x + halfScaledBoundingRectWidth + adjacentOnXAxis, 416 | viewCenter.y - halfScaledBoundingRectHeight); 417 | P3 = CGPointMake (viewCenter.x + halfScaledBoundingRectWidth, 418 | viewCenter.y + halfScaledBoundingRectHeight + adjacentOnYAxis); 419 | P4 = CGPointMake (viewCenter.x - halfScaledBoundingRectWidth - adjacentOnXAxis, 420 | viewCenter.y + halfScaledBoundingRectHeight); 421 | } 422 | else 423 | { 424 | // Clockwise rotation 425 | 426 | P1 = CGPointMake (viewCenter.x - halfScaledBoundingRectWidth + adjacentOnXAxis, 427 | viewCenter.y - halfScaledBoundingRectHeight); 428 | P2 = CGPointMake (viewCenter.x + halfScaledBoundingRectWidth, 429 | viewCenter.y - halfScaledBoundingRectHeight + adjacentOnYAxis); 430 | P3 = CGPointMake (viewCenter.x + halfScaledBoundingRectWidth - adjacentOnXAxis, 431 | viewCenter.y + halfScaledBoundingRectHeight); 432 | P4 = CGPointMake (viewCenter.x - halfScaledBoundingRectWidth, 433 | viewCenter.y + halfScaledBoundingRectHeight - adjacentOnYAxis); 434 | } 435 | 436 | // Create path to define the matte frame of the rotated snapshot 437 | CGPathMoveToPoint (matteFramePath, NULL, P1.x, P1.y); 438 | CGPathAddLineToPoint (matteFramePath, NULL, P2.x, P2.y); 439 | CGPathAddLineToPoint (matteFramePath, NULL, P3.x, P3.y); 440 | CGPathAddLineToPoint (matteFramePath, NULL, P4.x, P4.y); 441 | CGPathCloseSubpath (matteFramePath); 442 | } 443 | 444 | CGContextSaveGState (context); 445 | 446 | // Draw the snapshot shadow using the matte frames path, offset 447 | // slightly. Still not 100% happy with the shadow drawing, plan 448 | // to tweak eventually to get better end effect 449 | colour = [UIColor colorWithRed:0 green:0 blue:0.0 alpha:0.4]; 450 | CGContextSetShadowWithColor (context, CGSizeMake (0.0, (SWSnapshotStackViewStackShadowYOffset * m_shadowDirSign)), 451 | SWSnapshotStackViewStackShadowRadius, colour.CGColor); 452 | CGContextAddPath (context, matteFramePath); 453 | CGContextFillPath (context); 454 | 455 | CGContextRestoreGState (context); 456 | 457 | // Draw the matte frame 458 | CGContextAddPath (context, matteFramePath); 459 | CGContextDrawPath (context, kCGPathFillStroke); 460 | CGPathRelease (matteFramePath); 461 | 462 | CGContextRestoreGState (context); 463 | } 464 | 465 | } 466 | 467 | // Calculate frame for the actual image within the top snapshot, centered 468 | // within the already drawn matte frame. Unlike the stroked matte 469 | // frame outline the image must reside on integer point values, 470 | // to avoid aliasing across points/pixels. 471 | // Hence conversion of the matte frame rectangle (calculated to perform 472 | // innser stroke at 0.5 offset) requires subtraction of the offsets and 473 | // increasing size in both dimension by 1 point to compensate. 474 | CGRect imageFrame = matteFrameRect; 475 | imageFrame.origin.x += SWSnapshotStackViewMatteWidth - 0.5; 476 | imageFrame.origin.y += SWSnapshotStackViewMatteWidth - 0.5; 477 | imageFrame.size.width -= MatteWidthTotal - 1; 478 | imageFrame.size.height -= MatteWidthTotal - 1; 479 | 480 | // Draw the image without manipulation other than correct scaling, 481 | // could have used CGContextDrawImage() if further drawing required 482 | [m_image drawInRect:imageFrame]; 483 | } 484 | 485 | 486 | // ********************************************************************** // 487 | 488 | // METHOD: calculateScalingToFitStack 489 | /*! 490 | Calculates the snapshot within the stack which requires the most 491 | scaling, due to the rotation of the rectangle the points protrude 492 | outside of their original dimensions. Hence a bounding rectangle 493 | must be calculated that contains entirely the rotated rectangle. 494 | The dimensions of the bounding rectangle can then be used to calculate 495 | the required scaling to fit the bounding rectangle within the views 496 | frame. 497 | 498 | As the size of the views frame may change at anytime, the outcome 499 | of this method is to store the snapshot in the stack which requires 500 | the most scaling (minimum scaling factor) via it's index 501 | (m_minScaleShotIdx) into the snapshot position array 502 | (m_snapshotPositions) and the dimension (width or height) that 503 | should be used to calculate scaling (m_scaledUsingWidth). 504 | 505 | The output of this method remains constant as long as the image 506 | remains constant, re-calculation is required when the image 507 | is changed. Hence avoiding the need to perform these calculations 508 | each time the view is drawn. 509 | */ 510 | - (void)calculateScalingToFitStack 511 | { 512 | CGFloat requiredScaling = 1.0; 513 | 514 | for (NSInteger idx = 0; idx < SWSnapshotStackViewSnapshotsPerStack; idx++) 515 | { 516 | // Calculate bounding rectangle of rotated snapshot/image rectangle 517 | // Direction of rotation is not important given symmetry, only aiming 518 | // to calculate size, not location after rotation 519 | CGSize imageSize = m_image.size; 520 | CGFloat angleRotation = 521 | (fabs(m_snapshotPositions[idx].angleRotation) * (M_PI / 180.0)); 522 | CGSize boundingRect = CGSizeMake ((imageSize.width * cos (angleRotation)) + 523 | (imageSize.height * sin (angleRotation)), 524 | (imageSize.width * sin (angleRotation)) + 525 | (imageSize.height * cos (angleRotation))); 526 | m_snapshotPositions[idx].boundingRectSize = boundingRect; 527 | 528 | // Calculated required scaling for each dimension to fit the bounding 529 | // rectangle within the views frame 530 | CGFloat requiredWidthScaling = self.frame.size.width / boundingRect.width; 531 | CGFloat requiredHeightScaling = self.frame.size.height / boundingRect.height; 532 | 533 | // Determine if the scaling required for either dimension is the 534 | // largest (smallest scaling factor) required for any of the snapshots 535 | // processed thus far 536 | if (requiredWidthScaling < requiredScaling) 537 | { 538 | requiredScaling = requiredWidthScaling; 539 | m_minScaleShotIdx = idx; 540 | m_scaledUsingWidth = YES; 541 | } 542 | if (requiredHeightScaling < requiredScaling) 543 | { 544 | requiredScaling = requiredHeightScaling; 545 | m_minScaleShotIdx = idx; 546 | m_scaledUsingWidth = NO; 547 | } 548 | } 549 | } 550 | 551 | 552 | // ********************************************************************** // 553 | 554 | @end // @SWSnapshotStackView 555 | 556 | // ********************************************************************** // 557 | 558 | // End of File 559 | -------------------------------------------------------------------------------- /SWSnapshotStackViewDemo/SWSnapshotStackViewDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | FE3D212B14980D6D002B99A4 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FE3D212A14980D6D002B99A4 /* UIKit.framework */; }; 11 | FE3D212D14980D6D002B99A4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FE3D212C14980D6D002B99A4 /* Foundation.framework */; }; 12 | FE3D212F14980D6D002B99A4 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FE3D212E14980D6D002B99A4 /* CoreGraphics.framework */; }; 13 | FE3D213514980D6D002B99A4 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = FE3D213314980D6D002B99A4 /* InfoPlist.strings */; }; 14 | FE3D213714980D6D002B99A4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = FE3D213614980D6D002B99A4 /* main.m */; }; 15 | FE3D213B14980D6D002B99A4 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = FE3D213A14980D6D002B99A4 /* AppDelegate.m */; }; 16 | FE3D213E14980D6D002B99A4 /* RootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FE3D213D14980D6D002B99A4 /* RootViewController.m */; }; 17 | FE3D214114980D6D002B99A4 /* RootViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = FE3D213F14980D6D002B99A4 /* RootViewController.xib */; }; 18 | FE3D214A149836A9002B99A4 /* SWSnapshotStackView.m in Sources */ = {isa = PBXBuildFile; fileRef = FE3D2149149836A9002B99A4 /* SWSnapshotStackView.m */; }; 19 | FE3D21591499898C002B99A4 /* 350D_IMG_3157_20071030w.jpg in Resources */ = {isa = PBXBuildFile; fileRef = FE3D21581499898B002B99A4 /* 350D_IMG_3157_20071030w.jpg */; }; 20 | FE3D215B1499957D002B99A4 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FE3D215A1499957C002B99A4 /* QuartzCore.framework */; }; 21 | FE3D215D149A1089002B99A4 /* IMG_5737_081229w7sq.jpg in Resources */ = {isa = PBXBuildFile; fileRef = FE3D215C149A1089002B99A4 /* IMG_5737_081229w7sq.jpg */; }; 22 | FE3D215F149AD601002B99A4 /* IMG_2777_080216w6s.jpg in Resources */ = {isa = PBXBuildFile; fileRef = FE3D215E149AD601002B99A4 /* IMG_2777_080216w6s.jpg */; }; 23 | /* End PBXBuildFile section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | FE3D212614980D6D002B99A4 /* SWSnapshotStackViewDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SWSnapshotStackViewDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | FE3D212A14980D6D002B99A4 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 28 | FE3D212C14980D6D002B99A4 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 29 | FE3D212E14980D6D002B99A4 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 30 | FE3D213214980D6D002B99A4 /* SWSnapshotStackViewDemo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SWSnapshotStackViewDemo-Info.plist"; sourceTree = ""; }; 31 | FE3D213414980D6D002B99A4 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 32 | FE3D213614980D6D002B99A4 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 33 | FE3D213814980D6D002B99A4 /* SWSnapshotStackViewDemo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SWSnapshotStackViewDemo-Prefix.pch"; sourceTree = ""; }; 34 | FE3D213914980D6D002B99A4 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 35 | FE3D213A14980D6D002B99A4 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 36 | FE3D213C14980D6D002B99A4 /* RootViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RootViewController.h; sourceTree = ""; }; 37 | FE3D213D14980D6D002B99A4 /* RootViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RootViewController.m; sourceTree = ""; }; 38 | FE3D214014980D6D002B99A4 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/RootViewController.xib; sourceTree = ""; }; 39 | FE3D2148149836A9002B99A4 /* SWSnapshotStackView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SWSnapshotStackView.h; path = ../SWSnapshotStackView.h; sourceTree = ""; }; 40 | FE3D2149149836A9002B99A4 /* SWSnapshotStackView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SWSnapshotStackView.m; path = ../SWSnapshotStackView.m; sourceTree = ""; }; 41 | FE3D21581499898B002B99A4 /* 350D_IMG_3157_20071030w.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = 350D_IMG_3157_20071030w.jpg; path = SWSnapshotStackViewDemo/Resources/350D_IMG_3157_20071030w.jpg; sourceTree = ""; }; 42 | FE3D215A1499957C002B99A4 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 43 | FE3D215C149A1089002B99A4 /* IMG_5737_081229w7sq.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = IMG_5737_081229w7sq.jpg; path = SWSnapshotStackViewDemo/Resources/IMG_5737_081229w7sq.jpg; sourceTree = ""; }; 44 | FE3D215E149AD601002B99A4 /* IMG_2777_080216w6s.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = IMG_2777_080216w6s.jpg; path = SWSnapshotStackViewDemo/Resources/IMG_2777_080216w6s.jpg; sourceTree = ""; }; 45 | /* End PBXFileReference section */ 46 | 47 | /* Begin PBXFrameworksBuildPhase section */ 48 | FE3D212314980D6D002B99A4 /* Frameworks */ = { 49 | isa = PBXFrameworksBuildPhase; 50 | buildActionMask = 2147483647; 51 | files = ( 52 | FE3D212B14980D6D002B99A4 /* UIKit.framework in Frameworks */, 53 | FE3D212D14980D6D002B99A4 /* Foundation.framework in Frameworks */, 54 | FE3D212F14980D6D002B99A4 /* CoreGraphics.framework in Frameworks */, 55 | FE3D215B1499957D002B99A4 /* QuartzCore.framework in Frameworks */, 56 | ); 57 | runOnlyForDeploymentPostprocessing = 0; 58 | }; 59 | /* End PBXFrameworksBuildPhase section */ 60 | 61 | /* Begin PBXGroup section */ 62 | FE3D211B14980D6C002B99A4 = { 63 | isa = PBXGroup; 64 | children = ( 65 | FE3D21471498368C002B99A4 /* SWSnapshotStackView */, 66 | FE3D213014980D6D002B99A4 /* SWSnapshotStackViewDemo */, 67 | FE3D212914980D6D002B99A4 /* Frameworks */, 68 | FE3D212714980D6D002B99A4 /* Products */, 69 | ); 70 | sourceTree = ""; 71 | }; 72 | FE3D212714980D6D002B99A4 /* Products */ = { 73 | isa = PBXGroup; 74 | children = ( 75 | FE3D212614980D6D002B99A4 /* SWSnapshotStackViewDemo.app */, 76 | ); 77 | name = Products; 78 | sourceTree = ""; 79 | }; 80 | FE3D212914980D6D002B99A4 /* Frameworks */ = { 81 | isa = PBXGroup; 82 | children = ( 83 | FE3D212A14980D6D002B99A4 /* UIKit.framework */, 84 | FE3D212C14980D6D002B99A4 /* Foundation.framework */, 85 | FE3D212E14980D6D002B99A4 /* CoreGraphics.framework */, 86 | FE3D215A1499957C002B99A4 /* QuartzCore.framework */, 87 | ); 88 | name = Frameworks; 89 | sourceTree = ""; 90 | }; 91 | FE3D213014980D6D002B99A4 /* SWSnapshotStackViewDemo */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | FE3D213914980D6D002B99A4 /* AppDelegate.h */, 95 | FE3D213A14980D6D002B99A4 /* AppDelegate.m */, 96 | FE3D213C14980D6D002B99A4 /* RootViewController.h */, 97 | FE3D213D14980D6D002B99A4 /* RootViewController.m */, 98 | FE3D213F14980D6D002B99A4 /* RootViewController.xib */, 99 | FE3D2156149861C6002B99A4 /* Resources */, 100 | FE3D213114980D6D002B99A4 /* Supporting Files */, 101 | ); 102 | path = SWSnapshotStackViewDemo; 103 | sourceTree = ""; 104 | }; 105 | FE3D213114980D6D002B99A4 /* Supporting Files */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | FE3D213314980D6D002B99A4 /* InfoPlist.strings */, 109 | FE3D213614980D6D002B99A4 /* main.m */, 110 | FE3D213814980D6D002B99A4 /* SWSnapshotStackViewDemo-Prefix.pch */, 111 | FE3D213214980D6D002B99A4 /* SWSnapshotStackViewDemo-Info.plist */, 112 | ); 113 | name = "Supporting Files"; 114 | sourceTree = ""; 115 | }; 116 | FE3D21471498368C002B99A4 /* SWSnapshotStackView */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | FE3D2148149836A9002B99A4 /* SWSnapshotStackView.h */, 120 | FE3D2149149836A9002B99A4 /* SWSnapshotStackView.m */, 121 | ); 122 | name = SWSnapshotStackView; 123 | sourceTree = ""; 124 | }; 125 | FE3D2156149861C6002B99A4 /* Resources */ = { 126 | isa = PBXGroup; 127 | children = ( 128 | FE3D21581499898B002B99A4 /* 350D_IMG_3157_20071030w.jpg */, 129 | FE3D215E149AD601002B99A4 /* IMG_2777_080216w6s.jpg */, 130 | FE3D215C149A1089002B99A4 /* IMG_5737_081229w7sq.jpg */, 131 | ); 132 | name = Resources; 133 | path = ..; 134 | sourceTree = ""; 135 | }; 136 | /* End PBXGroup section */ 137 | 138 | /* Begin PBXNativeTarget section */ 139 | FE3D212514980D6D002B99A4 /* SWSnapshotStackViewDemo */ = { 140 | isa = PBXNativeTarget; 141 | buildConfigurationList = FE3D214414980D6D002B99A4 /* Build configuration list for PBXNativeTarget "SWSnapshotStackViewDemo" */; 142 | buildPhases = ( 143 | FE3D212214980D6D002B99A4 /* Sources */, 144 | FE3D212314980D6D002B99A4 /* Frameworks */, 145 | FE3D212414980D6D002B99A4 /* Resources */, 146 | ); 147 | buildRules = ( 148 | ); 149 | dependencies = ( 150 | ); 151 | name = SWSnapshotStackViewDemo; 152 | productName = SWSnapshotStackViewDemo; 153 | productReference = FE3D212614980D6D002B99A4 /* SWSnapshotStackViewDemo.app */; 154 | productType = "com.apple.product-type.application"; 155 | }; 156 | /* End PBXNativeTarget section */ 157 | 158 | /* Begin PBXProject section */ 159 | FE3D211D14980D6C002B99A4 /* Project object */ = { 160 | isa = PBXProject; 161 | attributes = { 162 | LastUpgradeCheck = 0420; 163 | }; 164 | buildConfigurationList = FE3D212014980D6C002B99A4 /* Build configuration list for PBXProject "SWSnapshotStackViewDemo" */; 165 | compatibilityVersion = "Xcode 3.2"; 166 | developmentRegion = English; 167 | hasScannedForEncodings = 0; 168 | knownRegions = ( 169 | en, 170 | ); 171 | mainGroup = FE3D211B14980D6C002B99A4; 172 | productRefGroup = FE3D212714980D6D002B99A4 /* Products */; 173 | projectDirPath = ""; 174 | projectRoot = ""; 175 | targets = ( 176 | FE3D212514980D6D002B99A4 /* SWSnapshotStackViewDemo */, 177 | ); 178 | }; 179 | /* End PBXProject section */ 180 | 181 | /* Begin PBXResourcesBuildPhase section */ 182 | FE3D212414980D6D002B99A4 /* Resources */ = { 183 | isa = PBXResourcesBuildPhase; 184 | buildActionMask = 2147483647; 185 | files = ( 186 | FE3D213514980D6D002B99A4 /* InfoPlist.strings in Resources */, 187 | FE3D214114980D6D002B99A4 /* RootViewController.xib in Resources */, 188 | FE3D21591499898C002B99A4 /* 350D_IMG_3157_20071030w.jpg in Resources */, 189 | FE3D215D149A1089002B99A4 /* IMG_5737_081229w7sq.jpg in Resources */, 190 | FE3D215F149AD601002B99A4 /* IMG_2777_080216w6s.jpg in Resources */, 191 | ); 192 | runOnlyForDeploymentPostprocessing = 0; 193 | }; 194 | /* End PBXResourcesBuildPhase section */ 195 | 196 | /* Begin PBXSourcesBuildPhase section */ 197 | FE3D212214980D6D002B99A4 /* Sources */ = { 198 | isa = PBXSourcesBuildPhase; 199 | buildActionMask = 2147483647; 200 | files = ( 201 | FE3D213714980D6D002B99A4 /* main.m in Sources */, 202 | FE3D213B14980D6D002B99A4 /* AppDelegate.m in Sources */, 203 | FE3D213E14980D6D002B99A4 /* RootViewController.m in Sources */, 204 | FE3D214A149836A9002B99A4 /* SWSnapshotStackView.m in Sources */, 205 | ); 206 | runOnlyForDeploymentPostprocessing = 0; 207 | }; 208 | /* End PBXSourcesBuildPhase section */ 209 | 210 | /* Begin PBXVariantGroup section */ 211 | FE3D213314980D6D002B99A4 /* InfoPlist.strings */ = { 212 | isa = PBXVariantGroup; 213 | children = ( 214 | FE3D213414980D6D002B99A4 /* en */, 215 | ); 216 | name = InfoPlist.strings; 217 | sourceTree = ""; 218 | }; 219 | FE3D213F14980D6D002B99A4 /* RootViewController.xib */ = { 220 | isa = PBXVariantGroup; 221 | children = ( 222 | FE3D214014980D6D002B99A4 /* en */, 223 | ); 224 | name = RootViewController.xib; 225 | sourceTree = ""; 226 | }; 227 | /* End PBXVariantGroup section */ 228 | 229 | /* Begin XCBuildConfiguration section */ 230 | FE3D214214980D6D002B99A4 /* Debug */ = { 231 | isa = XCBuildConfiguration; 232 | buildSettings = { 233 | ALWAYS_SEARCH_USER_PATHS = NO; 234 | ARCHS = ( 235 | armv6, 236 | "$(ARCHS_STANDARD_32_BIT)", 237 | ); 238 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 239 | COPY_PHASE_STRIP = NO; 240 | GCC_C_LANGUAGE_STANDARD = gnu99; 241 | GCC_DYNAMIC_NO_PIC = NO; 242 | GCC_OPTIMIZATION_LEVEL = 0; 243 | GCC_PREPROCESSOR_DEFINITIONS = ( 244 | "DEBUG=1", 245 | "$(inherited)", 246 | ); 247 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 248 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 249 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 250 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 251 | GCC_WARN_UNUSED_VARIABLE = YES; 252 | IPHONEOS_DEPLOYMENT_TARGET = 3.1; 253 | SDKROOT = iphoneos; 254 | }; 255 | name = Debug; 256 | }; 257 | FE3D214314980D6D002B99A4 /* Release */ = { 258 | isa = XCBuildConfiguration; 259 | buildSettings = { 260 | ALWAYS_SEARCH_USER_PATHS = NO; 261 | ARCHS = ( 262 | armv6, 263 | "$(ARCHS_STANDARD_32_BIT)", 264 | ); 265 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 266 | COPY_PHASE_STRIP = YES; 267 | GCC_C_LANGUAGE_STANDARD = gnu99; 268 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 269 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 270 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 271 | GCC_WARN_UNUSED_VARIABLE = YES; 272 | IPHONEOS_DEPLOYMENT_TARGET = 3.1; 273 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 274 | SDKROOT = iphoneos; 275 | VALIDATE_PRODUCT = YES; 276 | }; 277 | name = Release; 278 | }; 279 | FE3D214514980D6D002B99A4 /* Debug */ = { 280 | isa = XCBuildConfiguration; 281 | buildSettings = { 282 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 283 | GCC_PREFIX_HEADER = "SWSnapshotStackViewDemo/SWSnapshotStackViewDemo-Prefix.pch"; 284 | INFOPLIST_FILE = "SWSnapshotStackViewDemo/SWSnapshotStackViewDemo-Info.plist"; 285 | IPHONEOS_DEPLOYMENT_TARGET = 3.1; 286 | PRODUCT_NAME = "$(TARGET_NAME)"; 287 | TARGETED_DEVICE_FAMILY = 1; 288 | WRAPPER_EXTENSION = app; 289 | }; 290 | name = Debug; 291 | }; 292 | FE3D214614980D6D002B99A4 /* Release */ = { 293 | isa = XCBuildConfiguration; 294 | buildSettings = { 295 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 296 | GCC_PREFIX_HEADER = "SWSnapshotStackViewDemo/SWSnapshotStackViewDemo-Prefix.pch"; 297 | INFOPLIST_FILE = "SWSnapshotStackViewDemo/SWSnapshotStackViewDemo-Info.plist"; 298 | IPHONEOS_DEPLOYMENT_TARGET = 3.1; 299 | PRODUCT_NAME = "$(TARGET_NAME)"; 300 | TARGETED_DEVICE_FAMILY = 1; 301 | WRAPPER_EXTENSION = app; 302 | }; 303 | name = Release; 304 | }; 305 | /* End XCBuildConfiguration section */ 306 | 307 | /* Begin XCConfigurationList section */ 308 | FE3D212014980D6C002B99A4 /* Build configuration list for PBXProject "SWSnapshotStackViewDemo" */ = { 309 | isa = XCConfigurationList; 310 | buildConfigurations = ( 311 | FE3D214214980D6D002B99A4 /* Debug */, 312 | FE3D214314980D6D002B99A4 /* Release */, 313 | ); 314 | defaultConfigurationIsVisible = 0; 315 | defaultConfigurationName = Release; 316 | }; 317 | FE3D214414980D6D002B99A4 /* Build configuration list for PBXNativeTarget "SWSnapshotStackViewDemo" */ = { 318 | isa = XCConfigurationList; 319 | buildConfigurations = ( 320 | FE3D214514980D6D002B99A4 /* Debug */, 321 | FE3D214614980D6D002B99A4 /* Release */, 322 | ); 323 | defaultConfigurationIsVisible = 0; 324 | defaultConfigurationName = Release; 325 | }; 326 | /* End XCConfigurationList section */ 327 | }; 328 | rootObject = FE3D211D14980D6C002B99A4 /* Project object */; 329 | } 330 | -------------------------------------------------------------------------------- /SWSnapshotStackViewDemo/SWSnapshotStackViewDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | /*! 3 | ** \file AppDelegate.h 4 | ** \brief Application Delegate class definition file 5 | ** \author Scott White (support@scottwhite.id.au, http://github.com/snwau) 6 | ** 7 | ** Application Delegate class auto-generated via Xcode project wizard. 8 | ** 9 | ** Copyright (c) 2012 Scott White. All rights reserved. 10 | ** 11 | ** Permission is hereby granted, free of charge, to any person obtaining a 12 | ** copy of this software and associated documentation files (the "Software"), 13 | ** to deal in the Software without restriction, including without limitation 14 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 15 | ** and/or sell copies of the Software, and to permit persons to whom the 16 | ** Software is furnished to do so, subject to the following conditions: 17 | ** 18 | ** The above copyright notice and this permission notice shall be included 19 | ** in all copies or substantial portions of the Software. 20 | ** 21 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 22 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 24 | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 25 | ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 26 | ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 27 | ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | ** 29 | ** Open Source Initiative OSI - The MIT License, 30 | ** see . 31 | ** 32 | ** \see AppDelegate.m 33 | */ 34 | // Documentation of the code is formatted for use with the documentation 35 | // package Doxygen (see http://www.doxygen.org/). 36 | // 37 | // Project : Snapshot Stack View Demonstration 38 | // Platform : iOS SDK 3.0+ 39 | // 40 | //////////////////////////////////////////////////////////////////////////// 41 | 42 | #import 43 | 44 | #import "RootViewController.h" 45 | 46 | 47 | // ********************************************************************** // 48 | // APPLICATION DELEGATE CLASS 49 | // ********************************************************************** // 50 | 51 | #pragma mark Application Delegate class 52 | 53 | @interface AppDelegate : UIResponder 54 | { 55 | 56 | } 57 | 58 | 59 | // ********************************************************************** // 60 | // PROPERTIES 61 | 62 | #pragma mark Properties 63 | 64 | @property (strong, nonatomic) RootViewController *viewController; 65 | @property (strong, nonatomic) UIWindow *window; 66 | 67 | 68 | // ********************************************************************** // 69 | 70 | @end // @AppDelegate 71 | 72 | // End of file -------------------------------------------------------------------------------- /SWSnapshotStackViewDemo/SWSnapshotStackViewDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | /*! 3 | ** \file AppDelegate.m 4 | ** \brief Application Delegate class implementation file 5 | ** \author Scott White (support@scottwhite.id.au, http://github.com/snwau) 6 | ** 7 | ** Application Delegate class auto-generated via Xcode project wizard. 8 | ** 9 | ** Copyright (c) 2012 Scott White. All rights reserved. 10 | ** 11 | ** Permission is hereby granted, free of charge, to any person obtaining a 12 | ** copy of this software and associated documentation files (the "Software"), 13 | ** to deal in the Software without restriction, including without limitation 14 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 15 | ** and/or sell copies of the Software, and to permit persons to whom the 16 | ** Software is furnished to do so, subject to the following conditions: 17 | ** 18 | ** The above copyright notice and this permission notice shall be included 19 | ** in all copies or substantial portions of the Software. 20 | ** 21 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 22 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 24 | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 25 | ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 26 | ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 27 | ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | ** 29 | ** Open Source Initiative OSI - The MIT License, 30 | ** see . 31 | ** 32 | ** \see AppDelegate.h 33 | */ 34 | // Documentation of the code is formatted for use with the documentation 35 | // package Doxygen (see http://www.doxygen.org/). 36 | // 37 | // Project : Snapshot Stack View Demonstration 38 | // Platform : iOS SDK 3.0+ 39 | // 40 | //////////////////////////////////////////////////////////////////////////// 41 | 42 | #import "AppDelegate.h" 43 | 44 | 45 | // ********************************************************************** // 46 | // APPLICATION DELEGATE CLASS 47 | // ********************************************************************** // 48 | 49 | #pragma mark Application Delegate class 50 | 51 | @implementation AppDelegate 52 | 53 | // ********************************************************************** // 54 | // PROPERTIES 55 | 56 | #pragma mark Properties 57 | 58 | @synthesize window = _window; 59 | @synthesize viewController = _viewController; 60 | 61 | 62 | // ********************************************************************** // 63 | // INSTANCE METHODS 64 | 65 | #pragma mark Instance Methods 66 | 67 | - (void)dealloc 68 | { 69 | [_window release]; 70 | [_viewController release]; 71 | 72 | [super dealloc]; 73 | } 74 | 75 | 76 | // ********************************************************************** // 77 | 78 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 79 | { 80 | self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; 81 | 82 | // Override point for customization after application launch. 83 | self.viewController = [[[RootViewController alloc] initWithNibName:@"RootViewController" bundle:nil] autorelease]; 84 | self.window.rootViewController = self.viewController; 85 | [self.window makeKeyAndVisible]; 86 | return (YES); 87 | } 88 | 89 | 90 | // ********************************************************************** // 91 | 92 | - (void)applicationWillResignActive:(UIApplication *)application 93 | { 94 | /* 95 | 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. 96 | 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. 97 | */ 98 | } 99 | 100 | 101 | // ********************************************************************** // 102 | 103 | - (void)applicationDidEnterBackground:(UIApplication *)application 104 | { 105 | /* 106 | 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. 107 | If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 108 | */ 109 | } 110 | 111 | 112 | // ********************************************************************** // 113 | 114 | - (void)applicationWillEnterForeground:(UIApplication *)application 115 | { 116 | /* 117 | 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. 118 | */ 119 | } 120 | 121 | 122 | // ********************************************************************** // 123 | 124 | - (void)applicationDidBecomeActive:(UIApplication *)application 125 | { 126 | /* 127 | 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. 128 | */ 129 | } 130 | 131 | 132 | // ********************************************************************** // 133 | 134 | - (void)applicationWillTerminate:(UIApplication *)application 135 | { 136 | /* 137 | Called when the application is about to terminate. 138 | Save data if appropriate. 139 | See also applicationDidEnterBackground:. 140 | */ 141 | } 142 | 143 | 144 | // ********************************************************************** // 145 | 146 | @end // @AppDelegate 147 | 148 | // End of file 149 | -------------------------------------------------------------------------------- /SWSnapshotStackViewDemo/SWSnapshotStackViewDemo/Resources/350D_IMG_3157_20071030w.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snwau/SWSnapshotStackView/8e34c803647de4d2698476bebf0beef62f4208be/SWSnapshotStackViewDemo/SWSnapshotStackViewDemo/Resources/350D_IMG_3157_20071030w.jpg -------------------------------------------------------------------------------- /SWSnapshotStackViewDemo/SWSnapshotStackViewDemo/Resources/IMG_2777_080216w6s.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snwau/SWSnapshotStackView/8e34c803647de4d2698476bebf0beef62f4208be/SWSnapshotStackViewDemo/SWSnapshotStackViewDemo/Resources/IMG_2777_080216w6s.jpg -------------------------------------------------------------------------------- /SWSnapshotStackViewDemo/SWSnapshotStackViewDemo/Resources/IMG_5737_081229w7sq.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snwau/SWSnapshotStackView/8e34c803647de4d2698476bebf0beef62f4208be/SWSnapshotStackViewDemo/SWSnapshotStackViewDemo/Resources/IMG_5737_081229w7sq.jpg -------------------------------------------------------------------------------- /SWSnapshotStackViewDemo/SWSnapshotStackViewDemo/RootViewController.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | /*! 3 | ** \file RootViewController.h 4 | ** \brief Root View Controller class definition file 5 | ** \author Scott White (support@scottwhite.id.au, http://github.com/snwau) 6 | ** 7 | ** The root (and only) view controller responsible for displaying and 8 | ** controlling a Snapshot Stack View and associated controls for 9 | ** demonstrating its capabilities such as dynamic frame adjustment, 10 | ** support for all image aspects and the selectable display modes (single 11 | ** or stack). 12 | ** 13 | ** Copyright (c) 2012 Scott White. All rights reserved. 14 | ** 15 | ** Permission is hereby granted, free of charge, to any person obtaining a 16 | ** copy of this software and associated documentation files (the "Software"), 17 | ** to deal in the Software without restriction, including without limitation 18 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 19 | ** and/or sell copies of the Software, and to permit persons to whom the 20 | ** Software is furnished to do so, subject to the following conditions: 21 | ** 22 | ** The above copyright notice and this permission notice shall be included 23 | ** in all copies or substantial portions of the Software. 24 | ** 25 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 26 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 28 | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 29 | ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 30 | ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 31 | ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 32 | ** 33 | ** Open Source Initiative OSI - The MIT License, 34 | ** see . 35 | ** 36 | ** \see RootViewController.m 37 | */ 38 | // Documentation of the code is formatted for use with the documentation 39 | // package Doxygen (see http://www.doxygen.org/). 40 | // 41 | // Project : Snapshot Stack View Demonstration 42 | // Platform : iOS SDK 3.0+ 43 | // 44 | //////////////////////////////////////////////////////////////////////////// 45 | 46 | #import 47 | 48 | #import "SWSnapshotStackView.h" 49 | 50 | 51 | // ********************************************************************** // 52 | // ROOT VIEW CONTROLLER CLASS 53 | // ********************************************************************** // 54 | 55 | #pragma mark Root View Controller class 56 | 57 | @interface RootViewController : UIViewController 58 | { 59 | // ******************************************************************** // 60 | // MEMBER VARIABLES 61 | 62 | UISwitch *m_displayStackSwitch; 63 | UISegmentedControl *m_imageSelection; 64 | UILabel *m_imageFrameSize; 65 | UISlider *m_sizeSlider; 66 | SWSnapshotStackView *m_snapshotStackView; 67 | } 68 | 69 | 70 | // ********************************************************************** // 71 | // PROPERTIES 72 | 73 | #pragma mark Properties 74 | 75 | @property (nonatomic, retain) IBOutlet UISwitch *displayStackSwitch; 76 | @property (nonatomic, retain) IBOutlet UILabel *imageFrameSize; 77 | @property (nonatomic, retain) IBOutlet UISegmentedControl *imageSelection; 78 | @property (nonatomic, retain) IBOutlet UISlider *sizeSlider; 79 | @property (nonatomic, retain) IBOutlet SWSnapshotStackView *snapshotStackView; 80 | 81 | 82 | // ********************************************************************** // 83 | // ACTION METHODS 84 | 85 | #pragma mark Action Methods 86 | 87 | - (IBAction)displayStackSwitchValueChanged:(id)sender; 88 | - (IBAction)imageSelectionValueChanged:(id)sender; 89 | - (IBAction)sizeSliderValueChanged:(id)sender; 90 | 91 | 92 | // ********************************************************************** // 93 | 94 | @end // @RootViewController 95 | 96 | // End of file 97 | -------------------------------------------------------------------------------- /SWSnapshotStackViewDemo/SWSnapshotStackViewDemo/RootViewController.m: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | /*! 3 | ** \file RootViewController.m 4 | ** \brief Root View Controller class implementation file 5 | ** \author Scott White (support@scottwhite.id.au, http://github.com/snwau) 6 | ** 7 | ** The root (and only) view controller responsible for displaying and 8 | ** controlling a Snapshot Stack View and associated controls for 9 | ** demonstrating its capabilities such as dynamic frame adjustment, 10 | ** support for all image aspects and the selectable display modes (single 11 | ** or stack). 12 | ** 13 | ** Copyright (c) 2012 Scott White. All rights reserved. 14 | ** 15 | ** Permission is hereby granted, free of charge, to any person obtaining a 16 | ** copy of this software and associated documentation files (the "Software"), 17 | ** to deal in the Software without restriction, including without limitation 18 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 19 | ** and/or sell copies of the Software, and to permit persons to whom the 20 | ** Software is furnished to do so, subject to the following conditions: 21 | ** 22 | ** The above copyright notice and this permission notice shall be included 23 | ** in all copies or substantial portions of the Software. 24 | ** 25 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 26 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 28 | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 29 | ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 30 | ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 31 | ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 32 | ** 33 | ** Open Source Initiative OSI - The MIT License, 34 | ** see . 35 | ** 36 | ** \see RootViewController.h 37 | */ 38 | // Documentation of the code is formatted for use with the documentation 39 | // package Doxygen (see http://www.doxygen.org/). 40 | // 41 | // Project : Snapshot Stack View Demonstration 42 | // Platform : iOS SDK 3.0+ 43 | // 44 | //////////////////////////////////////////////////////////////////////////// 45 | 46 | #import "RootViewController.h" 47 | 48 | 49 | // ********************************************************************** // 50 | // ROOT VIEW CONTROLLER CLASS 51 | // ********************************************************************** // 52 | 53 | #pragma mark Root View Controller class 54 | 55 | @implementation RootViewController 56 | 57 | 58 | // ********************************************************************** // 59 | // PROPERTIES 60 | 61 | #pragma mark Properties 62 | 63 | @synthesize displayStackSwitch = m_displayStackSwitch; 64 | @synthesize imageFrameSize = m_imageFrameSize; 65 | @synthesize imageSelection = m_imageSelection; 66 | @synthesize sizeSlider = m_sizeSlider; 67 | @synthesize snapshotStackView = m_snapshotStackView; 68 | 69 | 70 | // ********************************************************************** // 71 | // INSTANCE METHODS 72 | 73 | #pragma mark Instance Methods 74 | 75 | - (void)didReceiveMemoryWarning 76 | { 77 | [super didReceiveMemoryWarning]; 78 | 79 | // Release any cached data, images, etc that aren't in use. 80 | } 81 | 82 | 83 | // ********************************************************************** // 84 | 85 | - (void)viewDidLoad 86 | { 87 | [super viewDidLoad]; 88 | 89 | // Do any additional setup after loading the view, typically from a nib. 90 | 91 | #if 1 92 | // Tested with the views contentMode set to redraw (forces call to drawRect: 93 | // on change of views frame) enabled and disabled. 94 | m_snapshotStackView.contentMode = UIViewContentModeRedraw; 95 | #endif 96 | 97 | m_snapshotStackView.displayAsStack = m_displayStackSwitch.on; 98 | m_snapshotStackView.image = [UIImage imageNamed:@"350D_IMG_3157_20071030w.jpg"]; 99 | } 100 | 101 | 102 | // ********************************************************************** // 103 | 104 | - (void)viewDidUnload 105 | { 106 | [super viewDidUnload]; 107 | 108 | // Release any retained subviews of the main view. 109 | self.displayStackSwitch = nil; 110 | self.imageFrameSize = nil; 111 | self.imageSelection = nil; 112 | self.sizeSlider = nil; 113 | self.snapshotStackView = nil; 114 | } 115 | 116 | 117 | // ********************************************************************** // 118 | 119 | /* 120 | - (void)viewWillAppear:(BOOL)animated 121 | { 122 | [super viewWillAppear:animated]; 123 | } 124 | 125 | - (void)viewDidAppear:(BOOL)animated 126 | { 127 | [super viewDidAppear:animated]; 128 | } 129 | 130 | - (void)viewWillDisappear:(BOOL)animated 131 | { 132 | [super viewWillDisappear:animated]; 133 | } 134 | 135 | - (void)viewDidDisappear:(BOOL)animated 136 | { 137 | [super viewDidDisappear:animated]; 138 | } 139 | */ 140 | 141 | 142 | // ********************************************************************** // 143 | 144 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 145 | { 146 | // Return YES for supported orientations 147 | return (interfaceOrientation == UIInterfaceOrientationPortrait); 148 | } 149 | 150 | 151 | // ********************************************************************** // 152 | // ACTION METHODS 153 | 154 | #pragma mark Action Methods 155 | 156 | - (IBAction)displayStackSwitchValueChanged:(id)sender 157 | { 158 | m_snapshotStackView.displayAsStack = m_displayStackSwitch.on; 159 | } 160 | 161 | 162 | // ********************************************************************** // 163 | 164 | - (IBAction)imageSelectionValueChanged:(id)sender 165 | { 166 | switch (m_imageSelection.selectedSegmentIndex) 167 | { 168 | case 0: 169 | m_snapshotStackView.image = [UIImage imageNamed:@"350D_IMG_3157_20071030w.jpg"]; 170 | break; 171 | 172 | case 1: 173 | m_snapshotStackView.image = [UIImage imageNamed:@"IMG_5737_081229w7sq.jpg"]; 174 | break; 175 | 176 | case 2: 177 | m_snapshotStackView.image = [UIImage imageNamed:@"IMG_2777_080216w6s.jpg"]; 178 | break; 179 | 180 | default: 181 | m_snapshotStackView.image = nil; 182 | } 183 | } 184 | 185 | 186 | // ********************************************************************** // 187 | 188 | - (IBAction)sizeSliderValueChanged:(id)sender 189 | { 190 | CGFloat sizeDelta = m_sizeSlider.maximumValue - m_sizeSlider.value; 191 | 192 | CGRect newFrame = CGRectMake (floor (20 + (sizeDelta / 2.0)), 193 | floor (20 + (sizeDelta / 2.0)), 194 | floor (m_sizeSlider.value), 195 | floor (m_sizeSlider.value)); 196 | m_snapshotStackView.frame = newFrame; 197 | 198 | m_imageFrameSize.text = [NSString stringWithFormat:@"(%.0f x %.0f)", floor (m_sizeSlider.value), 199 | floor (m_sizeSlider.value)]; 200 | } 201 | 202 | 203 | // ********************************************************************** // 204 | 205 | @end // @RootViewController 206 | 207 | // End of file -------------------------------------------------------------------------------- /SWSnapshotStackViewDemo/SWSnapshotStackViewDemo/SWSnapshotStackViewDemo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | Snapshot 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFiles 12 | 13 | CFBundleIdentifier 14 | com.scottwhite.${PRODUCT_NAME:rfc1034identifier} 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | ${PRODUCT_NAME} 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | 1.0 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | 1.0 27 | LSRequiresIPhoneOS 28 | 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /SWSnapshotStackViewDemo/SWSnapshotStackViewDemo/SWSnapshotStackViewDemo-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'SWSnapshotStackViewDemo' target in the 'SWSnapshotStackViewDemo' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_4_0 8 | #warning "This project uses features only available in iOS SDK 4.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /SWSnapshotStackViewDemo/SWSnapshotStackViewDemo/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /SWSnapshotStackViewDemo/SWSnapshotStackViewDemo/en.lproj/RootViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1280 5 | 11C74 6 | 1938 7 | 1138.23 8 | 567.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 933 12 | 13 | 14 | IBUISlider 15 | IBUISwitch 16 | IBUISegmentedControl 17 | IBUIView 18 | IBUILabel 19 | IBProxyObject 20 | 21 | 22 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 23 | 24 | 25 | PluginDependencyRecalculationVersion 26 | 27 | 28 | 29 | 30 | IBFilesOwner 31 | IBCocoaTouchFramework 32 | 33 | 34 | IBFirstResponder 35 | IBCocoaTouchFramework 36 | 37 | 38 | 39 | 274 40 | 41 | 42 | 43 | 274 44 | {{20, 20}, {280, 280}} 45 | 46 | 47 | 48 | _NS:196 49 | 50 | 3 51 | MQA 52 | 53 | 2 54 | 55 | 56 | IBCocoaTouchFramework 57 | 58 | 59 | 60 | 292 61 | {{18, 308}, {284, 23}} 62 | 63 | 64 | 65 | _NS:623 66 | NO 67 | IBCocoaTouchFramework 68 | 0 69 | 0 70 | 280 71 | 120 72 | 280 73 | 74 | 75 | 76 | 292 77 | {{206, 352}, {94, 27}} 78 | 79 | 80 | 81 | _NS:606 82 | NO 83 | IBCocoaTouchFramework 84 | 0 85 | 0 86 | YES 87 | 88 | 89 | 90 | 292 91 | {{20, 397}, {280, 44}} 92 | 93 | 94 | 95 | _NS:273 96 | NO 97 | IBCocoaTouchFramework 98 | 3 99 | 0 100 | 101 | Image 1 102 | Image 2 103 | Image 3 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | {0, 0} 117 | {0, 0} 118 | {0, 0} 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 292 129 | {{80, 354}, {120, 21}} 130 | 131 | 132 | 133 | _NS:328 134 | NO 135 | YES 136 | 7 137 | NO 138 | IBCocoaTouchFramework 139 | Display Stack 140 | 141 | 1 142 | MCAwIDAAA 143 | 144 | 145 | 1 146 | 10 147 | 2 148 | 149 | 1 150 | 17 151 | 152 | 153 | Helvetica 154 | 17 155 | 16 156 | 157 | 158 | 159 | 160 | 292 161 | {{20, 328}, {81, 21}} 162 | 163 | 164 | _NS:328 165 | NO 166 | YES 167 | 7 168 | NO 169 | IBCocoaTouchFramework 170 | (280 x 280) 171 | 172 | 173 | 1 174 | 10 175 | 176 | 1 177 | 14 178 | 179 | 180 | Helvetica 181 | 14 182 | 16 183 | 184 | 185 | 186 | {{0, 20}, {320, 460}} 187 | 188 | 189 | 190 | 191 | 3 192 | MQA 193 | 194 | NO 195 | 196 | IBCocoaTouchFramework 197 | 198 | 199 | 200 | 201 | 202 | 203 | view 204 | 205 | 206 | 207 | 7 208 | 209 | 210 | 211 | snapshotStackView 212 | 213 | 214 | 215 | 13 216 | 217 | 218 | 219 | sizeSlider 220 | 221 | 222 | 223 | 14 224 | 225 | 226 | 227 | displayStackSwitch 228 | 229 | 230 | 231 | 15 232 | 233 | 234 | 235 | imageSelection 236 | 237 | 238 | 239 | 16 240 | 241 | 242 | 243 | imageFrameSize 244 | 245 | 246 | 247 | 22 248 | 249 | 250 | 251 | sizeSliderValueChanged: 252 | 253 | 254 | 13 255 | 256 | 17 257 | 258 | 259 | 260 | displayStackSwitchValueChanged: 261 | 262 | 263 | 13 264 | 265 | 19 266 | 267 | 268 | 269 | imageSelectionValueChanged: 270 | 271 | 272 | 13 273 | 274 | 20 275 | 276 | 277 | 278 | 279 | 280 | 0 281 | 282 | 283 | 284 | 285 | 286 | -1 287 | 288 | 289 | File's Owner 290 | 291 | 292 | -2 293 | 294 | 295 | 296 | 297 | 6 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 8 311 | 312 | 313 | 314 | 315 | 9 316 | 317 | 318 | 319 | 320 | 10 321 | 322 | 323 | 324 | 325 | 11 326 | 327 | 328 | 329 | 330 | 12 331 | 332 | 333 | 334 | 335 | 21 336 | 337 | 338 | 339 | 340 | 341 | 342 | RootViewController 343 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 344 | UIResponder 345 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 346 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 347 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 348 | 349 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 350 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 351 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 352 | SWSnapshotStackView 353 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 354 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 355 | 356 | 357 | 358 | 359 | 360 | 22 361 | 362 | 363 | 364 | 365 | RootViewController 366 | UIViewController 367 | 368 | id 369 | id 370 | id 371 | 372 | 373 | 374 | displayStackSwitchValueChanged: 375 | id 376 | 377 | 378 | imageSelectionValueChanged: 379 | id 380 | 381 | 382 | sizeSliderValueChanged: 383 | id 384 | 385 | 386 | 387 | UISwitch 388 | UILabel 389 | UISegmentedControl 390 | UISlider 391 | SWSnapshotStackView 392 | 393 | 394 | 395 | displayStackSwitch 396 | UISwitch 397 | 398 | 399 | imageFrameSize 400 | UILabel 401 | 402 | 403 | imageSelection 404 | UISegmentedControl 405 | 406 | 407 | sizeSlider 408 | UISlider 409 | 410 | 411 | snapshotStackView 412 | SWSnapshotStackView 413 | 414 | 415 | 416 | IBProjectSource 417 | ./Classes/RootViewController.h 418 | 419 | 420 | 421 | SWSnapshotStackView 422 | UIView 423 | 424 | IBProjectSource 425 | ./Classes/SWSnapshotStackView.h 426 | 427 | 428 | 429 | 430 | 0 431 | IBCocoaTouchFramework 432 | YES 433 | 3 434 | 933 435 | 436 | 437 | -------------------------------------------------------------------------------- /SWSnapshotStackViewDemo/SWSnapshotStackViewDemo/main.m: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | /*! 3 | ** \file main.m 4 | ** \brief Application entry point 5 | ** \author Scott White (support@scottwhite.id.au, http://github.com/snwau) 6 | ** 7 | ** Entry point of application execution, auto-generated via Xcode project 8 | ** wizard. 9 | ** 10 | ** Copyright (c) 2012 Scott White. All rights reserved. 11 | ** 12 | ** Permission is hereby granted, free of charge, to any person obtaining a 13 | ** copy of this software and associated documentation files (the "Software"), 14 | ** to deal in the Software without restriction, including without limitation 15 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 16 | ** and/or sell copies of the Software, and to permit persons to whom the 17 | ** Software is furnished to do so, subject to the following conditions: 18 | ** 19 | ** The above copyright notice and this permission notice shall be included 20 | ** in all copies or substantial portions of the Software. 21 | ** 22 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 23 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 25 | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 26 | ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 27 | ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 28 | ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | ** 30 | ** Open Source Initiative OSI - The MIT License, 31 | ** see . 32 | ** 33 | */ 34 | // Documentation of the code is formatted for use with the documentation 35 | // package Doxygen (see http://www.doxygen.org/). 36 | // 37 | // Project : Snapshot Stack View Demonstration 38 | // Platform : iOS SDK 3.0+ 39 | // 40 | //////////////////////////////////////////////////////////////////////////// 41 | 42 | #import 43 | 44 | #import "AppDelegate.h" 45 | 46 | 47 | // ********************************************************************** // 48 | 49 | int main (int argc, char *argv[]) 50 | { 51 | @autoreleasepool 52 | { 53 | return (UIApplicationMain (argc, argv, nil, 54 | NSStringFromClass ([AppDelegate class]))); 55 | } 56 | } 57 | 58 | 59 | // ********************************************************************** // 60 | 61 | // End of file 62 | -------------------------------------------------------------------------------- /Screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snwau/SWSnapshotStackView/8e34c803647de4d2698476bebf0beef62f4208be/Screenshot.png -------------------------------------------------------------------------------- /ScreenshotDemo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snwau/SWSnapshotStackView/8e34c803647de4d2698476bebf0beef62f4208be/ScreenshotDemo.png --------------------------------------------------------------------------------