Showing posts with label iOS6. Show all posts
Showing posts with label iOS6. Show all posts

Sunday, June 7, 2015

Performing Segue and Passing data in iOS

I was trying to learn how to perform view switching using Segue for UI created by StoryBoard. Using Segue is quite easy and convenient. You can create Segue from Interface Builder, which associate action to view. Like if you click some button then you can associate this click action with view switch and you can select which view to switch to. This all is quite simple and can be done using simple drag and drop.

In case you want to perform view switch manually without any user interaction, you can call "performSegueWithIdentifier", like below. Here once my game is finished, I am calling "GameOverSegue", which will switch view to GameOver view.
self.performSegueWithIdentifier("GameOverSegue", sender: self)
If you want to pass some data while performing Segue, your calling ViewController needs to override "prepareForSegue" function. In this function you can set data to called view. Like below, I want to pass score to my GameOver view.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if( segue.identifier == "GameOverSegue") {
        let gameOverVC: GameOverViewController = 
            segue.destinationViewController as! GameOverViewController;
        gameOverVC.setScore(self.score)
    }
}
Thanks, hope this will be helpful.

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.

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, December 20, 2014

Resolving "_clock$UNIX2003", referenced from" error

I was trying to build Unity 3D project for simulator SDK. I wanted to get different screen size screen shot. But when I tried to build it I got following build error.
_clock$UNIX2003", referenced from
I found one work around to resolve this issue. We need to add following patch to main.mm file.
#include <time.h>

// "_clock$UNIX2003", referenced from:
//Temporary hack for building Simulator Project for Unity
extern "C"
{
    clock_t
    clock$UNIX2003(void)
    {
        return clock();
    }
}
Once I added above patch build started working fine for me and I was able to run project on Simulator.

Wednesday, September 10, 2014

Matching custom NSObject with isEqual and hash

While working on one multiplayer game for iOS using GameKit, I faced issue while comparing object.

For single player version I was not facing this issue but while running multiplayer version I was facing this issue. After debugging a little I realised condition for comparing object's value is failing and it turned out that I was comparing object's address rather then its value. As for Multiplayer game I was creating object using data from server/host, I needed to compare object's value and not its address.

For objectiveC, if you want to compare object's value using "==" operator, you need to overload isEqual and hash method as shown like below.

-(BOOL)isEqual:(id) other {
    if (other == self)
        return YES;
    
    if (!other || ![other isKindOfClass:[self class]])
        return NO;
    
    Card* otherCard = other;
    return ( mSuit == otherCard.mSuit && mRank == otherCard.mRank);
}

- (NSUInteger)hash {
    NSUInteger hash = 0;
    hash += [[NSNumber numberWithInt:mSuit] hash];
    hash += [[NSNumber numberWithInt:mRank] hash];
    return hash;
}
Note that you need to overload both method together, overloading only one will not work. Once I overloaded above method my multiplayer version started working as normal.

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.