There are many reasons for you to use method swizzling, even if it’s considered harmful and dangerous.
Despite it’s flaws, this little technique can be so powerful and let you reveal secrets of iOS like status bar is drawn by the current app, and replace methods in class you don’t own like customizing UINavigationBar background in old days to achieve a higher level of UI customisation.
So here’s the base snippet:
Example usage:
@implementation NSParagraphStyle (JTParagraphStyleDebug)
+ (void)load {
SwizzleInstanceMethod([self class], @selector(initWithCoder:), @selector(initWithCoderSwizzled:));
}
// -[NSParagraphStyle initWithCoder:] is called when an NSAttributedString is specified in an UILabel in Interface Builder.
- (id)initWithCoderSwizzled:(NSCoder *)aDecoder {
self = [self initWithCoderSwizzled:(id)[[UINibDecoderProxy alloc] initWithTarget:aDecoder]];
return self;
}
@end
Above code is extracted from JTAttributedLabel to use UINibDecoderProxy to diagnose NSAttributedString in Interface Builder.
Enjoy and have a good use with it!

In Xcode 4, you can simply point-and-click to specify supported orientation in your info.plist. But wait, it doesn’t really make your app obey to that certain interface orientation.
You still have to implement the - [UIViewController shouldAutorotateToInterfaceOrientation:] and return a right value.
Your specified value is located in your app’s info.plist, so here’s the code to let you easily access that configuration.
Example usage
// In your ViewController.m subclass that you wish to just obey the specified supported orientations,
// #import "UIApplicationAddition.h"
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return UIInterfaceOrientationIsSupportedOrientation(interfaceOrientation);
}
Now you can just point-and-click to really change the supported orientations!
Tired of Target-Action? Welcome to the world of blocks.
Sample usage:
UIButton *button = ...;
[button addEventHandler:^(id sender, UIEvent *event) {
NSLog(@"touchedUp!");
} forControlEvent:UIControlEventTouchUpInside];
This is a very simple implementation of adding block support for UIControls. Download the snippet from here, instantly saves you a few lines of code.
If you are finding for a more complex block addition of everything, you maybe interested to have a look at zwaldowski / BlocksKit.
Say you’d like to split an array into several arrays each with a specific number of components.
// Say your originalArray is [@"A", @"B", @"C", @"D"]
NSArray *originalArray = [NSArray arrayWithObjects:@"A", @"B", @"C", @"D", nil];
// And we now want the array to be split into two arrays with two per segment
// like this [[@"A", @"B"], [@"C", @"D"]]
NSArray *newArray = [NSArray splitArray:originalArray componentsPerSegment:1];
And here’s the code snippet on how you can do it.
//
// NSArray+JTArraySplit.h
//
// http://ioscodesnippet.tumblr.com
//
#import <Foundation/Foundation.h>
@interface NSArray (JTArraySplit)
+ (NSArray *)splitArray:(NSArray *)targetArray componentsPerSegment:(NSUInteger)componentsCount;
@end
//
// NSArray+JTArraySplit.m
//
// http://ioscodesnippet.tumblr.com
//
#import "NSArray+JTArraySplit.h"
@implementation NSArray (JTArraySplit)
+ (NSArray *)splitArray:(NSArray *)targetArray componentsPerSegment:(NSUInteger)componentsCount {
NSMutableArray *splitedArray = [NSMutableArray array];
NSUInteger targetArrayCount = [targetArray count];
if (targetArrayCount > 0) {
int index = 0;
while (index < targetArrayCount) {
int length = MIN(targetArrayCount - index, componentsCount);
NSArray *subArray = [targetArray subarrayWithRange:NSMakeRange(index, length)];
[splitedArray addObject:subArray];
index = index+length;
}
return splitedArray;
} else {
// no objects inside targetArray, so just return empty array
return splitedArray;
}
}
@end
Panther introduced Key-Value Observing, a Cocoa implementation of the observer pattern. It’s very useful, but the API kind of sucks.
To get observation notices, you have to override a lengthy selector (
observeValueForKeyPath:ofObject:change:context:), provide a static context pointer, and essentially implement a big switch statement on the key path.That’s unwieldy, but I think it also makes for unmaintainable code: the callbacks end up thrown in the same method, and they’re separated from the observer registration.
KVO+Blocks is an
NSObjectcategory I wrote which providesaddObserverForKeyPath:task:, where the latter parameter is a block.So, before KVO+Blocks:
const static NSString *SomeValueObservationContext = @"org.andymatuschak.SomeValueObservationContext"; - (void)registerObservation { [observee addObserver:self forKeyPath:@"someValue" options:0 context:SomeValueObservationContext] } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (context == SomeValueObservationContext && [keyPath isEqualToString:@"someValue"]) { NSLog(@"someValue changed: %@", change); } else { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } - (void)dealloc { [observee removeObserver:self forKeyPath:@"someValue"]; [super dealloc]; }And after:
- (void)registerObservation { [observee addObserverForKeyPath:@"someValue" task:^(id obj, NSDictionary *change) { NSLog(@"someValue changed: %@", change); }]; }Note that you don’t even need to unregister your observer if you’re using GC; it’s handled for you when the observee is released. If you want to unregister early, or you’re using retain-counted code, there’s API for that too.
Blocks make life happy, ladies and gentlemen. More on this later.
Update: more notes and gotchas.
If you’ve ever experience in loading lots of image in your app from the web, and display in a list form of UIImages in a table view, you’d properly heard of doing lazy loading those images. There are several great loading and caching open source solutions you’d probably already heard of such as SDWebImage, EGOImageLoading, etc.
However, you are still experience slight UI delay when the image finished loading or caching out from the disk. The reason behind is UIKit does extra lazy initialization, and only do expensive decompressing at the time to display or draw.
Here’s is code snippet meant to be load from a background thread that force an image to be decompressed into the right format, so that the system don’t have to do extra conversion on display.
//
// UIImage+JTImageDecode.h
//
// Created by james on 9/28/11.
// http://ioscodesnippet.tumblr.com
//
@interface UIImage (JTImageDecode)
+ (UIImage *)decodedImageWithImage:(UIImage *)image;
@end
//
// UIImage+JTImageDecode.m
//
// Created by james on 9/28/11.
// http://ioscodesnippet.tumblr.com
//
@implementation UIImage (JTImageDecode)
+ (UIImage *)decodedImageWithImage:(UIImage *)image {
CGImageRef imageRef = image.CGImage;
// System only supports RGB, set explicitly and prevent context error
// if the downloaded image is not the supported format
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL,
CGImageGetWidth(imageRef),
CGImageGetHeight(imageRef),
8,
// width * 4 will be enough because are in ARGB format, don't read from the image
CGImageGetWidth(imageRef) * 4,
colorSpace,
// kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little
// makes system don't need to do extra conversion when displayed.
kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little);
CGColorSpaceRelease(colorSpace);
if ( ! context) {
return nil;
}
CGRect rect = (CGRect){CGPointZero, CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)};
CGContextDrawImage(context, rect, imageRef);
CGImageRef decompressedImageRef = CGBitmapContextCreateImage(context);
CGContextRelease(context);
UIImage *decompressedImage = [[UIImage alloc] initWithCGImage:decompressedImageRef];
CGImageRelease(decompressedImageRef);
return [decompressedImage autorelease];
}
@end
So after an image has successfully loaded from the web or cached out, create an operation and decompress the image with
[UIImage decodedImageWithImage:anImage];
And now you can achieve a smoother scrolling experience for your app.
You can also download UIImage+JTImageDecode directly on gist or checkout the optimized mystcolor/SDWebImage library on github.
CGImageCreateWithImageInRect
That’s already defined in the Foundation framework. It is absolute fine for who already familiar well enough with CoreGraphics and doesn’t mind manually take care of the image orientation.
We loved UIKit anyway.
Use this UIImage+JTImageCrop category instead.
//
// UIImage+JTImageCrop.h
//
// Created by james on 9/8/11.
// http://ioscodesnippet.tumblr.com
//
#import <UIKit/UIKit.h>
@interface UIImage (JTImageCrop)
+ (UIImage *)imageWithImage:(UIImage *)image cropInRect:(CGRect)rect;
// define rect in proportional to the target image.
//
// +--+--+
// |A | B|
// +--+--+
// |C | D|
// +--+--+
//
// rect {0, 0, 1, 1} produce full image without cropping.
// rect {0.5, 0.5, 0.5, 0.5} produce part D, etc.
+ (UIImage *)imageWithImage:(UIImage *)image cropInRelativeRect:(CGRect)rect;
@end
// Used by +[UIImage imageWithImage:cropInRelativeRect]
CGRect CGRectTransformToRect(CGRect fromRect, CGRect toRect);
//
// UIImage+JTImageCrop.m
//
// Created by james on 9/8/11.
// http://ioscodesnippet.tumblr.com
//
#import "UIImage+JTImageCrop.h"
CGRect CGRectTransformToRect(CGRect fromRect, CGRect toRect) {
CGPoint actualOrigin = (CGPoint){fromRect.origin.x * CGRectGetWidth(toRect), fromRect.origin.y * CGRectGetHeight(toRect)};
CGSize actualSize = (CGSize){fromRect.size.width * CGRectGetWidth(toRect), fromRect.size.height * CGRectGetHeight(toRect)};
return (CGRect){actualOrigin, actualSize};
}
@implementation UIImage (JTImageCrop)
+ (UIImage *)imageWithImage:(UIImage *)image cropInRect:(CGRect)rect {
NSParameterAssert(image != nil);
if (CGPointEqualToPoint(CGPointZero, rect.origin) && CGSizeEqualToSize(rect.size, image.size)) {
return image;
}
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 1);
[image drawAtPoint:(CGPoint){-rect.origin.x, -rect.origin.y}];
UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return croppedImage;
}
+ (UIImage *)imageWithImage:(UIImage *)image cropInRelativeRect:(CGRect)rect {
NSParameterAssert(image != nil);
if (CGRectEqualToRect(rect, CGRectMake(0, 0, 1, 1))) {
return image;
}
CGRect imageRect = (CGRect){CGPointZero, image.size};
CGRect actualRect = CGRectTransformToRect(rect, imageRect);
return [UIImage imageWithImage:image cropInRect:CGRectIntegral(actualRect)];
}
Now you use this instead of the CoreGraphics method.
+ (UIImage *)imageWithImage:(UIImage *)image cropInRect:(CGRect)rect;
Last but not least, you’d somehow want to further abstract it with a proportional rect value. (Imagine you are defining a cropping area on the screen and want to crop a full sized image, you’d transform the visible area to the full sized photo).
A handly method is also created for this purpose.
+ (UIImage *)imageWithImage:(UIImage *)image cropInRelativeRect:(CGRect)rect;
While you may be interested in more of it, go visit JTImageKit on GitHub! Documentations are raw right now, but welcome any comments!
Typically you like to do something like below when you wanted to remove a view from its parent view.
[myView removeFromSuperview];
Sometimes it’s not that please for a user to see an UI component disappearing suddenly. You’d then consider adding some transition effects, and here’s a little code snippet in the UIView+JTRemoveAnimated category for how you can get a fade out effect on view removal.
So from now on, you just needed to do this to fade out any UIViews
[myView removeFromSuperviewAnimated]