Setting Global Value in Objective C

Setting and getting value using a global singleton in objective c is a programming pattern that allow you store in the system memory.

There’s a lot of discussion regarding this design pattern both on the pros and cons, visit the following to read more. http://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons

To Setup the Singleton Object in your Xcode project.

1. Create a class (.h/.m) and name them GlobalSingleton.

2. In the GlobalSingleton.h file, add the following section of codes.

#import <Foundation/Foundation.h>

 

@interface GlobalSingleton : NSObject

 

//This are the property you are going to store in the Singleton object

@property (nonatomic, retain) NSArray *array_SideViewOptions;

 

@property (nonatomic, retain) bool *offline;

 

+(GlobalSingleton*) getValues;

 

@end

 

Notice the Singleton Properties, these are the different type of properties you intend to store inside the object.

3. In the GlobalSingleton.m file, add the following section of the codes.

#import GlobalSingleton.h

static GlobalSingleton* singleton;

static dispatch_once_t pred;

@implementation GlobalSingleton

 

@synthesize offline;

@synthesize array_SideViewOptions;

 

+(GlobalSingleton*) getValues{

    

    dispatch_once(&pred, ^{

        singleton = [[GlobalSingleton alloc] init];

    });

    returnsingleton;

    

}

 

@end

Notice the synthesize portion, thats allow you have to do in future if you add more properties.

 

Using the Singleton – Setting Value.

#import “GlobalSingleton.h”


[GlobalSingleton getValues].array_SideViewOptions = [[NSArray alloc]initWithObjects:@“apple”,@”Spidy”,@”Settings”,@”Feedback”, nil];

Using the Singleton – Getting Value.

#import “GlobalSingleton.h”

array_SectionOne = [GlobalSingleton getValues].array_SideViewOptions;

 

 

JSONLint, One tool at a time.

Over the holiday season, I decided to explore the JSON component on IOS Objective C.

But before blogging on that, I like to introduce the following tool.
To test if a particular JSON URL is correct, I recommend the following site.

http://jsonlint.com/

JSONLint, allow you to quickly test and return result from the JSON URL, therefore you dont have to write a set of sampler codes to test if the JSON URL is working or not.

Cut down on the development time for sure.

 

Happy Holidays!

UITableView Prototype Cell with UIButton

With the introduction of iOS 5, UITableview now comes with Prototype Cell.

For those who work with anything before this, you will know that creating a customized tableview cell take alot of effort.

Today, I am going to show 2 method of getting the instance of the button that is clicked.

Method 1 is the “downright dirty” way of doing things. Method 2 is much “cleaner”.

Method 1:

In the

– (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

We add the uibutton to the cell and add the indexpath.row to the tag of the UIButton.

UIButton *newButton = [[UIButton alloc ] initWithFrame:CGRectMake(0, 0, 100, 50)];

newButton.tag = indexPath.row;

[newButton addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];

[cell.contentView addSubview:newButton];

By adding the indexPath.row to the tag of the button allow us to determine which row in the UITableview the user selected.

Therefore in the ButtonPressed Method we can do the following.

-(void) buttonPressed:(id) sender{

//We load the data from a NSArray name array_data

[array_data objectAtIndex:[sender tag]];

….}

As you can see from the above we can therefore know which data is selected and the application can progress forward.

Method 2:

– (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

    static NSString *CellIdentifier = @”Cell”;

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {

        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

    }    

    UIButton *btn = (UIButton *)[cell viewWithTag:1];

    [btn addTarget:self action:@selector(onClicked:) forControlEvents:UIControlEventTouchUpInside];

}

The above is similar to the first method. Do note that the cell viewWithTag this have been already added to the Prototype cell in the Storyboard.

The tag can be set via the Storyboard, on the right of the Xcode, 3 tag from the right. The Tag Field.

Now in the onClicked Method.

-(void) onClicked: (id) sender{

    UITableViewCell *clickedCell = (UITableViewCell *)[[sender superview] superview];

    NSIndexPath *clickedButtonPath = [self.tableview indexPathForCell:clickedCell];

  }

In the clickedButtonPath, this allow us to find out the row that was selected by the user.

Summary

The 2 method above shows the different way of doing things, each have its pro and con.

In method 1, by setting the tag of the uibutton we remove certain customising ability should we want to change the color of the uibutton programmatically at a later stage.

In method 2, we have to know the view to cast it as a UITableViewCell and the wrong view will cause us to hit EXE_BAD ACCESS error.

Thanks for the read

Local Notification

There are 2 type of Notification in IOS.

Apple’s definition of the differences and when to use what,
http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Introduction/Introduction.html#//apple_ref/doc/uid/TP40008194-CH1-SW1

Don’t confuse yourself with the 2 basically, Push Notification will require to set up the communication link to Apple’s Push Server and the way the Push Server works it have its own issue.

I have attached a guide that I used to set up APN previously.
http://www.raywenderlich.com/3443/apple-push-notification-services-tutorial-part-12

Create your First Local Notification:

UIApplication *iosApp = [UIApplication sharedApplication];

UILocalNotification *localNotification = [[UILocalNotification alloc] init];

NSTimeInterval timeZoneDiff = 8 * 60 * 60;

NSTimeInterval bug = 30 * 60;

NSDate *notifDate = [alertDate dateByAddingTimeInterval:[alertTime timeIntervalSince1970] + timeZoneDiff – bug];

localNotification.fireDate = notifDate;

localNotification.timeZone = [NSTimeZone systemTimeZone];

localNotification.alertBody = [NSString stringWithFormat:@”Alert : %@”, contentData];

localNotification.soundName = UILocalNotificationDefaultSoundName;

NSDictionary *dictionary = [NSDictionary dictionaryWithObject:[NSString stringWithFormat:@”%d”, uniqueId] forKey:@”id”];

localNotification.userInfo = dictionary;

[iosApp scheduleLocalNotification:localNotification];

Add the following method into your AppDelegate.m file. This method will be called when the user click on the View button when the notification pops up.

 – (void) application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{

Now, the hard part, if you have a navigation controller in your application on clicking on the View Button most of the developers will just use the following

[(UINavigationController *) self.window.rootViewController pushViewController: <targetController> animated: TRUE];

Example:

-ViewA
-HomeView

By doing the above command, if we push another View A to the stack, the stack will look like the following:

-View A (new)
-View A
-HomeView

This will not be the result we want. So we need to clear all the view and make sure that we only have the HomeView (landing view) and the targetView.

In the applicationDidReceiveLocalNotification method,

We will declares the views we need:

  UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@”MainStoryboard” bundle:nil];

ViewA *vcA = (ViewA *)[storyboard instantiateViewControllerWithIdentifier:@”ViewA”];

HomeView *home = (HomeView *)[storyboard instantiateViewControllerWithIdentifier:@”home”];

UINavigationController *nav = (UINavigationController *) self.window.rootViewController;

nav.viewControllers = [NSArray arrayWithObjects:home,vcA, nil];

[(UINavigationController *)self.window.rootViewController popToViewController:vcA animated:TRUE];

As you can see from the above codes, we need to init the storyboard object as in the AppDelegate its still not created yet.

Then we declare the respective view, note you need to import the headers files.

Finally we add this views into the stack of the navigationController.

Instead of using push, we are using pop here. The reason for this is that push adds a new view to the stack, where as pop show something that is currently in the stacks.

I hope this help you guys in anyway possible and do drop me a comment if you need further clarification.

Standard Height and Size for iphone

UIView – 320x460UINavigationBar – 320×44
UITabBar – 320×49
UISearchBar – 320×44
UIToolBar – 320x44UIPickerView – 320×216
UIDatePicker – 320×216
UIKeyboard – 320x216UISegmentedControl – 320×44
UIButton xx37

UITextField – xx37
UISwitch 94×27

UIActivityIndicatorView – 37×37
UIPageControl – 38×36

UIKeyboard – Height : 170

UITableViewCell – 320×44

IOS GameKit

Implementing Bluetooth with GameKit

In this article, I will share how to enable Bluetooth with GameKit api.

First, we will have to add GameKit library to our project.
Select your project and the corresponding target.
Under “Build Phases”, expand “Link Binary with Libraries”. Click the “+” button and add the GameKit Library
When you successfully add the GameKit framework. It should appear as in Fig B.
Now that we’ve added the GameKit framework, we can move on to implementing the codes for Bluetooth connectivity.
We will now need to create a controller that will be implementing and using the Bluetooth.
In the header file, make sure you input the following codes

#import <UIKit/UIKit.h>

#import <GameKit/GameKit.h>

@interface BluetoothViewController : UIViewController<GKPeerPickerControllerDelegate,GKSessionDelegate>{

    GKSession *gkSession;

    GKPeerPickerController *gkPicker;

}

@property (nonatomicretainGKSession *gkSession;

@property (nonatomicretainGKPeerPickerController *gkPicker;

-(IBAction)connectViaBlueTooth:(id)sender;

@end

Now, we will move onto the implementation file.

@implementation ExchangeGKViewController

@synthesize gkSession, gkPicker;

- (void)viewDidLoad

{

    [super viewDidLoad];

    if (!gkSession) {

        gkSession = [[GKSession allocinitWithSessionID:nil displayName:nilsessionMode:GKSessionModePeer];

    }

    

}

With this, we will synthesize our session and picker so that we are able to use them.

We have also implemented a session to be created so that when we first load the viewcontroller, there will always be a valid session.

Now, we will create a button for the viewcontroller to look for other bluetooth peers.

Back to the header file, add in:

-(IBAction) connectViaBlueTooth:(id)sender;

-(IBAction) disconnectFromBlueTooth:(id) sender;


And implement it with :
-(IBAction)connectViaBlueTooth:(id)sender{}    gkPicker = [[GKPeerPickerController allocinit];    gkPicker.delegate = self;    gkPicker.connectionTypesMask = GKPeerPickerConnectionTypeNearby;

    [gkPicker show];

}

-(IBActiondisconnectFromBlueTooth:(id) sender {

    [self.gkSession disconnectFromAllPeers];

    gkSession.available = NO;

    [gkSession setDataReceiveHandler:nil withContext:nil];

    gkSession.delegate = nil;

    gkSession = nil;

    

}

Don’t forget to create the buttons, and link it with the corresponding IBAction.
Go ahead and test what you have so far. If everything is working well so far you will be able to see
You’ll also be able to see other devices if they are looking for bluetooth devices too.
If you’ve gotten this far. Congrats. Pretty easy so far. Now for the finishing touches.
We will need to implement codes so that the PeerPicker knows what to do when you select a peer

#pragma mark - GKPeerPickerControllerDelegate methods

- (void)peerPickerController:(GKPeerPickerController *)picker

              didConnectPeer:(NSString *)peerID

                   toSession:(GKSession *) session {

    self.gkSession = session;

    session.delegate = self;

    [session setDataReceiveHandler:self withContext:nil];

    picker.delegate = nil;

    [picker dismiss];

}

- (void)peerPickerControllerDidCancel:(GKPeerPickerController *)picker

{

    picker.delegate = nil;

}

Add in these codes so you know the changes in Bluetooth connectivity state as well as to send data and receive data.

#pragma mark - Session methods

- (void)session:(GKSession *)session

           peer:(NSString *)peerID

 didChangeState:(GKPeerConnectionState)state {

    UIAlertView *alert;

    switch (state)

    {

        case GKPeerStateConnected:{

            NSLog(@"connected");

            alert = [[UIAlertView allocinitWithTitle:@"Bluetooth connection"message:@"connected" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nilnil];

            [alert show];

        }

            break;

        case GKPeerStateDisconnected:{

            NSLog(@"disconnected");

            alert = [[UIAlertView allocinitWithTitle:@"Bluetooth connection"message:@"disconnected" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nilnil];

            [alert show];

            gkSession = nil;

        }

        case GKPeerStateAvailable:

        case GKPeerStateConnecting:

        case GKPeerStateUnavailable:

            break;

    }

}

- (void)session:(GKSession *)session didFailWithError:(NSError *)error{

    NSLog(@"Session error: %@", [error description]);

}

- (void) mySendDataToPeers: (NSData *) data

{

    [gkSession sendDataToAllPeers: data withDataModeGKSendDataReliable errornil];

}

- (void) receiveData:(NSData *)data fromPeer:(NSString *)peer inSession: (GKSession *)session context:(void *)context

{

    // Read the bytes in data and perform an application-specific action.

}


Congrats, you have now successfully implemented the bluetooth programming. Use the mySendDataToPeers to send data. And receiveData to read the data received.

Xcode : EXE_BAD_ACCESS

Struggling with EXC_BAD_ACCESS ?

This happens when you are trying to access an object that has already been released.
In order to find the root of the problem you will need to turn on Zombie objects. This prevents the releasing of memory of any objects used during run time and can help you determine the source of your troubles.
To enable Zombie objects in XCode 4.2:
  1. Press ⌥⌘R (Alt – Command – R)
  2. From the tab “Info | Arguments | Options | Diagnostics” select Diagnostics and click “Enable Zombie Objects”.

From now on, released objects will turn into zombies and will appear in the debugger stack trace

Adding Three20 to your Xcode Project

This article will cover the basic of adding the Three20 framework to your Xcode 4 solutions.

A little background of this particular framework, quoting from the source.

Three20 is a open source Objective-C library used by dozens of well-known brands in the App Store, including Facebook, Posterous, Pulse, Meetup.com, and SCVNGR. Three20 provides powerful view controllers such as the Launcher, the popular Photo Browser, and internet-aware tables.

Another post will be written to discuss about the features of the framework, Three20. But for now let’s us get started on adding this the Three20 to your Xcode 4 project.

Three20 source code could be downloaded from the following link. www.three20.info

I do strongly suggest that you download the tar.gz version.

  1. Start by extracting the content of the file you downloaded from the site.Again, I suggest that you should extract the file on the desktop.
  2. Locate the file ttmodule.py at that paticularly path three20/src/script/

    xcode4 three20 facebook
    xcode4 three20 facebook

     

  3. Open Terminal,
    Enter: python
  4. Drag ttmodule.py into the terminal window,
    Enter: -p
  5. Locate your xcode project, Drag the .xcodeproj file into the Terminal.
    Enter: Three20
  6. Check that the Terminal Window should now look something like this
    > python /Users/xxx/Desktop/three20/src/scripts/ttmodule.py -p /TestingProject/TestingProject.xcodeproj Three20
    Press Enter.

This will add the Three20 framework into the xcode project and you can find out more on how to use the following at the following site.