Share
Embed
Real Life iOS Coding: a Journey Down the iOS Development Lane
When developing iOS apps, you'll have to overcome some small and major challenges. We'll take a short excursion into the real problems and solutions faced by an iOS developer. This journal-like trip will also share some tips and tricks and a small showcase of real life coding based on projects developed by the Milan-based digital agency Mutado.
(Italian video available at: http://vimeo.com/29137002 )
Luca Bernardi
May 08, 2012
Transcript
27 slides
-
@”Hello, WhyMCA!” •Luca Bernardi •Works as iOS Developer @ Mutado
•Currently taking my Master Degree in Computer Science •Stay in touch: •[email protected] •http://lucabernardi.com •@luka_bernardi -
What we are talking about •Essentially Tips&Trick and small snippet
of code based on my experience -
Enhanced Logging Function •The DLog macro take advantage of __PRETTY_FUNCTION__
and __LINE__ to print the function name and the line in where the macro is called •The macro definition depends on a compiler flag -DDEBUG •You can define the flag in “debug” build config and remove in “release” #ifdef DEBUG # define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); #else # define DLog(...) #endif -
[UIView recursiveDescription] •UIView undocumented API: -(NSString *)recursiveDescription; •Apple have talk
about it in the tecnical note “iOS Debugging Magic” •http://developer.apple.com/library/ios/#technotes/tn2239/_index.html •Returns an NSString describing the entire view hierarchy rooted at the receiver -
[UIView recursiveDescription] •Output Example: NSLog(@"\n%@", [self.window recursiveDescription]); <UIWindow: 0x4d14330; frame
= (0 0; 320 480); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x4d143e0>> | <UILayoutContainerView: 0x4d13b40; frame = (0 0; 320 480); autoresize = W+H; layer = <CALayer: 0x4d13b90>> | | <UINavigationTransitionView: 0x4d13ee0; frame = (0 0; 320 480); clipsToBounds = YES; autoresize = W +H; layer = <CALayer: 0x4d16200>> | | <UINavigationBar: 0x4d14c20; frame = (0 20; 320 44); clipsToBounds = YES; opaque = NO; autoresize = W; layer = <CALayer: 0x4d14e50>> | | | <UINavigationItemView: 0x4d14010; frame = (160 8; 0 27); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x4d14e00>> -
[UIView recursiveDescription] •Is a private API therefor remember to remove
before submitting the App to Apple •Generate a Warning. You can remove it with a Category: @interface UIView (privateAPI) - (NSString *)recursiveDescription; @end -
Use Clang Static Analyzer ! •The Clang Static Analyzer is
source code analysis tool that finds bugs in C and Objective-C programs •The Clang Static Analyzer can find bug like: •Memory Leak •Dead store •Using uninitalized or released variables •... •Early discovery of bugs •you have the chance to find bug while your hacking on code and not a month after -
Use Clang Static Analyzer ! •Since Xcode 3.2 Clang Static
Analyzer is integrated with Xcode -
Use Clang Static Analyzer ! •Why don’t static analyze at
every build? •Xcode has a build option to run Clang Static Analysis tool on every build •Slow down a bit the build processes •False Positives can occours -
You can’t ignore memory warning •When memory dips below a
safe threshold iOS notifies all running applications with a memory warning •In your application the following things happen: •The applicationDidReceiveMemoryWarning: method is called in your app delegate •The UIApplicationDidReceiveMemoryWarningNotification is posted •Each view controller calls its didReceiveMemoryWarning method -
•Focus on what happens in your in view controller AKA
unload cycle : •[UIViewController didReceiveMemoryWarning] invokes [self setView:nil] •Only if view.superview is nil = the view isn’t visible •Then the viewDidUnload method is called You can’t ignore memory warning -
•You should: •in didReceiveMemoryWarning release: •cached and image data •Data
structures associated with your view controller •in viewDidUnload method: •relinquish ownership of outlets calling the accessor method to set outlets to nil •release data that is not needed when your view is not visible •Keep a meaningful logic between viewDidLoad and viewDidUnload You can’t ignore memory warning -
•iOS Simulator uses all available memory on your Mac •iOS
Simulator can fake a memory warning •Hardware > Simulate Memory Warning •Memory warning handling can’t be a feature but must be a requirement •Always keep in mind your view controller lifecycle You can’t ignore memory warning -
Image and Video to the Cloud •What’s wrong with Image
and Video? •Photos taken with the iPhone’s camera use the industry-standard EXIF orientation flag to store rotation information •That means that the image data is always saved like the iPhone was in Landscape Right -
Image and Video to the Cloud •If you send the
picked image to server side script that doesn’t take care of EXIF flag strange thing happens. •You need to pre-rotate the image before send it to you remote server •https://gist.github.com/968154 -
Image and Video to the Cloud •The same happens to
picked video •iOS stores the iPhone’s orientations when the rec button is tapped •Orientation is not stored as exif flag •You need to read the video transformation matrix in order to know the rotation •Don’t process the video on iPhone but tell to server the rotation -
Image and Video to the Cloud ! AVURLAsset *avAsset! !
= [[AVURLAsset alloc] initWithURL:self.video options:nil]; ! AVAssetTrack* videoTrack! = [[avAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; ! CGAffineTransform txf! ! = [videoTrack preferredTransform]; ! CGFloat videoAngleInDegree = RadiansToDegrees(atan2(txf.b, txf.a)); ! [avAsset release]; 1)http://iphonedevelopment.blogspot.com/2008/10/demystifying-cgaffinetransform.html 2)http://developer.apple.com/library/ios/#documentation/GraphicsImaging/Conceptual/ drawingwithquartz2d/dq_affine/dq_affine.html -
UIScrollView trick - The problem •I want an horizontal pagination
like in Mobile Safari App -
UIScrollView trick - The problem •UIScrollView with pagination enabled stops
at multiples of its frame width or height •But I want the scrollview’s subviews aligned in center -
UIScrollView trick - The solution •Make the UIScrollView width as
wide as the page content •Set the UIScrollView clipsToBounds to NO -
UIScrollView trick - The solution •We still have a problem:
if the user start dragging outside the scroll view it doesn’t scroll •Create a UIView subclass that will contain the UIScrollView and all it’s subviews •Will be as wide as the scrollable area •Will pass the touch down to UIScrollView -
UIScrollView trick - The solution •How can I “pass down”
the touch? •Obviously you need to have a reference to UIScrollView •You should override - (UIView *)hitTest:withEvent: - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { ! ! ! if ([self pointInside:point withEvent:event]) { ! ! return scrollView; ! } ! return nil;! } -
One more thing... •Mutado always has a cup of coffee
for a mobile developer •Don’t be shy we are based in central Milan, C.so Sempione 10 •We are always looking for talented mobile developers •Drop your CV at [email protected]