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.

Sunday, August 16, 2015

The Math Game for iOS

If you have read my previous posts, you might already know I was trying to learn Swift language. While doing so I tried to create a simple game.

Finally I was able to complete the app and was able to publish it as well. You can download app from here.


Below is demo of the game.

You can also get more information about app here.

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.