Showing posts with label Tricks. Show all posts
Showing posts with label Tricks. Show all posts

Mac Tips and Tricks

Get all Mac OS X Tips, Tricks, Tutorials, Hacks, Support, Downloads, Updates...right in to your Mac OS X Mountain Lion, Lion, Snow Leopard, Leopard or Tiger Dashboard !
Learn How To using Finder, Preview, iChat, iCal, Mail, Safari, Address Book, Expose, Dock, Dashboard, Spotlight, Keyboard Shortcuts...or Customizing Your Mac !
↓ Download

Split View Controller

This is known as a split view controller, where there is a view controller on the left that takes up about 30% of the space, and a view controller on the right that takes up 70% of the screen estate.

In portrait mode, there is a button to tap which brings up a view controller known as a Popover Controller. This PopoverController is the exact same controller that was on the left in the previous slide.

Let’s start off first with a Split View Controller. We simply create it as usual, and then set the viewControllers property to an array of view controllers. Take note that we should only have two view controllers here.

Create split view controller
UISplitViewController* splitVC = [[UISplitViewController alloc] init];

Set viewControllers 
splitVC.viewControllers = [NSArray arrayWithObjects:firstVC, secondVC, nil];

For the popover controller, it is slightly different. We have to create the controller with an already existing view controller and set the delegate. Furthermore, we need to have a custom property that contains this popoverController.
After which, we can present the popover from a UIBarButtonItem or a rectangle. In here, permittedArrowDirections means which way the arrow of the popovercontroller can point.

Create Popover Controller/set delegate
UIPopoverController* aPopover = [[UIPopoverController alloc] initWithContentViewController:content];
aPopover.delegate = self;

Set in custom property
self.popoverController = aPopover;

Present controller
[self.popoverController presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];

[popoverController presentPopoverFromRect:CGRectMake(0,0,100,100) inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];


As mentioned earlier, the view controllers in the split view controller and the popover controller are the same. We have to do a bit of extra work to ensure all is smooth. Let’s first take care of it when the iPad rotates from a landscape to a portrait orientation. Firstly, the delegate method, willHideViewController withBarButtonItem forPopoverController will be called. In here, we have to point the UIBarButtonItem which has been created by the method and set it to our popoverController property which we have. This is where the property comes into use.

Supporting Orientation Changes
// Called when rotating to a portrait orientation. 

- (void)splitViewController: (UISplitViewController*)svc willHideViewController:
(UIViewController *)aViewController withBarButtonItem: (UIBarButtonItem*)barButtonItem forPopoverController: (UIPopoverController*)pc{

barButtonItem.title = @"Root List"; 
NSMutableArray *items = [[toolbar items] mutableCopy]; 
[items insertObject:barButtonItem atIndex:0]; [toolbar setItems:items animated:YES]; 
[items release]; 
self.popoverController = pc;
}

When we rotate it back to the landscape position, we do the exact opposite, by removing the UIBarButtonItem and setting the popoverController to be nil.

Supporting Orientation Changes
// Called when the view is shown again in the split view, invalidating the button and popover controller.

- (void)splitViewController: (UISplitViewController*)svc willShowViewController: (UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem
*)barButtonItem {

NSMutableArray *items = [[toolbar items] mutableCopy]; 
[items removeObjectAtIndex:0]; 
[toolbar setItems:items animated:YES]; 
[items release]; 
self.popoverController = nil;
}

UITouch

Let’s have a look at touchesBegan. When touchesBegan is called, it returns an event. We can call allTouches to get the touches and then locate the first touch. Each touch has many properties, including tapCount, timeStamp and the view it was contained in. We can manipulate these to create whatever desired action we want.

Touches
-(void) touchesBegan: (NSSet *) touches withEvent: (UIEvent *) event { NSSet *allTouches = [event allTouches];
//first touch
UITouch *touch = [[allTouches allObjects] objectAtIndex:0];


Understanding each touch
tapCount
timeStamp
view


Gesture Recognizers
If you want to detect gestures, there’s an app for that. But you have to build it. However, Apple has created recognizers called UIGestureRecognizers which save lives. You can easily detect motions and gestures such as tapping, pinching, panning, swiping, rotating, and long presses. They are extremely easy to add and customize, and include delegates for further customization.

UIGestureRecognizer
UITapGestureRecognizer *doubleFingerDTap =
[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleDoubleTap:)];

Add to view
[self.view add doubleFingerDTap];

Let’s look at how we can use them. First we create the UIGestureRecognizer, in this case, we use a UITapGestureRecognizer.
We add it to the view, and implement the delegate if we want. Now, the delegate has important methods such as requiring other gesture recognizers to fail. For instance, if you have a singleTapGestureRecognizer and a doubleTapGestureRecognizer, you would need the double tap gesture to fail before recognizing the single tap. That means, you will have to wait for a few seconds to confirm that it is not a double tap, before performing the single tap action.

MapKit

CoreLocation
CLLocation represents a point or vector and can be detected by several methods (GPS, Wi-Fi, Cell Towers). Of course, it uses Skyhook technology to retrieve accurate location results. Each CLLocation consists of properties such as the coordinate itself, altitude and timestamp.

CLLocationManager
There is a manager for all our CLLocations, and it helps to start or stop the location service. There’s also an included delegate which you may choose to use for location changes.

MapKit
MapKit is how we can use Google Maps in our apps. The class MKMapView helps to display maps, satellite images or hybrid images. Annotations which are based on CLLocations can also be added to the map. MKMapView also has a delegate that helps to detect when it is zoomed or panned.

MKMapView
For MKMapView itself, it has a couple of properties, such as the region, centerCoordinate, mapType and annotations.

MKAnnotation
Annotations are pins which you can add in Google Maps. It has properties such as title and subtitle, which are entirely customizable. MKPlacemark which is based on MKAnnotation, goes a step further and converts human readable addresses to annotations. So if you create an MKPlacemark with a postal code, it will automatically map itself on the MKMapView.

Webkit

Webkit. Webkit is predominantly used in most apps, and is used for displaying webpages within your own app, without leaving the app to go to Safari to view a site.

WebKit includes UIWebView, which is used for displaying web content. It can take in HTML, MIME + data, or a URL.

UIWebView
//Load data
- (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL; - (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL; - (void)loadRequest:(NSURLRequest *)request;
//Common action methods
- (void)reload; - (void)stopLoading; - (void)goBack; - (void)goForward;
//Useful properties
@property BOOL scalesPageToFit; @property BOOL detectsPhoneNumbers;



It is very simple to use a UIWebView. We first create the object and we can start loading the data. There are several action methods you might want to take note, such as reload, stopLoading, etc. There are also properties which are useful such as scalesPageToFit, which scales it on the first load, and detectsPhoneNumbers, which detects all phone numbers in the page to make them tappable. And when you tap on these numbers, your iPhone automatically.

UIWebViewDelegate
There is also a delegate which you may wish to implement, and it brings about many interesting methods such as failing to load, link clicked, form submitted, and many more.

Accelerator

The accelerator in the iPhone and iPad can tell you the device orientation. But before that, we need to understand the two types of orientation: device orientation and interface orientation. The device orientation can be portrait, landscape, faceUp, faceDown, and so on. It reflects how the iPhone or iPad itself is currently positioned. The interface orientation, tells us how the screen is being shown. The bar that contains the device’s battery life and shows us the time is called the status bar. Interface orientation basically means the status bar orientation, which can be Portrait, PortraitUpsideDown, LandscapeLeft or LandscapeRight.

Device Orientation
[[UIDevice currentDevice] orientation]

Start notifications
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]

Receive notifications
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didRotate:)
name:@"UIDeviceOrientationDidChangeNotification" object:nil];


To retrieve the device orientation, we can call UIDevice currentDevice orientation. If we want to be notified of updates, we need to make use of the NSNotificationCenter. First we have to tell the device to begin generating device orientation notifications, then set up Notification Center to start listening for updates. When we want to stop the updates, we can simply call endGeneratingDeviceOrientationNotifications on the UIDevice currentDevice.

Detecting Shakes
To detect shakes in any iOS device, we first need a custom UIView to detect shakes in. After which, we call becomeFirstResponder on the shakeView in the viewWillAppear and viewWillDisappear methods, to ensure that the shakeView will be the first to be notified of such events. We need to then implement the method, motionEnded, and handle the shake within. This is how we can detect shakes.

Add [shakeView becomeFirstResponder] in viewWillAppear and viewWillDisappear

@implementation ShakingView
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event{ if ( event.subtype == UIEventSubtypeMotionShake ){
// Handle shake here
}
if ( [super respondsToSelector:@selector(motionEnded:withEvent:)] ) [super motionEnded:motion withEvent:event];
} - (BOOL)canBecomeFirstResponder{ return YES; } @end

UIImagePickerController

Let’s dive into the hardware of the iPhone and iPad, both of which now have a camera.

UIImagePickerController
The default use of a camera in iOS applications is the UIImagePickerController. You can take pictures from the Photo Library, Saved Photos, or Camera itself.
There are certain steps you need to take when you want to implement UIImagePickerController into your apps. First off, you need to check the source availability. Some devices do not have cameras, and thus this step is crucial (although Apple does check for you as well, it is good to check it yourself to be sure). Next step is to set the source type, which is where you want to select the photos from, be it the camera or photo library or saved photos. After which, you would want to set properties such as the media types, photo or video. Finally, you assign the delegate to yourself and present the controller modally. Take note that these controllers are always modally presented.

//Check source availability
if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera])
{
//Create UIImagePickerController
UIImagePickerController* picker = [[UIImagePickerController alloc] init];

//Set image picker source
picker.sourceType = UIImagePickerControllerSourceTypeCamera;

//Set image picker media types
picker.mediaTypes = [NSArray arrayWithObjects: (NSString *) kUTTypeMovie, (NSString *) kUTTypeImage, nil];

//Set image picker delegate
picker.delegate = self;

//Present image picker
[self presentModalViewController:picker animated:YES];
}

* Add MobileCoreServices.framework or
 #import <MobileCoreServices/UTCoreTypes.h>

First off, we check the source availability by calling isSourceTypeAvailable. Next we create the UIImagePickerController, set the source and mediaTypes. For mediaTypes we create an array that includes both Movie and Image, in this case. Make sure you add the MobileCoreServices framework and import the UTCoreTypes file first.
Finally, we set the delegate to the view controller and present it modally.

There are many properties you might want to take note of while writing for your iOS apps, such as whether to use the rear or front camera, the quality of media, and whether you want to use flash or not.


UIImagePickerControllerDelegate
After implementing all of the above, you still need to implement the delegate methods as well. Your final images or videos will be stored in an NSDictionary that is returned in the imagePickerController didFinishPickingMediaWithInfo. Here is where you would want to store the images somewhere, and then dismiss the controller. There’s also a cancel method if the user chose to cancel taking a photo instead.

Contains your original and edited images (save them!)
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info; 

Dismiss controller here
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker;

After implementing all of the above, you still need to implement the delegate methods as well. Your final images or videos will be stored in an NSDictionary that is returned in the imagePickerController didFinishPickingMediaWithInfo. Here is where you would want to store the images somewhere, and then dismiss the controller. There’s also a cancel method if the user chose to cancel taking a photo instead.

Saving Media
To save media, we have to use the following methods, UIImageWriteToSavedPhotosAlbum, and UISaveVideoAtPathToSavedPhotosAlbum. For videos, you need to check if the path is compatible to be saved in.

UIImageWriteToSavedPhotosAlbum

Optional completion callback 
UIVideoAtPathIsCompatibleWithSavedPhotosAlbum 
UISaveVideoAtPathToSavedPhotosAlbum


Augmented Reality
If you want to use augmented reality in your apps, you definitely can. The few properties that you should be looking at are showsCameraControls, cameraOverlayView, and cameraViewTransform. A third party kit that was recently developed is available for free to incorporate into your apps at www.iphonear.org.

ARKit (http://www.iphonear.org)
showsCameraControls
cameraOverlayView 
cameraViewTransform

Web Services XML or JSON

Most web services are exposed via RESTful interfaces such as XML or JSON.

XML
XML looks like this. Basically it starts off with the version number, and then a dictionary or array within. This dictionary or array can contain even more dictionaries and arrays or any other objects. The next thing we have to do is to parse through this message.

<?xml version="1.0"?> <note>
<to>Steve</to> <from>Paul</from> <message>Have a good weekend!</message>
</note>



XML Parsers
There are two types of XML parsers, the DOM and SAX parsers. The DOM notifies you when it runs through the tree. A SAX parser reads and builds up an in-memory representation of the XML. Both has its advantages and disadvantages.

Many to choose from (C / Obj-C)
NSXML, 
libxml2
TBXML
TouchXML
KissXML
TinyXML
GDataXML

Advantages/drawbacks
Validation
XPath

For the parser itself, we have many to choose from. The included parsers are NSXMLParser and libxml2 parser. The rest are created by third-party developers and have proven to work. Each parser, again has its own advantages / disadvantages to watch out for, such as validation of each step as it parses through the XML, and also XPath which functions as an index.


NSXMLParser
Let’s run through the included XML parser, NSXMLParser. The first thing you have to do is to create the parser, set the delegate to self, and any properties you may wish to set. During the creation of the XMLParser, be sure to init with whatever XML you have.

Create parser/set delegate & properties
NSXMLParser *parser = [[NSXMLParser alloc] initWithURL:myURL];
parser.delegate = self;
parser.shouldProcessNameSpaces = NO;

Parse
[parser parse];

Receive from delegate methods
 - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI: (NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI: (NSString *)namespaceURI qualifiedName:(NSString *)qName 
 - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string


JSON
Another form of RESTful interface is JSON, which is Javascript Object Notation. Here’s how the same message looks like in JSON. This is more human-readable, according to many.
To parse JSON, we can use a third-party JSON framework, called SBJSON. SBJSON was created by Stig Brautaset. It was originally named JSON-framework but renamed soon after to SBJSON.


SBJSON
To use SBJSON, we simply download, drag and copy into our own project. If you are using XCode 4, you might want to check out how to link projects instead of copying them over. The instructions are a bit more complicated, but are also found in the same SBJSON link.
The next thing we need to do is to import JSON.h, create the SBJSON parser, and then parse it into an NSDictionary. If we do not know what the final object is, we can simply use the id type. Download, drag and drop, copy into folder.

Import/create/parse
#import “JSON.h”
SBJSON *parser = [[SBJSON alloc] init];
NSDictionary *object = [parser objectWithString:json_string error:nil];

NSUserDefaults

There are a few ways we can persist data on the iPhone. The first one is to store data securely. We can make use of the Keychain framework that Apple has provided.
NSUserDefaults is another way of storing data, but for non-sensitive info such as user settings which do not need to be encrypted. NSUserDefaults will be further explained in the next slide.

Set a value
[[NSUserDefaults standardUserDefaults] setObject:myValue forKey:myKey];

Retrieve a value
[[NSUserDefaults standardUserDefaults] objectForKey:myKey];

Synchronize
[[NSUserDefaults standardUserDefaults] synchronize];

NSUserDefaults is a simple way of storing non-sensitive data. We can set a value by calling NSUserDefaults standardUserDefaults set Object. Basically, it works like an NSDictionary. You can easily set and retrieve values.
However, this time round, you need to synchronize. Synchronize basically works like a save. After changing variables, you might want to call synchronize to save NSUserDefaults. NSUserDefaults saves every now and then, but to make sure you can simply call synchronize.