Wednesday, July 13, 2016

Convenience Initialisation Vs Designated Initialization


Designated initializers fully initialize an instance of a class, meaning that every property of the instance has an initial value after initialization. Looking at the Task class, for example, we see that the nameproperty is set with the value of the name parameter of the init(name:) initializer. The result after initialization is a fully initialized Task instance.
Convenience initializers, however, rely on a designated initializer to create a fully initialized instance of the class. That's why the init initializer of the Task class invokes the init(name:) initializer in its implementation. This is referred to as initializer delegation. The init initializer delegates initialization to a designated initializer to create a fully initialized instance of the Task class.
Convenience initializers are optional. Not every class has a convenience initializer. Designated initializers are required and a class needs to have at least one designated initializer to create a fully initialized instance of itself.
Ref: http://code.tutsplus.com/tutorials/swift-from-scratch-initialization-and-initializer-delegation--cms-23538
import Foundation
 
class Task: NSObject {
    var name: String
     
   convenience override init() {
        self.init(name: "New Task")
    }
     
    init(name: String) {
        self.name = name
    }
}

Friday, June 10, 2016

Finding out whether device is iPad Pro

Both iPad and iPad Pro fall into same family size (Rw and Rh) sometimes we will be in need of customising only for iPad Pro.In such scenarios we need to have short cuts to determine whether device is iPad Pro.

Following snippet will help you out:

#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define SCREEN_WIDTH ([[UIScreen mainScreen] bounds].size.width)
#define SCREEN_HEIGHT ([[UIScreen mainScreen] bounds].size.height)
#define IS_IPAD_PRO_1366 (IS_IPAD && MAX(SCREEN_WIDTH,SCREEN_HEIGHT) == 1366.0)
#define IS_IPAD_PRO_1024 (IS_IPAD && MAX(SCREEN_WIDTH,SCREEN_HEIGHT) == 1024.0)
  

Thursday, May 26, 2016

Storing more entries in Keychain

Recently i got a requirement that involves storing more than one entry in the keychain.Apparently keychain accepts one entry for the application.

We know keychain in iOS are unique to each application.And we store as "Key-value" combination in keychain.Both keys and values can be strings.Now the problem is what if there is a need to store more than one entry in keychain for the same application.

Solution is Create a mutable dictionary and add "key-value" entries in the same dictionary each for entry you wanted to save in keychain.

For instance:

I want to save username,password,last login time in the keychain.Then create a dictionary called "User details" and going to add "username":"xyz" ,"Password":"1234","Last login time":"12:34:45pm"

Our dictionary "User details" looks like
username   xyz
password 1234
last login time 12:34:45

Then add this entire "User details" dictionary in keychain like below:

Code excerpts are in Xamarin.But it gives you idea fairly about

//entry in dictionary
            keyItemsDict.SetValueForKey (NSObject.FromObject(value),(NSString)key);
            keyItemsDict.SetValueForKey (NSObject.FromObject(Convert.ToBase64String(value)),keyStr);

            NSData dicDt = NSJsonSerialization.Serialize (keyItemsDict,0,out error);
//keyItemsDict is a dictionary            var s = new SecRecord (SecKind.GenericPassword) {
                ValueData =dicDt,
                Generic = NSData.FromString ("KeyChain")
            };

            SecKeyChain.Add (s);  //add in keychain

Wednesday, May 11, 2016

What happens when installing ipa and launching the app from springboard

When we build the app for release what happens really is it creates a directory which contains all the things our app needs.
Once ipa is generated,right click the app file (not the Dipa file) and select show package contents.Besides normal project files and resources you will be able to see other two things:

  1. Provisioning file
  2. Code signature directory-Inside it there is a file called "Code resources", a plist file which has cryptographic hashes for all the files in the solution.
When installing the ipa,it checks whether the provisioning file is actually signed from apple and compares each one of the hashes in the code resources against all the real files to verify whether its modified since the build.If anything fails,app won't be installed.

And then when you launch the app,it checks the app has not been modified and you still have provision file for the app to run.If any problem arises in these steps,app will crash.

For further reading on this topic,where to go from here? Check out Demystifying iOS certificates and provisioning file 

Monday, April 18, 2016

Disable Swipe gesture in Selected views of UIPageViewController

I used UIPageViewController for the seamless navigation of tabs through swipe gestures.Since UIPageViewController seems good for swipe gesture navigation i used this controller through out the application.

It works like a charm until i got a need to implement a custom slider inside a view of UIPageViewController.


Design of the screen is as below:




Problem was when i intend to swipe the play field slider either forward or backward,the entire screen moves,page controller eats the swipe gesture and thinks it has to navigate to next screen or previous screen.But my intention was i would like to forward the song for a few seconds or reverse for few seconds.


I tried to solve this problem by many methods.Every attempts failed but one simple and efficient solution worked wonders to me.


I created one Pan Gesture Recognizer with no handle method and added to the Slider view initially.And set CancelsTouchesInView to false.


Code snippet in Xamarin


            UIPanGestureRecognizer panGesture=new        UIPanGestureRecognizer();
            panGesture.CancelsTouchesInView=false;

            PlayfieldSlider.AddGestureRecognizer(panGesture);
           PlayfieldSlider.thumbButton.AddGestureRecognizer(panGesture);

I added the pan gesture only to the thumb portion of slider.Thumb is the one which has play/pause button on the slider of any music player.Idea is when user holds thumb and drags along the slider the page controller does not react whereas if user slides anywhere even on the slider area also makes the page to move to another screen.


Explanation


Referhttp://stackoverflow.com/questions/13042632/what-really-happens-when-call-setcancelstouchesinview

suppose you have a view with a pan gesture recognizer attached, and you have these methods in your view controller:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"touchesBegan");
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"touchesMoved");
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"touchesEnded");
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"touchesCancelled");
}

- (IBAction)panGestureRecognizerDidUpdate:(UIPanGestureRecognizer *)sender {
    NSLog(@"panGesture");
}
And of course the pan gesture recognizer is configured to send the panGestureRecognizerDidUpdate: message.
Now suppose you touch the view, move your finger enough for the pan gesture to be recognized, and then lift your finger. What does the app print?
If the gesture recognizer has cancelsTouchesInView set to YES, the app will log these messages:
touchesBegan
touchesMoved
touchesCancelled
panGesture
panGesture
(etc.)
You might get more than one touchesMoved before the cancel.
So, if you set cancelsTouchesInView to YES (the default), the system will cancel the touch before it sends the first message from the gesture recognizer, and you won't get any more touch-related messages for that touch.
If the gesture recognizer has cancelsTouchesInView set to NO, the app will log these messages:
touchesBegan
touchesMoved
panGesture
touchesMoved
panGesture
touchesMoved
panGesture
(etc.)
panGesture
touchesEnded
So, if you set cancelsTouchesInView to NO, the system will continue sending touch-related messages for the gesture touch, interleaved with the gesture recognizer's messages. The touch will end normally instead of being cancelled (unless the system cancels the touch for some other reason, like the home button being pressed during the touch).

Tuesday, April 12, 2016

Find out if earphones are plugged in or not

There may be usecase where you need to check whether head phones are plugged in or not before delving into other functionality.

Here is a way to achieve that.

1.Import AVFoundation framework.

2.Include AVFoundation header file in the place where you need to check whether head phone is plugged in or not.

3.Use the below method

-(BOOL)isHeadPhonePlugged
{
    AVAudioSessionRouteDescription *route=[[AVAudioSession sharedInstance]currentRoute];
    for (AVAudioSessionPortDescription *port in [route outputs]) {

        if ([[port portType]isEqualToString:AVAudioSessionPortHeadphones]) {
            return YES;
        }
        
    }
    return NO;


}

Monday, April 11, 2016

Making hyperlinks in UITextView to respond instantly

Ever wondered why hyperlinks in UITextView responds only when you touch and hold for a few seconds,whereas hyperlink in web view works much faster.

I assume its designed in that way.Am sure you have checked those initial set ups like   textview.selectable=yes.

I solved it through help from stack overflow post http://stackoverflow.com/questions/22379595/uitextview-link-tap-recognition-is-delayed 

Solution:

1.Add a Tap gesture to UITextview.

UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tappedTextView:)];
[myTextView addGestureRecognizer:tapRecognizer];

2.In the handle method get the touch position


    CGPoint tapLocation = [tapGesture locationInView:textView];

 and get the Attributes of the text whose points closest to the touch
    UITextPosition *textPosition = [textView closestPositionToPoint:tapLocation];
    NSDictionary *attributes = [textView textStylingAtPosition:textPosition inDirection:UITextStorageDirectionForward];

3.Get URL from the attributes and open the url if its not null

    NSURL *url = attributes[NSLinkAttributeName];

    if (url) {
        [[UIApplication sharedApplication] openURL:url];
    }