Showing posts with label iphone application. Show all posts
Showing posts with label iphone application. Show all posts

Saturday, October 10, 2015

Custom UISwitch in iOS

I wanted to create Custom UISwitch in my iOS game. Initially I just waned to change size, font and color and for that I used UICustomSwitch from Hardy Macia found at here. It's quite easy to use and customisable, but then I wanted to switch to use custom image instead of standard one. For that I need to modify code a bit, below is the code which use custom image to create UISwitch. BTW this is how it looks


Header is same as original implementation, but I removed unnecessary properties and added left and right images required to display on and off images for switch.
@interface UICustomSwitch : UISlider {
    BOOL on;
    UIImageView* leftImage;
    UIImageView* rightImage;
 
    BOOL touchedSelf;
}

@property(nonatomic,getter=isOn) BOOL on;
@property (nonatomic, retain) UIImageView* leftImage;
@property (nonatomic, retain) UIImageView* rightImage;

- (void)setOn:(BOOL)on animated:(BOOL)animated;

@end
Now lets see implementation. Below is code for initialising the UISwitch with custom rect. You can also see we are adding On and Off image as left and right subview to switch.
-(id)initWithFrame:(CGRect)rect
{    
    if ((self=[super initWithFrame:rect])) {
 [self awakeFromNib];
    }
    return self;
}

-(void)awakeFromNib
{
    [super awakeFromNib];
 
    self.backgroundColor = [UIColor clearColor];
    
    [self setThumbImage:[Util imageNamed:@"switch"] 
        forState:UIControlStateNormal];
    [self setMinimumTrackTintColor:[UIColor clearColor]];
    [self setMaximumTrackTintColor:[UIColor clearColor]];
    
    self.minimumValue = 0;
    self.maximumValue = 1;
    self.continuous = NO;
 
    self.on = NO;
    self.value = 0.0;
 
    self.leftImage = [[UIImageView alloc] initWithFrame:self.frame];
    self.leftImage.image = [Util imageNamed:@"on"];
    [self addSubview: self.leftImage];
    [self.leftImage release];
    
    self.rightImage = [[UIImageView alloc] initWithFrame:self.frame];
    self.rightImage.image = [Util imageNamed:@"off"];
    [self addSubview: self.rightImage];
    [self.rightImage release];
}

Now you should be able to see UISwitch with custom images, we now need to add code required to on and off switch from code and change image accordingly.
- (void)setOn:(BOOL)turnOn animated:(BOOL)animated;
{
    on = turnOn;
 
    if (animated) {
 [UIView beginAnimations:@"UICustomSwitch" context:nil];
 [UIView setAnimationDuration:0.2];
    }
 
    if (on) {
 self.value = 1.0;
        self.rightImage.hidden = YES;
        self.leftImage.hidden = NO;
    } else {
 self.value = 0.0;
        self.rightImage.hidden = NO;
        self.leftImage.hidden = YES;
    }
 
    if (animated) {
 [UIView commitAnimations]; 
    }
}


Now finally we also have to add code to enable interaction.
- (void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
{
    [super endTrackingWithTouch:touch withEvent:event];
    touchedSelf = YES;
    [self setOn:on animated:YES];
}

- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
    [super touchesBegan:touches withEvent:event];
    touchedSelf = NO;
    on = !on;
}

- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
    [super touchesEnded:touches withEvent:event]; 
    if (!touchedSelf) {
 [self setOn:on animated:YES];
 [self sendActionsForControlEvents:UIControlEventValueChanged];
    }
}
That's it, I hope this will help.

Friday, July 17, 2015

Displaying Game Centre Leaders board from Swift

In last post, I showed how we can authenticate local player and how we can post score to default leader board.

In this post, I will show how we can display leader board using swift gamekit API. Below code shows how we can display GKGameCenterViewController. Game center viewcontroller needs delegate, which is called when view is dismissed. Also we need parent viewcontroller which will be used to display GKGameCenterViewController.
func showLeaderboard(viewController: UIViewController, 
    gameCenterDelegate: GKGameCenterControllerDelegate) {
    let gameCenterVC: GKGameCenterViewController = GKGameCenterViewController();
    gameCenterVC.leaderboardIdentifier = defaultLeaderBoard;
    gameCenterVC.gameCenterDelegate = gameCenterDelegate;
    viewController.presentViewController(gameCenterVC, animated: true, completion: nil);
}
Now we have code that can display leader board, but we need to make our class conform to GKGameCenterControllerDelegate protocol and implement required method. Below is code for delegate method. Which simply dismiss presented view controller.
func gameCenterViewControllerDidFinish(gameCenterViewController: GKGameCenterViewController!) {
    gameCenterViewController.dismissViewControllerAnimated(true, completion: nil)
}
So, as you can see it's quite simple. Hope this will be helpful.

Friday, July 10, 2015

Creating array of IBOutlets of NSLayoutConstraint's from Swift in iOS

While working on my iOS app, I wanted to modify UI Constraint set from Interface Builder from Swift code.

Below video shows how we can create Array of IBOutlets using Interface Builder. Here I am creating array of NSLayoutConstraint, which I want to modify from Swift Code.



Now lets see how we can manipulate constraints from swift. First we need to define array of IBOutlet. Below code shows the same.
@IBOutlet var constraints: Array?
Now, once you connect IBoutlet from Interface Builder as shown in above video. You can use those. In below code I am modifying NSLayoutConstraint's constant value.
if( Utils.isIPad() ) {
    for constraint: NSLayoutConstraint in constraints! {
        if(Utils.isIPad()) {
            constraint.constant = 30
        }
    }
}
That's it, Thank you for reading.

Sunday, June 28, 2015

Posting score to Game Kit Leader board using swift

As you might already know, I recently started exploring Swift language and now I am trying out GameKit framework. While I have some experience in working with GameKit using Objective C. I wanted to do the same thing using swift. As such there are no API changes while using GameKit with Swift or Objective C. However there are some syntax change.

In this post, I will show how to Authenticate local player using GameKit framework and post score to LeaderBoard defined in iTune Connect Application setting.

Following is code snippet that shows how to Authenticate Local player. This function takes ViewController as argument. Login dialog will be displayed using this View controller. Rest will be taken care by GameKit framework.
func authenticateLocalPlayer(viewController: UIViewController) {
    let localPlayer: GKLocalPlayer = GKLocalPlayer.localPlayer()
    
    localPlayer.authenticateHandler = {(ViewController, error) -> Void in
        if((ViewController) != nil) {
            // 1 Show login if player is not logged in
            viewController.presentViewController(ViewController, animated: true, completion: nil)
        } else if (localPlayer.authenticated) {
            // 2 Player is already euthenticated & logged in, load game center
            self.isGameCenterEnabld = true                
        } else {
            // 3 Game center is not enabled on the users device
            self.isGameCenterEnabld = false
            println("Local player could not be authenticated, disabling game center")
            println(error)
        }
        
    }
    
}
Now we have authenticated local player. So when we are ready to post score to Leader Board. We can use below function. Here we are posting score to "defaultLeaderBoard". Which is identifier of Leader board defined in iTune connect App setting.

func submitScore( score: Int) {
    if( !isGameCenterEnabld ) {
        return;
    }
    
    var sScore = GKScore(leaderboardIdentifier: defaultLeaderBoard)
    sScore.value = Int64(score)
    
    let localPlayer: GKLocalPlayer = GKLocalPlayer.localPlayer()
    
    GKScore.reportScores([sScore], withCompletionHandler: { (error: NSError!) -> Void in
        if error != nil {
            println(error.localizedDescription)
        } else {
            println("Score submitted")
            
        }
    })
}
That's it. Hope this will be useful.

Saturday, June 27, 2015

Using NSNotificationCenter in Swift

NSNotificationCenter is a convenient method to implement Observer pattern in iOS, something similar to what we say Signal/Slot in Qt framework.

To register one self as observer to some event, you can use addObserver method form NSNotificationCenter. In below code you are adding self as observer, selector is method which will be called when event is triggered, name is name of event or notification in which we are interested in, and object is object from which we want to receive event from, nil means we are ready to receive event from any object.
NSNotificationCenter.defaultCenter().addObserver(
    self, 
    selector: "gameViewClosed", 
    name: "gameViewClosed", 
    object: nil);
Now to trigger the notification, you can use postNotificationName method from NSNotificationCenter. Following code shows the same. Here we are sending notification for "gameViewClosed" event, object nil mean deliver event to all interested objects.
NSNotificationCenter.defaultCenter().postNotificationName(
    "gameViewClosed", 
    object: nil);
That's it, thanks for reading.

Saturday, June 6, 2015

Drawing round border around UIView in iOS

I wanted to create a subview UIView with round border in iOS. I found following code works very well to draw round border around UIView. While this code is written swift you can easily write similar code in Objective C as well.

Following is the code. As you can see, I selected subview UIView and made is IBOutlet using Interface Builder. Once that is done you can see round border around view.

@IBOutlet weak var contentView: UIView?
    
override func viewDidLoad() {
    super.viewDidLoad();
        
    contentView?.layer.borderWidth = 3.0
    contentView?.layer.borderColor = UIColor(red:102/255,green:102/225,blue:102/225, alpha:1).CGColor
    contentView?.layer.cornerRadius = 14
}
    
And following how it looks.

Friday, June 5, 2015

Hiding status bar in iOS8 using Swift

I recently started learning swift, while learning I started to create simple game. I wanted to make my game full screen, but I was unable to hide top status bar from Interface builder. No matter what I change that status bar was always visible.

Buf I found following code snippet, if you add this code in your View Controller file, you can easily hide status bar.
override func prefersStatusBarHidden() -> Bool {
    return true;
}
Following how my ViewController file looks after adding this code.
class ViewController: UIViewController {
        
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
    override func prefersStatusBarHidden() -> Bool {
        return true;
    }
}
That's it. Hope this will be hopeful.

Saturday, January 24, 2015

Notification on property change in iOS SDK

I have used QML quite a lot in my projects and there is one quite nice feature in QML that makes implementation quite easy. The feature is Property change notification.

Apple iOS SDK also similar mechanism named Key-Value Observing mechanism. Here is Apple's documentation for the same.

Following is simple code which demonstrate how we can use Key-Value Observer API to get notification on property changes. First we need to register observer and in which property observer is interested in. Code shows, class "self" is interested in property change event from propertyOwner for "isPlaying" property.
[propertyOwner addObserver:self
    forKeyPath:@"isPlaying"
       options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
       context:NULL];
Now, we have registered observer for property change, we need to implement method which will be called in case of property is changed. Following code shows the same. We need to check which object sent event and for which property, then we can take appropriate action.
- (void) observeValueForKeyPath:(NSString *)path ofObject:(id) object change:(NSDictionary *) change context:(void *)context
{
    // this method is used for all observations, so you need to make sure
    // you are responding to the right one.
    if (object == propertyOwner && [path isEqualToString:@"isPlaying"]) {
        // now we know which property is modified
    }
}
When we are done and don't need notification any more we can remove observer. Below is code for the same. It's safe to use try and catch as we might get exception if we try to remove observer when none is registered.
    @try{
        [propertyOwner removeObserver:self forKeyPath:@"isPlaying"];
    }@catch(id anException){
        //do nothing, obviously it wasn't attached because an exception was thrown
    }
Now whenever "propertyOwner" changes's "isPlaying" property then "self" will get notification and "observeValueForKeyPath" method will get called.

Saturday, September 13, 2014

Creating array of IBOutlet

Sometimes you want to enable/disable bunch of buttons together or perform other such activities on bunch of UI elements created using Interface Builder.

I recently needed to perform similar operation on bunch of button for iOS game I am working on. For this kind of operation, its easier to create array of IBOutlet which can be created using IBOutletCollection. Following is my code, which create IBOutletCollection of UIButtons and then enable/disbale them together.
@interface MyViewController : UIViewController {
    IBOutletCollection(UIButton) NSArray *buttons;
}
in MyViewController.m, we can use buttons as below.
-(void) enableUI:(BOOL) enable {    
    for( UIButton* button in buttons){
        button.enabled = enable;
    }    
}
Only thing missing now is, connecting UIButtons created using Interface Builder to IBoutletCollection. We need to do this from Interface Builder, process is similar to connecting UI Elements from Interface Builder to IBOutlet.

Following snaps describes the required process. I created three buttons on view.


You can connect IBoutletCollection to UIButton as shown in below snap.


And you can repeat above process to connect more UIButton with IBOutletCollection.

That's it.

Saturday, November 23, 2013

Using NSOperationQueue in iOS SDK

Sometimes we need to perform some task in different thread or in background. NSOperationQueue is quite handy for such purpose in iOS.

You can easily add operation you need to perform in queue just like any other object and NSOperationQueue queue will take care of its execution. You can also add operation in NSOperationQueue by specifying code block, and in many situations that's quite useful.

 Following code sample shows how we can create NSOperationQueue.
- (id)init
{
    if ((self = [super init]))
    {
        _operationQueue = [[NSOperationQueue alloc] init];
        //[_operationQueue setMaxConcurrentOperationCount:1];
    }
    return self;
}

- (void)dealloc
{
    [_operationQueue release];
    [super dealloc];
}

Below code shows how we can add operation to NSOperationQueue by code block.
- (void)requestFinished:(ASIHTTPRequest *)request {
        
    [_operationQueue addOperationWithBlock:^{
        
        //perform some useful task
        
    }];
}
   -(void) processEntries:(NSArray*) entries
   {
   }

   [_operationQueue addOperationWithBlock:^{
     [self processEntries:entries];
   }];

Friday, September 6, 2013

Reading file from resource in iOS

I was working on creating some utility function for iOS App. I required to create a File in resource and read it. File contains some words separated by new lines. I wanted to read those words and create array of those.

Its quite simple but though to share it.

Following how its done.

        
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"keywords_en" ofType:@"txt"];
NSError *error = nil;
NSString *keywordsStr = [NSString stringWithContentsOfFile: filePath encoding:NSUTF8StringEncoding error:&error];

NSArray* keywordArray = [[keywordsStr componentsSeparatedByString:@"\n"]retain];

Thursday, November 29, 2012

Making app iPhone5 compatible

I recently ported my iPhone app to iPhone5. I required to change quite a few things. Porting experience was not that much smooth as I was expecting.

In this post I am listing what all changes I made to make my universal app iPhone5 compatible.

Enable iPhone5 support

If you have not done anything to your application for iPhone5 support, it should work fine but your app will be launched in letterbox mode. I mean you will see black area around your app.

If you want to remove those black bar and want to use whole iPhone5 screen then you need to supply iPhone5 specific launch image. Image name should be Default-568h@2x.png and resolution should be 640x1136.

When you supply this image, iOS6 knows that your app is iPhone5 resolution compatible.
You can supply that image using project screen.



Once this is done your application will be able to use whole screen area.

You will also need to create other background image with above resolution, however they will not be used by default. You will need to load and display them manually.

Detecting iPhone5

While porting we will need to detect if phone is iPhone5 or not. I am using following code for detecting iPhone5.

+(BOOL) isTall
{
   return  ([ [ UIScreen mainScreen ] bounds ].size.height == 568);
}

Changes in App Delegate

There are some changes in iOS6 to handle orientation change.

In your app delegate class you need to use UIWindow's setRootViewController api to set view controller, rather than using addSubview

Now my applicationDidFinishLauncing method looks like following. I also required to create UIWindow instance manually else touch event was not working properly.

- (void)applicationDidFinishLaunching:(UIApplication *)application 
{        
    self.window = [[[UIWindow alloc] initWithFrame:
       [[UIScreen mainScreen] bounds]] autorelease];
    
    self.viewController = [[ViewController alloc] 
       initWithNibName:@"ViewController" bundle:nil];
    
    if ( [[UIDevice currentDevice].systemVersion floatValue] < 6.0)
    {
        // for older version
        [window addSubview: viewController.view];
    }
    else
    {
        // use this method on ios6
        [window setRootViewController:viewController];
    }
    [window makeKeyAndVisible];
}

Handling Orientations

Api to detect orientation change is also changed in iOS6. shouldAutorotateToInterfaceOrientation method is replaced by supportedInterfaceOrientations and shouldAutorotate in iOS6.

I left implementation of shouldAutorotateToInterfaceOrientation method as it is as those will be used for old platform.

Following is how I handled the orientation change.

// For old version
- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationLandscapeRight ||
            interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}

// for iOS6
- (NSUInteger) supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskLandscape;
}

-(BOOL) shouldAutorotate {
    return YES;
}

Handling nib file

My application is universal application and I have different nib file for iphone and ipad. There are many view for my application and each view has background and different layout. For iPhone5, you either have to create separate nib file to handle iphone5 specific layout and background image. Or you can go ahead with auto layout but this will work only for iOS6 and onwards.

I wanted to support old platform in the same code base so I ended up creating separate nib file for iPhone5 and specified iphone5 specific background and layout manually.

I am using following code for loading different nib file according to platform.

+(NSString*) getPlatformNibName:(NSString*) origNibName
{
    NSString* fileName = origNibName;
    if( [Util isIPad] == YES ) {
        fileName = [fileName stringByAppendingString:@"-iPad"];
    } else if( [Util isTall] == YES ) {
        fileName = [fileName stringByAppendingString:@"-iphone5"];       
    }
 
    return fileName;
}
After making these changes, my application was working fine for iPhone5.

Saturday, June 18, 2011

Trying out iPhone SDK Mapkit framework

Currenly I am working on my small pet project for my iPod. I want my iPod to communicate with my Nokia device to get current location and display it.

I have not make much progress yet,  now days I don't have much free time. But I was easily able to display hard coded location on my application.

To display map and location you can use iPhone SDK's Mapkit framework. But before using it you must add framework to your project.  To add framework right click on framework-> add -> existing frameworks and then choose Mapkit framework.




Now I added instance of MKMapView to my view controller like below.

#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>

@interface MapkitDemoViewController : UIViewController {
 IBOutlet MKMapView* mapView;
}

@property(retain,nonatomic) MKMapView* mapView;

@end

And initialized it in viewDidLoad function like below. I am using CLLocationCoordinate2D structure to set required cordinate and MKCoordinateSpan to specify required zoom level.  Then creating MKCoordinateRegion from above info and setting that to mapView.

We can also add our custom place marker using MKPointAnnotation, its concrete implementation for MKAnnotation protocol. Creating instance of MKPointAnnotation and setting it to mapView is quite strait forward.

- (void)viewDidLoad {
[super viewDidLoad];
 
 mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
 mapView.mapType = MKMapTypeHybrid;
 
 CLLocationCoordinate2D coord = {latitude: 37.247414,longitude: 127.058278};
 MKCoordinateSpan span = {latitudeDelta: 0.001, longitudeDelta:0.001};
 MKCoordinateRegion region = {coord, span};
 
 [mapView setRegion:region];
 
 MKPointAnnotation *anno = [[MKPointAnnotation alloc] init];
 [anno setCoordinate:coord];
 [anno setTitle:@"Test"];
 [anno setSubtitle:@"Test annotation"];
 [mapView addAnnotation:anno];
  
 [self.view addSubview:mapView];
}

In case you need convert latitude and longitude between decimal degrees and degrees, minutes, and seconds. Here is link which I used.

And also If you face "Couldn't register com.yourcompany.Mapkit Demo with the bootstrap server" kind of error. I used to kill my simulator and relaunch application and it worked fine then after.

That's all for now, following is output from above code.


Saturday, March 19, 2011

Custom UIAlertView in iPhoneSDK

Recently while working on personal project I need to customizing UIAlertView. My requirement was just to add image on UIAlertView everything else should be same.

For that I could have derived UIAlertView and could have provided custom drawing to put image, but instead I used following hack because i thought it was fast.

Here is code if you find it useful.
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Hack!" 
      message:@"Hacking alert view\n\n\n\n\n" 
     delegate:nil 
     cancelButtonTitle:@"OK" 
     otherButtonTitles:nil];
 
    UIImageView *imageView = [[UIImageView alloc] 
        initWithFrame:CGRectMake(110, 80, 66, 66)];
 
    NSString *path = [[NSString alloc] initWithString:[[
[NSBundle mainBundle] resourcePath] 
stringByAppendingPathComponent:@"images.jpg"]];

    UIImage *bkgImg = [[UIImage alloc] initWithContentsOfFile:path];
    [imageView setImage:bkgImg];
    [bkgImg release];
    [path release];
 
    [alert addSubview:imageView];
    [imageView release];
 
    [alert show];
    [alert release];

Here is output.

Sunday, February 13, 2011

Posting message to facebook wall using iPhone SDK

UPDATE: I have posted my sample application code here. Please visit code fore more information.

Recently I was working on iPhone project that required to post message on Facebook wall.

There is already official facebook API for iOS SDK, which we can use for interacting with Facebook.

You can download Facebook API from GitHub repository using following command.
git clone git://github.com/facebook/facebook-ios-sdk.git

To use downloaded facebook API, you need to bring all facebook API source code under your project. To do this you can just drag it's src folder and drop it under your project in XCode.

Before you start coding, you need a valid facebook application id, you can get one from Developer App. And you need to add this App ID in "fbYOUR_APP_ID" format to your project's .plist file like shown in following snapshot.


Now you are ready to use Facebook iPhone SDK. Main interface class to invoke Facebook API is "Facebook". Following is code to use Facebook class to login and autorize application to use user's facebook account.
facebook = [[Facebook alloc] initWithAppId:@"YOUR_APP_ID"];
   NSArray* permissions =  [NSArray arrayWithObjects:@"read_stream", 
    @"publish_stream", nil];
   [facebook authorize:permissions delegate:self];
With read_stream we can access user's basic account information and with publish_stream we can post to user's wall and make comment.

To authorization to complete successfully we need to implement application:handleOpenURL: method from UIApplicationDelegate and forwad call to facebook API. Like shown in below code.
return [facebook handleOpenURL:url]; 
So everything goes fine then you should be able to retrieve user's account information and post to user's wall as well.

Now to post message to user's wall you can use following code.
NSMutableDictionary* params = [[NSMutableDictionary alloc] 
initWithCapacity:1]
 [params setObject:@"Testing" forKey:@"name"];
 [params setObject:@"IMAGE_URL" forKey:@"picture"];
 [params setObject:@"Description" forKey:@"description"];
 [facebook requestWithGraphPath:@"me/feed" 
        andParams:params 
    andHttpMethod:@"POST" 
      andDelegate:self];
Here "me/feed" is used to post message to logged in user's wall, if you want to post to some other user's wall using logged in user's account then use need to use "USER_ID/feed" instead.

Friday, January 7, 2011

Dragon Killer Tien Len 13 game for iPhone, iPod

Sometime ago I was working with a friend to create Tien Len game for iPhone. Now that game is live on Apple app store.

Tien Len (also known as Thirteen, Killer, & VC) is a popular & very addicting card game that is played around the world.

Each player is given 13 cards, and the objective is to get rid of your cards before your opponents. The lowest card (3 of spades) is played to start the game and then players take turns using strategy to beat their opponent’s hand in multiple rounds with singles, doubles, triples, straights, and bombs. Suit rank (spades<4<5 … <2) determines which hand is higher than the other.

Please visit iTunes or App store for more information and download.

Following are few snaps from game.






Following is video from game.