Monday, October 21, 2013

FlipViewUtils: iOS library for customized flip animation

iOS provides a lot of in-built transition styles from one view to another view such as instant change (using addSubView), default navigation controller transition from right to left, modal view transitions from top/bottom or flip transitions. Although the one feature which I needed in one of my project was flip transition where flip should initiate from a single component of current screen which should animate/enlarge/flip and complete transition to next ViewController seamlessly.

Watch the video for the effect what I am talking about.


For the same purpose, I wrote customized code for making such a type of transition possible. Then I took out the relevant code and made this static library which gives us the option of view controller navigation using customized flip animation. This library could be just added to any project and such an animation could be achieved with as little as 2 lines of code.

You can download it from here. The usage is described in the Readme on github and it includes a demo project as well for complete understanding of how to use it.

Tuesday, June 11, 2013

Apple’s WWDC 2013 Keynote: Highlights

So there you have it, the announcement of this year’s Apple Worldwide Developers Conference (WWDC) 2013. This year, Apple gave fair warning for ticket sales and the public responded by giving giving Apple it’s fastest sold out event ever: 71 seconds. Attendees came in from 66 countries and two-thirds of them are first-time attendees.

Everyone got something from the latest WWDC keynote address. We got a new, cylinder(!) Mac Pro (tell us if you love or hate the new design), and a new OS – OS X Mavericks (they ran out of cats), with higher responsiveness and longer battery life (it’s about time); Maps gets a second chance, users get a new password-management system for iCloud, Finder gets an update and more.
If you missed it, here is a quick recap of the highlights.

1. OS X Mavericks

So because of a dwindling supply of cats, the 10th OS version was named OS X Sea Lion , OS X Mavericks, and it promises to extend battery life and provide better responsiveness, hitting a 1.4x performance improvement over Mountain Lion.

App Nap

App Nap selectively assigns power to the thing that has your immediate attention and runs on OpenGL 4 for super-responsive graphics.

Timer Coalescing

Timer Coalescing lets the CPU power up from idle mode on lower energy needs, reducing CPU memory by 72%. Even Safari has a Power Saver option to help direct power to what is in the centre of your attention.
With shared memory resource cache and power saver, Safari kills the competition, and is said to be run on only one-third of the energy of Firefox.


Apart from being able to share links more easily via Linkedin and Twitter, Safari now sports a sidebar bookmark, which actually lets you go through your Reading List as you read.

Finder Tabs

Your Finder is going the way of Tabs, like how it is with major browsers these days. Rather than have so many windows, just open up all your files into multiple tabs.
Open windows can be merged into tabs with just one clicks and files can be transferred from one folder to another just by hovering over the tabs.

Tagging

Tagging is brought to the Mac. Save a document and give it a tag and have the tags turn up automatically on the sidebar. As tagging can now be done anywhere, including on files on the iCloud, all files with the same tags can be pulled up with a single click.
Users can assign multiple tags to the same document, making all their files easy to search and retrieve.

Multiple Display

Multiple Display support allow you to work on, multiple screens, even though only one device is physically connected, even if it means you are using Apple TV as one of your screens. Full screen spaces can be pulled from one display to the next and the dock and other menus will be displayed on each connected screen as well.

Password Management With KeyChain

Apple is taking it upon themselves to better safeguard and help their users better remember their passwords, account information, Wifi-networks and even credit card numbers with iCloud KeyChain. Safari auto-suggests passwords for you, and even extends this option to your logged-in credit card information.

Respond Via Notifications

They hit the jackpot this time with responsive notifications, allowing you to reply to notifications on your Mac, as if you were on the iPhone.
Reply straight to friends who are messaging you over messaging apps, delete emails as they come in (straight on the notification), reply Facetime calls with a text message (although I’m driving now doesn’t work) among others. All notifications are logged in, and will pop up when your machine wakes from sleep.

Smarter Calendar

You can now integrate your calendar with your Facebook calendar, but more importantly, setting up an event like a simple Lunch date, prompts the calendar to suggest places for you to dine in, gives you projected weather forecasts as well as suggestions on travel time (and when you should make a move).


Sounds like Google Now to me but hey, this one lets you send your information to our iPhone when you’ve got to go, so that’s a plus.

Smoother Maps

Apart from sending calendar events and suggestions to your iPhone, you can also send directions on the Map app to the iPhone from your Mac. This will show on your lockscreen and once you are in your phone, you are taken straight to navigation.
The Map app looks smoother and 3D rendering of the Flyover data looks stunning. Just give it a spin and rotate around the Eiffel Tower to have a look.

iBooks on Your Mac

iBooks is now available on the Mac, giving users access to 1.8 million books including interactive textbooks. The table of contents can be found at the bottom of the book title, and finding a page is as easy as scrolling through the pages at bottom of the book.
You can add notes in between, highlight important text and generate study cards from those marked passages for a highly interactive learning experience.

Macbook Air Lasts ‘Full Day’

I’ll keep it brief. Enhanced battery life. 4th generation Intel core processor. Haswell ULT. 40% faster graphics, dual GPU execution units. With all this, your Air can wake up in a second, or stay on standby for 30 days.
The 11” also got an extension in battery life, staying awake now for to 9 hours. 13” goes from 7 hour battery life to 12 hours. Good news for power users on the go. 11′ starts at $999 with 128GB; 13′ starts at $1099. Both start shipping today.


Mac Pro (Became a cylinder)

When, they innovate, they innovate. The new Mac Pro now only takes up one-eighth of the original volume and packs a power in its relatively tiny frame. Two times faster than the old Mac Pro, this new addition to the family has a ‘central thermal core’ running on 12-core Intel Xeon processor, Flash storage, supports 4K displays and is available only at the end of the year.
Prices yet to be announced. And oh yeah, you can hardly recognize it too.


iOS 7

Oh yes, we got a new mobile OS version and iOS 7 promises new features (Control Center, Airdrop for iOS, smarter multitasking etc) that you shouldn’t miss and new designs as well. Siri gets a new look, we’re getting iTunes Radio, and iOS comes to life in your vehicle.
I've devoted another post to just the enhancements done to iOS 7 just so you can get to the nitty-gritty details. So don’t miss out on that.

Monday, June 10, 2013

iOS 7

Apple iOS has gone through 6 versions and now we are getting iOS 7. Announced at the WorldWide Developers Conference (WWDC) 2013, iOS 7 aimed to please with its massive redesign and fancy new features. It’s time to quench those rumors and check out what iOS 7 (beta still) has for iOS users.


While developers play with the beta version of iOS 7, which will be released for iPhone 4, iPhone 5, iPad 2nd generation and above, iPad Mini, and the 5th generation iPod touch, let’s check out what made the cut, what got updated, and the juicy details behind this latest update to the world’s most advanced mobile operating system yet.

1. UI Redesign – Flat, Simplicity

iOS has been redesigned, from the app icons and colors to typography, buttons and the general outlook — everything is simple and clean. The homescreen wallpaper uses gyroscope hardware to give the background picture a parallax effect. As you move your device, you can clearly differentiate the homescreen layer from the app icon layers, and this works throughout the system.

Translucent design on the keyboard as well as system-wide (Mail, Messages, Calendar, Game Center) are present throughout the OS; you get a view of what is happening at the back. Swipes form the left edge of the device brings you to the previous menu or back to the previous webpage. Pages for app folders have also been implemented, perfect for your ton of gaming apps.

The Notification Center now works on the lockscreen and also has a new look. You can see today’s notifications, missed notifications or all notifications through the buttons at the top. Calendar events are accessible with a single swipe all the way to the top.

2. One-Swipe Access Control Center

Access settings and options in a heart beat with Control Center. Swipe from the bottom of the screen to access settings like WiFi, Bluetooth and also change brightness and control music playback.

Control Center also allows you quick access to a few apps like the camera and calculator. It also lets you turn on the flashlight, and since Control Center works on the lockscreen, you’ll be able to turn the light on to find things in the dark without the need of finding an app.

3. Smarter Multitasking

Orientation lock and volume slider are also on the Control Center. Multitasking now lets you peek at the apps which are opened. Slide through all the app previews and double tap on a preview to launch the app.

iOS 7 recognizes your app usage patterns, and will allocate more resources for your favorite apps even with other apps open helping you to improve battery life. It’s even intelligent enough to know that you’re going to use Instagram around lunch time and will allocate resources for that behavior.

There’s also Intelligent Scheduling that works with networks where it will only push updates for an app when you have a strong network connection.

4. Safari’s New user Interface

Browsing the Web on Safari now is better with its automatic full screen mode. As you scroll down through content, the address bar that you normally see will be minimized to only show the website name. The buttons at the bottom will also be hidden until you scroll up to reveal the controls.

The address bar doubles as a search bar with new features: typing in part of a word will show you the Top Hit and also shows other Google search suggestions.

You can now open unlimited tabs on Safari. Scrolling through multiple tabs looks like you’re scrolling through a file cabinet, where you can only see the top. Just tap on the website to open it, tap and hold to rearrange the tabs or swipe it to the right to close it.

iCloud Keychain that saves password throughout all your Apple products featured on the new OS X Maverick is also integrated to Safari for iOS. Shared links by your Twitter followers are also convieniently located next to the Reader tab which syncs throughout your other devices.

5. AirDrop Sharing Between iOS Devices

AirDrop is now available for transfers between iOS devices via peer-to-peer WiFI connection. Turning on the Share Sheet on an app, you can find users who are nearby and tap items to share. A notification will appear on their device and when they open it, it will open to the relevent app and show the content that you shared.

Since it uses new hardware, AirDrop only works on the iPhone 5, 4th-gen iPad, iPad mini, 5th-gen iPod Touch.

6. Quick Camera, Geo-sorted Albums

The camera app now comes with 4 features accessible by left or right swipes: Videos, Photos, Photos in a square frame (for instagram) and Panorama pictures. New filters have also been added to the camera app on top of the basic editing features that is already available.

The Photos app also auto organizes your photos into moments based on location and date. It shows the location name and date when you first enter the Photos app. You can then pinch to zoom out and view collections where it sorts by locations only.

Zooming out again then shows you the photos taken, sorted by year. It can roughly tell you highlights of each year like you visiting another country for holiday. You can then tap, hold and swipe your finger across the small pictures for a quick view.


7. Siri & iOS In The Car

Siri is now smarter with integrated Wikipedia and Bing support built in for your search queries. There’s also Twitter where Siri can check out what your friends are saying. Other than Siri’s new look with the soundwave, it now shows results in a cleaner way.

Siri now also has a male voice, and can speak to you in French or German (more languages coming soon). Voice commands are also available for actions like "play my last voicemail", "turn on Bluetooth" or "increase brightness".



Because of these voice commands that let you change settings on the system, Siri will be integrated into 12 car manufacturers in 2014, which leads to the new feature called iOS In The Car.

With the powerful voice commands, you can easily call someone, play music, get directions with Maps or have messages read to you without you having to look at the car’s center console or iOS device.


8. iTunes Radio & More Music Control

Apple now has its own Radio app similar to services like Pandora. It’s built into the new Music app where you can see featured stations or songs that are trending on Twitter. You can create your own stations based on music genre or your favorite artist and then share it with your friends.

While music is streamed to you, you can choose to "play more songs like this" or "don’t play this song" and it’ll intelligently tweak the playlists further.



It keeps track of all the songs that you listen to on the History tab so you can opt to purchase it later. iTunes Radio is also available on your Mac, PC or Apple TV and is free with ads unless you’re a iTunes Match subscriber.

With the Music app update, you can see all your purchased music, movies and TV shows over iCloud on your device. Landscape mode also shows you all your album covers where you can just tap on a cover to start listening to it.


9. More Features

Here are a few more interesting things that you might want to know about iOS 7.

The App Store has changed where you can look for apps based on age range and view popular apps around you. Apps now also auto-update.

FaceTime will also feature audio only calls together with the ability to block numbers so they can’t reach you over the phone, FaceTime or messages.




Find My iPhone has an update with Activation Lock. Even if someone disables Find My iPhone or wipes the entire device clean, they won’t be able to use it as your iCloud user ID is required to use your device.

Notification syncing is also a new feature where notifcations that you’ve cleared will be gone throughout all your devices.

Tencent Weibo will also see more integration on iPhone.

Also, 1500 new APIs will be released to developers to integrate all the cool new features and looks of iOS 7 to their apps, so expect more features to turn up when iOS 7 comes to your iDevices this fall.

Saturday, June 1, 2013

Using EventKit in iOS

What's EventKit?

It is a framework provided by Apple in iOS 4+ for integrating your iOS app with the built in calendar app (iCal). You are able to retrieve events from the calendar, as well as create, update and delete events.

The Simulator

Although there is no calendar application in the iOS simulator, you can still use it for EventKit development using some open source code such as this.

Fetching Events

Retrieving stored events from a users calendar is super simple. The only parameters you need to specify is a date range and the calendar you want to query.

EKEventStore *eventStore = [[EKEventStore alloc] init];

NSDate *startDate = [NSDate date];
NSDate *endDate   = [NSDate distantFuture];

NSPredicate *predicate = [eventStore predicateForEventsWithStartDate:startDate
                                                             endDate:endDate
                                                           calendars:nil];
                                                           
NSArray *events = [eventStore eventsMatchingPredicate:predicate];

Calendars within the Calendar app

The calendar app is made up of many calendars, e.g. Home calendar, Work calendar, Birthday calendar etc. Every event created must belong to a calendar, however some calendars are read-only.
You can retrieve the following calendar information in iOS 4:

EKEventStore *eventStore = [[EKEventStore alloc] init];

// Get all calendars
NSArray * calendars = [eventStore calendars];

// Get the default calendar
EKCalendar * calendar = [eventStore defaultCalendarForNewEvents];

// Test if calendar is read-­‐only
[calendar allowsContentModifications];

// Get the associated colour of a calendar
[UIColor colorWithCGColor:calendar.CGColor];

Inserting Events

As the following code illustrates, inserting an event to a users calendar is also fairly simple.

EKEventStore *eventStore = [[EKEventStore alloc] init];

EKEvent *event  = [EKEvent eventWithEventStore:eventStore];
event.calendar  = [eventStore defaultCalendarForNewEvents];
event.title     = @"WWDC";
event.location  = @"San Francisco";
event.notes     = @"Apple Developer Conference";
event.startDate = startDate;
event.endDate   = endDate;
event.allDay    = YES;

[eventStore saveEvent:event span:EKSpanThisEvent error:nil];

Inserting Events with EventKitUI

Instead of saving the created event directly into the event store, a better approach is to use EventKitUI which will allow the user visually check/modify an event before it is inserted.

EKEventStore * eventStore = [[EKEventStore alloc] init];

EKEvent * event = [EKEvent eventWithEventStore:eventStore];
event.title     = title;
event.location  = location;
event.startDate = startDate;
event.endDate   = endDate;
event.notes     = notes;

EKEventEditViewController *controller = [[EKEventEditViewController alloc] init];

controller.eventStore       = eventStore;
controller.event            = event;
controller.editViewDelegate = self;

[self presentViewController:controller animated:YES completion:nil];


If you use EventKitUI, remember to always set the editViewDelegate delegate, and implement a delegate method to handle the dismissal of the view controller window.

-(void)eventEditViewController:(EKEventEditViewController *)controller
         didCompleteWithAction:(EKEventEditViewAction)action {
    
    switch (action) {
       case EKEventEditViewActionCanceled:
           // User tapped "cancel"
           break;
       case EKEventEditViewActionSaved:
           // User tapped "save"
           break;
       case EKEventEditViewActionDeleted:
           // User tapped "delete"
           break;
       default:
           break;
    }
    
    [self dismissViewControllerAnimated:YES completion:nil];
}

Resources

Saturday, May 25, 2013

Custom Push in/out Transition Animation for Modal View Controllers

Implementing a custom transition animation for view controllers is not too difficult. Let's consider that we need to push from right/left when presenting a modal view controller, and then pushing out to the other direction when dismissing the dialog. The below mentioned UIViewController category serves this purpose for us.

@interface UIViewController (Transitions)

- (void) presentModalViewController:(UIViewController *)modalViewController withPushDirection: (NSString *) direction;
- (void) dismissModalViewControllerWithPushDirection:(NSString *) direction;

@end  

and the implementation:

#import "UIViewController+Transitions.h"

@implementation UIViewController (Transitions)

- (void) presentModalViewController:(UIViewController *)modalViewController withPushDirection: (NSString *) direction {
    
    [CATransaction begin];
    
    CATransition *transition = [CATransition animation];
    transition.type = kCATransitionPush;
    transition.subtype = direction;
    transition.duration = 0.25f;
    transition.fillMode = kCAFillModeForwards;
    transition.removedOnCompletion = YES;
    
    [[UIApplication sharedApplication].keyWindow.layer addAnimation:transition forKey:@"transition"];
    [[UIApplication sharedApplication] beginIgnoringInteractionEvents];
    [CATransaction setCompletionBlock: ^ {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(transition.duration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^ {
            [[UIApplication sharedApplication] endIgnoringInteractionEvents];
        });
    }];
    
    [self presentViewController:modalViewController animated:NO completion:nil];
    
    [CATransaction commit];
    
}

- (void) dismissModalViewControllerWithPushDirection:(NSString *) direction {
    
    [CATransaction begin];
    
    CATransition *transition = [CATransition animation];
    transition.type = kCATransitionPush;
    transition.subtype = direction;
    transition.duration = 0.25f;
    transition.fillMode = kCAFillModeForwards;
    transition.removedOnCompletion = YES;
    
    [[UIApplication sharedApplication].keyWindow.layer addAnimation:transition forKey:@"transition"];
    [[UIApplication sharedApplication] beginIgnoringInteractionEvents];
    [CATransaction setCompletionBlock: ^ {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(transition.duration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^ {
            [[UIApplication sharedApplication] endIgnoringInteractionEvents];
        });
    }];
    
    [self dismissViewControllerAnimated:NO completion:nil];
    
    [CATransaction commit];
    
}

@end

To use it, you import "UIViewController+Transitions.h" in your file and call the presentModalViewController:withPushDirection:
the direction parameter receives core animation transition sub-types such as kCATransitionFromRight.
You can download the category files from here and import to your project.

Enjoy...

Thursday, May 23, 2013

IPhone: Playing Basic Audio

This post is for beginner level programmers and hence I won't go into complex audio using OpenAL or Audio Queues. Today, we will just be playing short sounds (less than 30 seconds). This will be the easiest way to do audio if you don’t require any background/continuous music. However, the downfall of doing audio this way is only one audio file can be playing at a time.

Let's get started

Lets assume the two sounds we want to play are:
* drumSound.caf
* pianoSound.caf


Notice that both of the audio files have a .caf extension. This is the audio type all of your sound files must be in to be played by the iPhone. Luckily Apple has provided us a utility for converting audio to this format. You can read up on it here. It’s pretty straight forward, just open up a Terminal and type:

/usr/bin/afconvert -f caff -d LEI16 {INPUT} {OUTPUT}

where {INPUT} is the path to your input audio file and {OUTPUT} is the file you want it to save it to with a .caf extension.

Step 1: Adding Audio Files
Drag the required audio files to your Resources Folder inside of your project. Make sure you check the box to copy the files into your project’s directory.

Step 2: Add The AudioToolbox.framework to Your Project
Right Click on the Frameworks folder in your project and select Add -> Existing Frameworks. Search for AudioToolbox.framework and when found click Add.

Step 3: Add the Header Declarations
Open up your ViewController and add the following code into its .h file

#import


SystemSoundID drumSoundID;
SystemSoundID pianoSoundID;

@property(nonatomic) SystemSoundID drumSoundID;
@property(nonatomic) SystemSoundID pianoSoundID;


Now open up the .m file of the same ViewController and add the following code:
@synthesize drumSoundID, pianoSoundID;


Now add the following code in viewDidLoad method to initialize our sounds object.


NSString *drumPath = [[NSBundle mainBundle] pathForResource:@"drumSound" ofType:@"caf"];
CFURLRef drumURL = (CFURLRef) [NSURL fileURLWithPath:drumPath];
AudioServicesCreateSystemSoundID (drumURL, &drumFileID);

NSString *pianoPath = [[NSBundle mainBundle] pathForResource:@"pianoSound" ofType:@"caf"];
CFURLRef pianoURL = (CFURLRef) [NSURL fileURLWithPath:pianoPath];
AudioServicesCreateSystemSoundID (pianoURL, &pianoFileID);


The first line gets the path of the audio file. The next line converts the path to a CFURLRef. Finally, we load that audio file and associate it with the given sound ID. Notice we pass &drumFileID. This is a pass by reference and allows the AudioServicesCreateSystemSoundID method to modify this variable. We do the same thing to load the volley sound. Now, let’s play the sounds.

Step 4: Playing the Sounds
t’s actually quite simple to play the sounds we have loaded. Simply call the AudioServicesPlaySystemSound method and pass it the soundID of the file you want to play. So to play the drum sound, just call this method:


-(void)playDrumSound {
AudioServicesPlaySystemSound (drumFileID);
}


Same way we could play the other sound anytime depending on our requirement. This tutorial would help you in adding any basic audio to your project.

Wednesday, April 10, 2013

iOS 6 Pull-to-Refresh

A new feature in iOS 6, the pull-to-refresh control available for UITableViewControllers.
Some things to keep in mind with this new control are the following:
  • It’s only available for UITableViewControllers, not regular UITableView instances
  • Cannot customize the shape or design, only the tint color
  • Cannot be added via Interface Builder, only programmatically
These may change at some point in the future but for now you’ll have to work with them.
The best way to showcase this new control is to jump straight into Xcode and start a new project. Please do this and select the Master-Detail Application iOS template.

Click Next and use Refresher as the Product Name, enter your Organization Name and Company Identifier, make sure only iPhone is selected for Devices and only check the Automatic Reference Counting and Storyboards checkboxes.


Click Next one more time and select where to save the project.
The template is pretty standard, you have a storyboard file for iPhone with a Navigation Controller, a UITableViewController as its root controller and a UIViewController for when a cell is tapped in the table. You will also notice the appropriate subclasses for the table view controller and the view controller.
Open MasterViewController.m and delete all of the method implementations except for the following:
    • didReceiveMemoryWarning
    • numberOfSectionsInTableView:
    • tableView:numberOfRowsInSection:
    • tableView:cellForRowAtIndexPath:
    • prepareForSegue:sender: 
After you do this, go ahead and delete the _objects variable declared in the class extension and replace it with this property declaration:
 @interface MasterViewController ()  
 @property (strong, nonatomic) NSArray *objects;  
 @end  

You’re not going to let users add or remove items to the table in this project, only use the pull-to-refresh control to invert the sorting of the items. It’s for this reason that a property with a custom getter method will be easier to work with. Add this code inside your implementation block:

- (NSArray *)objects  
 {  
    if (!_objects)  
    {  
      _objects = @[@"Argentina", @"Australia", @"Brazil", @"Ecuador", @"England", @"Germany", @"Italy", @"Japan", @"New Zealand", @"United States"];  
    }  
    return _objects;  
 }  

This initializes the objects array with the names of some countries ordered from A-Z. Before running the project you need to make a few changes in order to use this property. Update the following methods as shown:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section  
 {  
    return self.objects.count;  
 } 
  - (UITableViewCell *)tableView:(UITableView *)tableView  cellForRowAtIndexPath:(NSIndexPath *)indexPath  
 {  
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];  
    cell.textLabel.text = self.objects[indexPath.row];  
    return cell;  
 }  
 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender  
 {  
    if ([[segue identifier] isEqualToString:@”showDetail”])  
    {  
      NSIndexPath *indexPath = [self.tableView  indexPathForSelectedRow];  
      [[segue destinationViewController] setDetailItem:self.objects[indexPath.row]];  
    }  
 }  

All you’re doing here is using the property instead of the instance variable. This will, if necessary, create the objects array with the preloaded list of countries.
Go ahead and run the project on a device or the simulator and check out the results:

Sweet, the table view is looking just as expected albeit without any pull-to-refresh. How about tackling that next?
Go back to MasterViewController.m and add the following implementation for viewDidLoad:
- (void)viewDidLoad  
 {  
    [super viewDidLoad];  
    UIRefreshControl *refreshControl = [[UIRefreshControl alloc]  init];  
    refreshControl.tintColor = [UIColor magentaColor];  
    self.refreshControl = refreshControl;  
 }  

As mentioned before, the UIRefreshControl has to be created programmatically. You do the standard alloc and init, set the tint color (this is optional but I wanted to show you that it can be done) and assign it to the table view controller’s refreshControl property.
Run the project one more time and pull the table view down:
Things are looking good. But, umm, the activity indicator never really stops!
This is because you need to respond to the valueChanged control event on the refresh control. To do this, update viewDidLoad as follows:
 
- (void)viewDidLoad  
 {  
  [super viewDidLoad];  
  UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];  
  refreshControl.tintColor = [UIColor magentaColor];  
  [refreshControl addTarget:self action:@selector(changeSorting) forControlEvents:UIControlEventValueChanged];  
   self.refreshControl = refreshControl;  
 } 

And to avoid a runtime crash when you pull-to-refresh, stub out the changeSorting method:

 - (void)changeSorting  
 {  
 } 

Once again run your project. Notice how you are still getting the endless activity indicator. To fix this, add the following property declaration in your class extension:

  @property (assign, nonatomic) BOOL ascending;  

And add this code to changeSorting:

- (void)changeSorting  
 {  
   NSSortDescriptor *sortDescriptor = [[NSSortDescriptoralloc] initWithKey:nil ascending:self.ascending];  
   NSArray *sortDescriptors = @[sortDescriptor];  
   _objects = [_objects sortedArrayUsingDescriptors:sortDescriptors];  
   _ascending = !_ascending;  
   [self performSelector:@selector(updateTable) withObject:nil afterDelay:1];  
 }  

This code uses a sort descriptor to change the sort order of the array by using the BOOL property created a second ago. You also call a method named updateTable with a small delay that will handle reloading the table data and setting the refresh control to stop updating.
Add the implementation for that private method as shown:
 - (void)updateTable  
 {  
    [self.tableView reloadData];  
    [self.refreshControl endRefreshing];  
 } 

Go ahead and run the project one more time, pull the table view down and notice how the list of countries is now using the reverse sort order!





Saturday, January 5, 2013

Listing the Fonts Available in iOS


iOS 5.0 was a huge update in many ways and one of them is built-in font selection. For the first time ever, iPhone and iPad have exactly the same fonts! Many times, we need to know the list of available fonts in iOS, sometimes to display to end-user so that he can write any text in custom font or sometimes to know ourselves the available fonts which we can use. Since Apple is always adding to the available fonts with each iOS release, the best way to know what fonts you can use is to query the iOS for available fonts under the UIFont class.Here is an excellent bit of compact code to print out the available fonts to your console.

NSMutableArray *fontNames = [[NSMutableArray alloc] init];
NSArray *fontFamilyNames = [UIFont familyNames];
for (NSString *familyName in fontFamilyNames) {
    NSLog(@"Font Family Name = %@", familyName);
    NSArray *names = [UIFont fontNamesForFamilyName:familyName];
    NSLog(@"Font Names = %@", fontNames);
    [fontNames addObjectsFromArray:names];
}

Fonts are part of a font family, and the UIFont class returns a list of all of the font families available in iOS as well as the fonts under each font family. The code above first gets a list of all the font families, and then a list of all the fonts under each family, printing those font names out to the console.