Tuesday 29 April 2014

Toll-Free Bridged Types

There are a number of data types in the Core Foundation framework and the Foundation framework that can be used interchangeably. Data types that can be used interchangeably are also referred to as toll-free bridged data types. This means that you can use the same data structure as the argument to a Core Foundation function call or as the receiver of an Objective-C message invocation. For example, NSLocale (see NSLocale Class Reference) is interchangeable with its Core Foundation counterpart, CFLocale (see CFLocale Reference).
Not all data types are toll-free bridged, even though their names might suggest that they are. For example, NSRunLoop is not toll-free bridged to CFRunLoop, NSBundle is not toll-free bridged to CFBundle, and NSDateFormatter is not toll-free bridged to CFDateFormatter. Table 1 provides a list of the data types that support toll-free bridging.


The compiler does not automatically manage the lifetimes of Core Foundation objects. You tell the compiler about the ownership semantics of objects using either a cast (defined in objc/runtime.h) or a Core Foundation-style macro (defined in NSObject.h):
  • __bridge transfers a pointer between Objective-C and Core Foundation with no transfer of ownership.
  • __bridge_retained or CFBridgingRetain casts an Objective-C pointer to a Core Foundation pointer and also transfers ownership to you.
    You are responsible for calling CFRelease or a related function to relinquish ownership of the object.
  • __bridge_transfer or CFBridgingRelease moves a non-Objective-C pointer to Objective-C and also transfers ownership to ARC.
    ARC is responsible for relinquishing ownership of the object.
Some of these are shown in the following example:


NSLocale *gbNSLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_GB"];
CFLocaleRef gbCFLocale = (__bridge CFLocaleRef)gbNSLocale;
CFStringRef cfIdentifier = CFLocaleGetIdentifier(gbCFLocale);
NSLog(@"cfIdentifier: %@", (__bridge NSString *)cfIdentifier);
// Logs: "cfIdentifier: en_GB"
 
CFLocaleRef myCFLocale = CFLocaleCopyCurrent();
NSLocale *myNSLocale = (NSLocale *)CFBridgingRelease(myCFLocale);
NSString *nsIdentifier = [myNSLocale localeIdentifier];
CFShow((CFStringRef)[@"nsIdentifier: " stringByAppendingString:nsIdentifier]);
// Logs identifier for current locale


Table 1  Data types that can be used interchangeably between Core Foundation and Foundation
Core Foundation type
Foundation class
Availability
CFArrayRefNSArrayOS X v10.0
CFAttributedStringRefNSAttributedStringOS X v10.4
CFCalendarRefNSCalendarOS X v10.4
CFCharacterSetRefNSCharacterSetOS X v10.0
CFDataRefNSDataOS X v10.0
CFDateRefNSDateOS X v10.0
CFDictionaryRefNSDictionaryOS X v10.0
CFErrorRefNSErrorOS X v10.5
CFLocaleRefNSLocaleOS X v10.4
CFMutableArrayRefNSMutableArrayOS X v10.0
CFMutableAttributedStringRefNSMutableAttributedStringOS X v10.4
CFMutableCharacterSetRefNSMutableCharacterSetOS X v10.0
CFMutableDataRefNSMutableDataOS X v10.0
CFMutableDictionaryRefNSMutableDictionaryOS X v10.0
CFMutableSetRefNSMutableSetOS X v10.0
CFMutableStringRefNSMutableStringOS X v10.0
CFNumberRefNSNumberOS X v10.0
CFReadStreamRefNSInputStreamOS X v10.0
CFRunLoopTimerRefNSTimerOS X v10.0
CFSetRefNSSetOS X v10.0
CFStringRefNSStringOS X v10.0
CFTimeZoneRefNSTimeZoneOS X v10.0
CFURLRefNSURLOS X v10.0
CFWriteStreamRefNSOutputStreamOS X v10.0
You can also go through given link:


Dynamic Objective-C with NSInvocation

Although Objective-C may seem very much like Java or C++ to the untrained eye, there's actually a lot of trickery just waiting to be tapped. The dynamic nature of the language allows us to bundle up a method call as an object, and either customize it or reuse it with different targets and arguments.

First, let's create a method that we want to call:

- (NSString *) stringForDate: (NSDate *)date
usingFormatter: (NSDateFormatter *)formatter
{
  // yes, this doesn't do anything interesting.
  // just using it as a simple example

  return [formatter stringFromDate: date];
}


A brilliant masterpiece, isn't it? Now, outside of this method, let's prepare an NSInvocation object. First, we need an Objective-C selector and a matching NSMethodSignature:

// get an Objective-C selector variable for the method

SEL mySelector;
mySelector = @selector(stringForDate:usingFormatter:);

// create a signature from the selector

NSMethodSignature * sig = nil;
sig = [[self class] instanceMethodSignatureForSelector:mySelector];


Notice that we ask [self class] for the method signature. This is because the instanceMethodSignatureForSelector: class method is built into NSObject.

Now, make NSInvocation object itself:

// create an actual invocation object and set the target
// to self

NSInvocation * myInvocation = nil;
myInvocation = [NSInvocation invocationWithMethodSignature:sig];
[myInvocation setTarget:self];
[myInvocation setSelector:mySelector];


Pretty straightforward. We use the NSMethodSignature as input, and set the target to "self". You can, of course, send messages to other objects by setting a different target here.

Now, we need to add the arguments for the method:

// add first argument

NSDate * myDate = [NSDate date];
[myInvocation setArgument:&myDate atIndex:2];

// add second argument

NSDateFormatter * dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[myInvocation setArgument:&dateFormatter atIndex:3];


Again, pretty simple. We create objects and simply assign them as arguments. We need to pass in the address of the objects, so we use the addressof operator (&).

One obvious question here is why do we add the first argument at index 2. The first argument should be index 0, right? Here's the answer:

Indices 0 and 1 indicate the hidden arguments self and _cmd, respectively; these values can be retrieved directly with the target and selector methods. Use indices 2 and greater for the arguments normally passed in a message.


Finally, we want to call the actual method and get a result:

// now activate the invocation and get the result

NSString * result = nil;
[myInvocation retainArguments];
[myInvocation invoke];
[myInvocation getReturnValue:&result];

NSLog(@"The result is: %@", result);


The result is written directly to the NSString variable. The output looks something like this:

The result is: 05/13/06

This may seem like an awkward way to send a message, but the point is that NSInvocation objects can be used to call arbitrary methods with arbitrary arguments which are determined at runtime, and the objects are mutable so you can send the same message to multiple targets easily, or just change arguments.

Using -performSelector: vs. just calling the method

Basically performSelector allows you to dynamically determine which selector to call a selector on the given object. In other words the selector need not be determined before runtime.



Thus even though these are equivalent:
[anObject aMethod]; 
[anObject performSelector:@selector(aMethod)];
The second form allows you to do this:
SEL aSelector = findTheAppropriateSelectorForTheCurrentSituation();
[anObject performSelector: aSelector];
before you send the message.


respondsToSelector

You use it pretty much just when you think you need to: to check to see if an object implements the method you are about to call. Usually this is done when you have an optional methods or an informal protocol.

I've only ever used respondsToSelector when I'm writing code that must communicate with a delegate object.

if ([self.delegate respondsToSelector:@selector(engineDidStartRunning:)]) 
{
        [self.delegate engineDidStartRunning:self];
 }

You sometimes would want to use respondsToSelector on any method that returns and id or generic NSObject where you aren't sure what the class of the returned object is.





Monday 28 April 2014

Retrieving user timelines of Twitter account with SLRequest (API requests with SLRequest) (API Version 1.1)

Overview

SLRequest is a class in the Social.framework for iOS that encapsulates HTTP requests to Twitter’s REST API. This class supersedes the Twitter.framework's TWRequest from iOS5.


How do I perform requests with SLRequest ?
Executing a request to Twitter's REST API is a 3 step process:
  1. First, you create a new request using +[SLRequest requestForServiceType:requestMethod:URL:parameters:] , with the service type set to SLServiceTypeTwitter and the subsequent parameters set to the required values.
  2. Next, you assign an ACAccount instance to the request via the -[SLRequest setAccount:] method.
  3. Finally, to perform the request, you call -[SLRequest performRequestWithHandler:].
Note
Beginning with API v1.1, all requests to the REST API must be authenticated. Failure to attach an account instance to a request will result in an error.


Example: Retrieving user timelines
In this example, we will first query the accounts that the user has stored on the device, then for the first account returned we retrieve the user's home timeline using GET statuses/user_timeline, which requires authentication. We will pass four parameters to the endpoint, screen_name, count, include_rts, and trim_user.




//.h file

#import <UIKit/UIKit.h>

#import <Accounts/Accounts.h>
#import <Social/Social.h>
//#import "SCSimpleSLRequestDemo.h"

@interface HomeViewController : UIViewController
{
    
}


@property (nonatomic) ACAccountStore *accountStore;

@end








//.m file

#import "HomeViewController.h"

@interface HomeViewController ()

@end

@implementation HomeViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    
    
    _accountStore = [[ACAccountStore alloc] init];
    
    
    
    [self fetchTimelineForUser:@"UserName"];
    
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}




- (BOOL)userHasAccessToTwitter
{
    return [SLComposeViewController
            isAvailableForServiceType:SLServiceTypeTwitter];
}

- (void)fetchTimelineForUser:(NSString *)username
{
    //  Step 0: Check that the user has local Twitter accounts
    if ([self userHasAccessToTwitter])
    {
        
        //  Step 1:  Obtain access to the user's Twitter accounts
        ACAccountType *twitterAccountType =
        [self.accountStore accountTypeWithAccountTypeIdentifier:
         ACAccountTypeIdentifierTwitter];
        
        [self.accountStore
         requestAccessToAccountsWithType:twitterAccountType
         options:NULL
         completion:^(BOOL granted, NSError *error) {
             if (granted) {
                 //  Step 2:  Create a request
                 NSArray *twitterAccounts =
                 [self.accountStore accountsWithAccountType:twitterAccountType];
                 NSURL *url = [NSURL URLWithString:@"https://api.twitter.com"
                               @"/1.1/statuses/user_timeline.json"];
                 NSDictionary *params = @{@"screen_name" : username,
                                          @"include_rts" : @"0",
                                          @"trim_user" : @"1",
                                          @"count" : @"5"};
                 SLRequest *request =
                 [SLRequest requestForServiceType:SLServiceTypeTwitter
                                    requestMethod:SLRequestMethodGET
                                              URL:url
                                       parameters:params];
                 
                 //  Attach an account to the request
                 [request setAccount:[twitterAccounts lastObject]];
                 
                 //  Step 3:  Execute the request
                 [request performRequestWithHandler:
                  ^(NSData *responseData,
                    NSHTTPURLResponse *urlResponse,
                    NSError *error) {
                      
                      if (responseData) {
                          if (urlResponse.statusCode >= 200 &&
                              urlResponse.statusCode < 300) {
                              
                              NSError *jsonError;
                              NSDictionary *timelineData =
                              [NSJSONSerialization
                               JSONObjectWithData:responseData
                               options:NSJSONReadingAllowFragments error:&jsonError];
                              if (timelineData) {
                                  NSLog(@"Timeline Response: %@\n", timelineData);
                              }
                              else {
                                  // Our JSON deserialization went awry
                                  NSLog(@"JSON Error: %@", [jsonError localizedDescription]);
                              }
                          }
                          else {
                              // The server did not respond ... were we rate-limited?
                              NSLog(@"The response status code is %d",
                                    urlResponse.statusCode);
                          }
                      }
                  }];
             }
             else {
                 // Access was not granted, or an error occurred
                 NSLog(@"%@", [error localizedDescription]);
             }
         }];
    }
}


@end




Recommended Reading
The following articles on Apple's Developer Site will help you as you work with SLRequest :






Tuesday 22 April 2014

Sort NSArray with custom objects

Every app has to work with some data and this data is usually structured in custom classes. A music app will probably have a Song class, a chat app will have a Friend class, a recipe app will have a Recipe class and so on. And sometimes you want to display a sorted list of objects. Let’s find out about the different methods to do this.


The objects in the array we’re going to sort are instances of a Person class that looks like this:


@interface Person : NSObject

@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *surname;
@property (nonatomic, strong) NSDate *dateOfBirth;

@end



And the array contains the following data:

Smith John 03/01/1984
Andersen Jane 16/03/1979
Clark Anne 13/09/1995
Smith David 19/07/1981
Johnson Rose 22/02/1989




Sort using NSComparator

A comparator is a block object used for comparison operations. It’s definition looks like this:
typedef NSComparisonResult (^NSComparator)(id obj1, id obj2);

The arguments are the objects we are trying to compare. The block returns an NSComparisonResult value to denote the ordering of the two objects.

To sort the whole array you will use the method sortArrayUsingComparator: like this:



NSArray *sortedArray = [self.persons sortedArrayUsingComparator:^NSComparisonResult(Person *p1, Person *p2){

    return [p1.surname compare:p2.surname];

}];



The sorted array will look like this:
Andersen Jane
Clark Anne
Johnson Rose
Smith John
Smith David




Sort using NSDescriptor

Sort descriptors can be used not just for sorting arrays but also to specify how the elements in a table view should be arranged and also with Core Data to specify the ordering of objects returned from a fetch request. With sort descriptors you can easily sort the array by multiple keys. We’ll sort our array by surname and then by name.


NSSortDescriptor *firstDescriptor = [[NSSortDescriptor alloc] initWithKey:@"surname" ascending:YES];
NSSortDescriptor *secondDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];

NSArray *sortDescriptors = [NSArray arrayWithObjects:firstDescriptor, secondDescriptor, nil];

NSArray *sortedArray = [self.persons sortedArrayUsingDescriptors:sortDescriptors];




The resulting array will look like this:
Andersen Jane
Clark Anne
Johnson Rose
Smith David
Smith John





Sort using selectors

You can define your own method for comparing two objects and use it to sort the array. The comparator message is sent to each object in the array and has as its single argument another object in the array. The method should return NSOrederedAscending if the array is smaller than the argument, NSOrderedDescending if the array is larger than the argument and NSOrderedSame if they are equal.



- (NSComparisonResult)compare:(Person *)otherPerson 
{

    return [self.dateOfBirth compare:otherPerson.dateOfBirth];
}




This method is defined and implemented in our Person class, it sorts persons by date of birth.
All these methods do the same thing, sort an array, so you might be wondering which one to use. When you need to sort by multiple keys, the easiest way is to use sort descriptors. If you have a complicated compare method then it would make sense to have it as a selector in your class. Blocks have been introduced in iOS 4 and are a powerful tool. You can use them without a variable for a simple compare method (as presented here) or you can define a block and have a complex implementation instead of using a selector. There’s no correct answer, just use the one that makes your life easy when writing the code.














Validate e-mail address


The method that I am using, uses NSRegularExpression. Taken directly from the Apple website:



The NSRegularExpression class is used to represent and apply regular expressions to Unicode strings. An instance of this class is an immutable representation of a compiled regular expression pattern and various option flags. The pattern syntax currently supported is that specified by ICU. The ICU regular expressions are described at http://userguide.icu-project.org/strings/regexp .

The fundamental matching method for NSRegularExpression is a Block iterator method that allows clients to supply a Block object which will be invoked each time the regular expression matches a portion of the target string. There are additional convenience methods for returning all the matches as an array, the total number of matches, the first match, and the range of the first match.


So, here it is:




- (BOOL) validEmail:(NSString*) emailString 
{

    if([emailString length]==0)
   {
        return NO;
    }

    NSString *regExPattern = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";

    NSRegularExpression *regEx = [[NSRegularExpression alloc] initWithPattern:regExPattern options:NSRegularExpressionCaseInsensitive error:nil];

    NSUInteger regExMatches = [regEx numberOfMatchesInString:emailString options:0 range:NSMakeRange(0, [emailString length])];

    NSLog(@"%i", regExMatches);
    if (regExMatches == 0) 
    {
        return NO;
    } else 
    {
        return YES;
    }
}

Set a background image in your iOS Application

This is a quick iOS Development tip that will show you two different ways that you can set the background image of you application

So, There are two ways to set a background image to a UIView -
  • You can set your view background color to color created with UIColor’s colorWithPaternImage.
  • You can add a UIImageView subview to your view.

colorWithPaternImage is ideal when you wish to use a small image/pattern, say about 5px by 5px as a repeated background in your iOS Application. This method is not recommended when using a large image. For that you should use a UIImageView instead otherwise you would consume too much memory and potentially cause your iOS Application to crash.



You would need to drag the pattern image into your project and then you could use:

self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"backgroundImage"]];



If you are using the UIImageView then you would use:

UIImageView *backgroundImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"background"]];
[self.view addSubview:backgroundView];





Adding Background Images to the UIKit Controls

In iOS5, Apple released their Appearance API which allows you to bring appearance changes to the UIKit Controls. This means that you can now set the tint color, background image, and title position properties and others on a wide variety of objects, including toolbars, navigation bars, search bars, buttons, sliders, and other controls. A pretty neat addition right?

So, lets say you wanted to add the background image to the Navigation Bar, you could achieve this using the following piece of code:


[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:@"nav_bar"] forBarMetrics:UIBarMetricsDefault];







For further reading into the Appearance API Have a look at the apple documentation

















Constants in Objective C

When you’re building an app you usually need some values to remain the same for the whole runtime of the app. Instead of using those values everywhere inside your app it is better to define a constant and use the constant instead. It will make your life easier when you want to change the value everywhere in the code and if you give it a good name it will make your code more readable. In this post we’re going to talk about how to define these constants and where to define them so that we end up with a nice design.


In Objective C there are two ways you can make a value remain the same: preprocessing macros and using const storage specifier.


Preprocessing Macros

If you do something like this:


#define MAX_NUMBER_OF_ROWS 10



The value of MAX_NUMBER_OF_ROWS will always be 10 so this sounds like our definition of a constant. This is not an actual constant. It’s called a preprocessing macro because before compile time all the occurrences of MAX_NUMBER_OF_ROWS will be replaced by the actual value, 10 in our case. You’ve probably noticed that we didn’t specify a type for MAX_NUMBER_OF_ROWS. However, because the value gets replaced before compile time, the compiler will complain if you try to assign an int to an NSString for example. You will also get an error if you try to assign a value to MAX_NUMBER_OF_ROWS. So although this is not a constant it does make sure the value is the same and that you have a nice significant name for that value.


Using const

More and more people seem to like this approach better. Instead of using #define you can use const like this:

const int MAX_NUMBER_OF_ROWS = 10;


This actually allocates space for an int. The compiler will flag an error when you try to modify it.
You might be wondering which one to use. Usually you can use any of them. My personal preference is to use const. Together with extern or static you can fine tune your classes and have a clean design.




Understanding extern and static


So how exactly can you use extern and static with constants? As with variables you want the scope of your constant to be as limited as needed. You don’t want to have something public if you’re only using it in your class.
This is where static comes in. If you know that the constant you’re defining is only used in that class then you can define the constant in the .m file before the implementation of the class. Using static means that the constant will only be available in that file.


static NSString * const MY_ID = @"2A3D";


Static can be used with both variables and constants. With variables you can use it in a very nice way to persist a value across methods. If for example you do this:


- (void)oneMethod 
{

    static int x = 0;

    NSLog(@"%d \n", x++);       
}

The output will be:

0
1
2


So the variable is persisted across multiple method calls.
Going back to our constants, if you do want to have a constant global then you should use extern. In the .h file you should define the constant like this:

extern NSString * const MY_ID;





And in the .m file you would actually give it a value:


NSString * const MY_ID = @"2A3D";




This way your API interface will be nice and pretty, you’re not exposing the internals of your class to the world. If you have constants that are used in lots of classes all over the app then it makes sense to have a separate .h and .m file just for defining these constants. This way whenever you need to change the value of one of your constants you know where to look.
Just like variables constants can be defined inside methods or blocks. That means they can be used only in the scope that they have been defined for. Using extern on a const defined in a method doesn’t work, so make sure you define them in the right place when using extern.