Screen Capture in iOS Apps

by Bob McCune on September 8, 2011

I occasionally come across the need to grab the contents of a view as an image. This is often the result of needing to perform some non-stock, animated transition between views, but there are a variety of reasons why this might be useful. Thanks to the Core Animation framework’s CALayer class, this is easy to do.

All UIView instances have an underlying instance of a CALayer. The layer is responsible for rendering the view’s contents and performing any view-related animations. CALayer defines a method called renderInContext: which allows you to render the layer, and its sublayers, into a given graphics context:

UIGraphicsContext context = // some graphics context
[viewToCapture.layer renderInContext:context];

Before you can access any layer-specific APIs, you’ll need to make sure you’re linking against the QuartzCore framework. Xcode’s default templates don’t link against this framework so you’ll need to select Target Name > Build Phases > Link Binary With Libraries and select QuartzCore.framework.

Additionally, you’ll need to add the following import to your code wherever you are calling the layer’s properties or methods:

#import <QuartzCore/QuartzCore.h>

With the necessary project configuration out of the way, the next question is where do we get a graphics context into which we can render the view’s content? This can be created using UIKit’s UIGraphicsBeginImageContextWithOptions function which will create a new bitmap-based graphics context for us.

UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale);

This function takes a CGSize (you view’s size), a BOOL indicating if your view is opaque, and a CGFloat specifying the scaling factor. If you’re rendering a fully opaque, rectangular view you can pass YES for the opaque argument so the alpha channel can be discarded from the context.

Now that we’ve created a graphics context we can use the UIGraphicsGetCurrentContext() and UIGraphicsGetImageFromCurrentImageContext() functions to get reference to this new context and retrieve the rendered image data from it. Finally, we’ll want to call the UIGraphicsEndImageContext() function to clean up this context and remove it from the stack. Putting all this together we end up with the following:

// Render the views layer contents into the current Graphics context
CGSize viewSize = viewToCapture.bounds.size;
UIGraphicsBeginImageContextWithOptions(viewSize, NO, 1.0);
[viewToCapture.layer renderInContext:UIGraphicsGetCurrentContext()];
// Read the UIImage object
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

To see this code in action I’ve put together a simple demo app. You can tap on Archer, Lana, or the background to capture the contents of the view and write the image to your Photo Library.

Note: Before running the demo be sure to open the “Photos” app on the Simulator so it can initialize its database or the images won’t be written. Enjoy!

Download Demo

[ 3 comments ]

Quick Github PSA

by Bob McCune on September 6, 2011

My Core Animation Demos projects was previously available on Github under my personal account, but I have since moved it to my business account. The new location of of the CA demos is:

https://github.com/tapharmonic/Core-Animation-Demos

I haven’t made any major changes to code at this point, however, I did start an ARC branch to house my ongoing ARC changes.

[ 0 comments ]

Automagic Factories in Objective-C

by Bob McCune on April 8, 2011

The Factory pattern is a frequently used creational pattern to help abstract the creation of an object from its clients. Although there are a few specializations of this pattern I’ll focus on the most commonly used approach and then look at how we can leverage the Objective-C Runtime to make this solution more robust.

Let’s begin by creating a simple command-line app that creates Animal objects and gets them to speak on command. The various animal objects will all inherit from the abstract Animal class.
[click to continue…]

[ 7 comments ]

Core Animation Presentation

by Bob McCune on March 13, 2011

This past week I gave a presentation on Core Animation to the Minnesota CocoaHeads user group. Core Animation is a truly amazing framework and is really the magic ingredient in the iOS user experience. Understanding how to effectively use it can allow you to add new levels of realism and interactivity to your apps.

As part of the presentation I prepared a number of examples ranging from image effects to 3D animations (OK, 2 1/2 D animations). If you’re interested in taking a look you can find the demo on github and the slides are available here.

[ 3 comments ]

iOS 101: Pattern Images

by Bob McCune on March 8, 2011

A common need in an iOS app is to tile a background image on a UIView. It’s trivial to implement, but not particularly obvious if you’re new to the platform. The solution is to set the view’s backgroundColor property to a UIColor instance created from your pattern image. For instance, the following code will create a pattern image from pattern.png:

- (void)viewDidLoad {
  [super viewDidLoad];
  UIImage *patternImage = [UIImage imageNamed:@"pattern.png"];
  self.view.backgroundColor = [UIColor colorWithPatternImage:patternImage];
}

This will produce the following effect:

Like most things in Cocoa there is usually an easy solution to the problem you’re trying to solve, but what it is may not be immediately apparent if you’re just starting out. Hope this helps.

[ 0 comments ]

Using iOS 4′s IBOutletCollection

by Bob McCune on January 31, 2011

Cocoa has long defined the IBAction and IBOutlet keywords. These keywords provide metadata hints to Interface Builder providing it some understanding of your underlying code so you can graphically wire instance variables and properties and set target-action behaviors. For instance, whenever you need a pointer to NIB-defined object you would create a property defined as:

@interface MainViewController : UIViewController {
    UIButton *saveButton;
}
@property (nonatomic, retain) IBOutlet UIButton *saveButton;
@end

The inclusion of the IBOutlet keyword in the saveButton’s property definition makes it visible to Interface Builder allowing this connection to be wired graphically as show below:

Interface Builder

Using IBOutlet makes it very easy to define your UI in Interface Builder and simply “wire” the object references to your code. However, it does come with one major drawback in that the relationship from a NIB-defined object to property/ivar is always 1-to-1; there was no way to define a collection of components as a single property in your code. Thankfully, Apple quietly introduced a new keyword in iOS4+ called IBOutletCollection allowing you to do just this. Let’s take a closer look at an example where this can be useful.

IBOutletCollection

Like the other keywords previously mentioned, you’ll find the IBOutletCollection keyword in UINibDeclarations.h, which is part of the UIKit framework. The new keyword is defined as follows:

#ifndef IBOutletCollection
#define IBOutletCollection(ClassName)
#endif

You’ll notice that IBOutletCollection takes a class name parameter. This allows you specify what are considered valid values for the collection such as UIView or UIButton. If you’d prefer you can change the “type” argument to id to allow for a heterogeneous collection. So how could this be useful?

Putting IBOutletCollection To Work

I’ve often found times where I needed references to certain components, but really only in an aggregate way so I could change state on them as a group. To do this I’d first need to define separate ivar/property combinations for each component, wire them up in Interface Builder, and then manually collect each pointer into an NSArray and store the collection for later use. Although this works, it is rather tedious and does add unnecessary bloat to your code. A better way to handle this type of scenario is to make use of the IBOutletCollection keyword and wire up this relationship in IB.

In the example below I’ve defined two unique ivars/properties to hold references to my on & off buttons and then an NSArray to hold a collection of other buttons. The on/off buttons are used to change the enabled state of the group of “otherButtons”.

@interface MainViewController : UIViewController {
    UIButton *onButton;
    UIButton *offButton;
    NSArray  *otherButtons;
}

@property (nonatomic, retain) IBOutlet UIButton *onButton;
@property (nonatomic, retain) IBOutlet UIButton *offButton;
@property (nonatomic, retain) IBOutletCollection(UIButton) NSArray *otherButtons;

- (IBAction)toggleButtons:(id)sender;

@end
@implementation MainViewController

- (void)setButtonsState:(BOOL)state {
   for (id button in self.otherButtons) {
      [button setEnabled:state];
   }
   self.onButton.enabled = !state;
   self.offButton.enabled = state;
}

- (void)viewDidLoad {
   [super viewDidLoad];
   [self setButtonsState:YES];
}

- (IBAction)toggleButtons:(id)sender {
   [self setButtonsState:sender == onButton];
}

- (void)dealloc {
   self.onButton = nil;
   self.offButton = nil;
   self.otherButtons = nil;
   [super dealloc];
}

@synthesize onButton, offButton, otherButtons;

@end

I can now easily wire this together in Interface Builder without the need to write any code to collect and store the references to my group of buttons. This is clearly a contrived example, but I hope you can see the benefit of this small addition to iOS 4.

[ 2 comments ]

Objective-C for Java Developers

by Bob McCune on August 10, 2010

I wanted to thank everyone who attended my Objective-C for Java Developers presentation at TCJUG tonight. It was odd giving a non-Java talk at TCJUG, but it was a lot of fun and I hope you found it useful. Objective-C is a fairly significant departure from Java but hopefully the presentation highlighted some areas of commonality and helped bridge some of the gaps.

The slides to the presentation can be found on the “Works” tab above.

[ 0 comments ]

iPhone Jam Session

by Bob McCune on April 8, 2010

Thanks to everyone who turned out for the iPhone presentation Chris Bartling and I gave at last night’s Jam Session! We had a great time talking about a fun topic. I hope you enjoyed it.

There were some questions about Apple’s approval process. I mentioned that I just submitted an app this past Saturday and said I didn’t know how soon it would be before it was given the thumbs up. I wish I had checked my email during the break as it was approved last night. That’s not too bad a turnaround time. Thanks Apple!

Thanks again and I hope I’ll see some of you at next month’s CocoaHeads.

[ 2 comments ]

CocoaHeads: We're Off To a Great Start!

by Bob McCune on June 16, 2008

I would really like to thank all of you who attended the inaugural CocoaHeads meeting last Thursday. I couldn’t have been happier with the turnout and participation from everyone. It was also nice to finally meet many of you with whom I’ve traded emails over the past couple of months.

We had a great mix of people at the first meeting ranging from experienced Cocoa, NeXT, and Mac OS developers to those experienced with other languages/platforms, but just starting out with Cocoa and CocoaTouch, to those just starting their journey into software development. This should make for a very interesting group!

Andy Atkinson started polling at the end of the meeting for what technical topics people would like to see at upcoming meetings. I think the final ones we settled on were:

  • Intro to iPhone Development
  • Overview of RubyCocoa
  • Unit Testing with OCUnit
  • NSFoundation Framework
  • Intro to CoreGraphics
  • Overview of Instruments

Some additional ones I would personally like to see covered (even if I’m the one covering them) are overviews of Core Data and Core Animation.
Let me know if there are any others that I missed and should be tracking.

John Shields wrote up a nice summary of his thoughts on the meeting that you should check out.

I’d like to thank Bill Heyman and Damon Allison for showing us some very cool demos of what they are doing over at CodeMorphic. Good luck guys and keep ‘em coming! If anyone else would be interested in demoing their products or projects, just let me know and I’ll find you a slot.

I’d also like to thank everyone at Synergy Information Services. Their facilities are great and they also have a larger room available should we need it. We all also greatly appreciated the pizza and soda!

Vlad will be posting the Getting Started with Cocoa presentation and sample code to the website. Keep an eye out at Synergy’s CocoaHeads Page over the next few days if you’d like to download that content.

BTW, if you are interested in understanding the history of Cocoa and Mac OS X, I’d recommend checking out David Shaw’s website. He has a wealth of information on NeXT, Rhapsody, and Apple that many of you would find very interesting. Great job David!

As I mentioned the other night I’ll be giving a presentation on Object-C 2.0 at the July meeting. This will be a much more detailed look at ObjC which will allow us to dig into its core syntax and features.

I hope to see you all again at the next CocoaHeads meeting on 7/10 @ 6pm.

-Thanks,
Bob

[ 4 comments ]

Over the weekend, I finished reading the 3rd edition of Cocoa Programming for Mac OS X by Aaron Hillegass. The previous edition had long been considered the best introduction to the topic, but it had grown rather out of date given the major changes introduced in the Leopard release of OS X. Thankfully, the 3rd edition has been completely revised to reflect the current state of Mac OS X development.

Cocoa Programming for Mac OS X is an introductory guide to programming on the Mac platform. It provides broad coverage of the core Mac programming concepts you’ll need to write real world applications, but is not intended to be a definitive reference on the subject. Aaron’s presentation of the material is excellent and the code examples really help explain the concepts being covered.

The organization of the book has changed considerably since the last release. Several less-relevant and irrelevant chapters have been dropped and replaced with chapters covering Core Data, Core Animation, web services, and garbage collection. Additionally, the existing content and examples have been significantly revised giving this release the feel of a whole new book.

I would highly recommend this title to anyone interested in Mac development. Even if you own the previous edition, I think you’ll find the new and revised content well worth the price.

[ 3 comments ]

  • Page 1 of 2
  • 1
  • 2
  • >