Thursday, 10 July 2014

UIPickerView and UIDatePicker demo using Swift

Hi All, hope everyone is exploring/learning Swift. I have created a sample application which uses UIPickerView and UIDatePicker. I thought of sharing with you. Lets see what I did.

I have created a empty project and added a new swift file called "UIPickerViewDemoController" and a xib file "UIPickerViewDemo.xib".


I am going to add two text fields one for picker view and one for date picker.

    @IBOutlet var textField:UITextField

    @IBOutlet var dateTextField:UITextField

Added a Picker View and Date Picker and created outlets for them.

    @IBOutlet var pickerView:UIPickerView

    @IBOutlet var datePicker:UIDatePicker

Have assigned pickers to inputView property of text fields

        textField.inputView = pickerView

        dateTextField.inputView = datePicker

 Corresponding picker will be shown based up on the first responder status. 

Here is how XIB look like :



Here is the complete initialisation code in viewDidLoad method :

    @IBOutlet var pickerView:UIPickerView
    @IBOutlet var textField:UITextField
    
    @IBOutlet var datePicker:UIDatePicker
    @IBOutlet var dateTextField:UITextField
    
    var elements:Array<String>?

    override func viewDidLoad()
    {
        super.viewDidLoad()
        
        self.edgesForExtendedLayout = UIRectEdge.None
        
        self.title = "Picker View"
        
        textField.inputView = pickerView
        
        elements = ["One","Two","Three","Five","Six","Seven","Eight","Nine","Ten"]
        
        dateTextField.inputView = datePicker

    }

Following are the delegate and datasource implementation for picker view :

    func numberOfComponentsInPickerView(pickerView: UIPickerView!) -> Int
    {
        return 1;
    }
    
    func pickerView(pickerView: UIPickerView!, numberOfRowsInComponent component: Int) -> Int
    {
        return elements!.count;
    }
    
    func pickerView(pickerView: UIPickerView!, titleForRow row: Int, forComponent component: Int) -> String
    {
        return elements![row]
    }
    
    func pickerView(pickerView: UIPickerView!, didSelectRow row: Int, inComponent component: Int)
    {
        textField.text = elements![row]
    }


Following is the valueChanged selector for date picker :

@IBAction func dateValueChanged(sender:UIDatePicker)
    {
        dateTextField.text = sender.date.description
    }

Here is the output :




You can download source code here

Wednesday, 11 June 2014

UITableView Demo using Swift

Hi All,  Apple has introduced new programming language called "Swift" and iOS 8. Hope all of you know about this. I have downloaded XCode 6.0 beta from "developer.apple.com" and started playing with it. I have created a UITableView demo and thought of sharing it with you.

I have created a empty application and created new UIViewController subclass "TableViewController" and corresponding xib file called "TableView".


Added code in AppDelegate.swift to create a new navigation controller with TableViewController as root view controller :

        var tableVC : TableViewController = TableViewController(nibName: "TableView", bundle: NSBundle.mainBundle())
        var navVC : UINavigationController = UINavigationController(rootViewController: tableVC)
        

        self.window!.rootViewController = navVC

now, func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool of AppDelegate class will look like below :

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
        self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
        
        var tableVC : TableViewController = TableViewController(nibName: "TableView", bundle: NSBundle.mainBundle())
        var navVC : UINavigationController = UINavigationController(rootViewController: tableVC)
        
        self.window!.rootViewController = navVC
        self.window!.backgroundColor = UIColor.whiteColor()
        self.window!.makeKeyAndVisible()
        
        return true
    }

In TableViewController class, I took elements as an optional array and implemented UITableViewDatasource methods :

    import UIKit

class TableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource
{
    var elements : Array<AnyObject>?
    
    init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    }

    override func viewDidLoad()
    {
        super.viewDidLoad()
        
        self.title = "Table View"
        
        elements = ["One","Two","Three","Five","Six","Seven","Eight","Nine","Ten"]
    }
    
    func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int
    {
        return elements!.count;
    }
    
    func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!
    {
        var cell = tableView.dequeueReusableCellWithIdentifier("Cell") as UITableViewCell!
        
        if cell == nil
        {
            cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
        }
        
        cell.textLabel.text = elements![indexPath.row] as String
        
        return cell
    }
}

Here is the output :



Here is the Source Code.

Tuesday, 21 January 2014

Customising or adding subviews to UIAlertView in iOS 7

Hi All, hope everybody is doing good. Today I am planning to discuss about customising alert views in iOS 7. In earlier versions of iOS, we can subclass UIAlertView and add subviews to it by passing addSubview: message. But, in iOS 7 we can't add a sub view to UIAlertView by passing addSubview: message. Even if send message addSubview: message to UIAlertView, there wont be any effect.

I explored different ways to add subviews to UIAlertView in iOS 7 and finally came up with a solution. I have created a single view application and created a subclass of UIAlertView MLKLoadingAlertView.

Added a custom init method as shown below :

Header File :


@interface MLKLoadingAlertView : UIAlertView

- (id)initWithTitle:(NSString *)title;

@end

init method in Implementation File :

- (id)initWithTitle:(NSString *)title
{
    if ( self = [super init] )
    {
        self.title = title;
        self.message = @"\n\n";
        
        [self setDelegate:self];
    }
    
    return self;
}

If you observer initWithTitle method, I have made UIAlertView subclass itself as delegate of UIAlertView. I have implemented following delegate method of UIAlertViewDelegate in MLKLoadingAlertView :


// You can Customise this based on your requirement by adding subviews.
- (void)didPresentAlertView:(UIAlertView *)alertView
{
    NSArray *subviews = [UIApplication sharedApplication].keyWindow.rootViewController.presentedViewController.view.subviews;
    
    if( subviews.count > 1 )
    {
        // iOS while presenting an alertview uses a presening view controller. That controller's view has several subviews. I have picked one
        // subview from it which has frame similar to the alertview frame.
        UIView *presentedView = [subviews objectAtIndex:1];
        
         UIActivityIndicatorView *customActivityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
        [customActivityIndicator startAnimating];
        customActivityIndicator.center = ACTIVITY_INDICATOR_CENTER;
        
        [presentedView addSubview:customActivityIndicator];
    }
}

What I did is, when alert view is presented, I am trying to access alert view via subviews of presentedViewController's view in following way :

[UIApplication sharedApplication].keyWindow.rootViewController.presentedViewController.view.subviews

After getting access to UIAlertView instance, I am adding subviews to it.





I have created an example to demonstrate this and placed code in github. You can download source code form Here

Hope this tutorial helps who ever looking for customising UIAlertView in iOS 7 by adding subviews.

Please feel free to add your comments.

Thursday, 19 December 2013

Copy vs Retain in Objective C

Hi all, in one of my previous posts, we have discussed about memory management in Objective C using retain message. Sending "retain" message to a object will give ownership of the object. Now, lets see what we have to do to get a copy of object instead of just getting ownership of the object.

We have a method called "copy" in Objective C root class "NSObject". Using this method we can we can create a copy of an existing instance. Following is the syntax to do that.

Object *obj2 = [obj1 copy];

Now obj2 is exact copy of obj1. Both are difference objects. Newly created object "obj2" will have a retain count of 1 irrespective of the retain count of obj1.

Now lets take an example. I took NSMutableArray to explain the difference. Don't worry, if you don't know about NSMutableArray. Its just a collection object which holds a bunch of objects. If a object can be copied then it should confirm to NSCopying protocol.

We will discuss about collections and protocols in our next tutorials. For now just take NSMutableArray can hold a collection of objects and we can add or remove objects from it.


    NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:@"First",@"Second", nil];
    NSMutableArray *copiedArray = [array mutableCopy];
    NSMutableArray *retainedArray = [array retain];
    
    [retainedArray addObject:@"Retained Third"];
    [copiedArray addObject:@"Copied Third"];
    
    NSLog(@"array = %@",array);
    NSLog(@"Retained Array = %@",retainedArray);
    NSLog(@"Copied Array = %@",copiedArray);


Now look at the above code. First list shows creating a NSMutableArray object(array) with NSString elements @"First" and @"Second"(In Objective C we represent strings in @"").  copiedArray is copied object of array and retainedArray is retained object of array.

In next code we have added @"Retained Third" object to retained array and @"Copied Third" to copied array. After that I am printing the array values in console. (NSLog is used to print your logs in console. It uses c format specifiers. Apart from those, we can use %@ to print an object.)

Now here is the out put in console :

2013-12-19 17:15:49.379 RetainVsCopy[2876:c07] array = (
    First,
    Second,
    "Retained Third"
)
2013-12-19 17:15:49.380 RetainVsCopy[2876:c07] Retained Array = (
    First,
    Second,
    "Retained Third"
)
2013-12-19 17:15:49.381 RetainVsCopy[2876:c07] Copied Array = (
    First,
    Second,
    "Copied Third"
)

See, both array and Retained Array are having same contents. This is because both are pointing to same  memory/instance/object. Where as contents of Copied Array are different. This is because copy created a separate instance.

I hope this explanation helped you in figuring out difference between copy and retain. Feel free to ask your questions.

You can get source code of this example from here Source Code

Saturday, 21 September 2013

Memory management in Objective C

Hi all, today we will discuss about memory management in Objective C. Its an important concept in Objective C. Lets see how it works. Memory is very important for every application. Especially for mobile applications. So, its important to manage memory in our applications.

Thumb rule in Objective C memory management is, who ever creates an object or gets ownership of an object, they are responsible to release that particular object. We discusses in my earlier in my posts that Objective C is object oriented programming language. So, there will be object sharing. To manage this, we have retain count mechanism in Objective C. Retain count represents number of owners to a particular object.

Lets say we have created an object in class A following way :

Object *obj = [[Object alloc] init]; // retain count is 1.

Now, what to do if the same object is shared by another class B? Class B has to get owner ship of obj. Otherwise, if we use obj in class B after it is released by class A, application will be crashed as there are no owners to obj.

Lets retain obj in class B :

[obj retain]; // retain count is 2.

Will increase retain count by 1. Thus indicates class B is also owner of obj. Its responsibility of class B to release obj. Whenever send release message on obj, its retain count will be decremented by 1.

[obj release]; // retain count is 0


Now, retain count of the object obj is 1. After some processing, lets say I am done with using object obj in class A also. I need to release memory related to this object. What I need to do is, just send "release" message on this object.

[obj release];  // retain count 0.

Now, retain count of the obj is 0. There are no owners present for this object. Objective C runtime environment will take care of reclaiming memory allocated to obj.

Following summary explains how memory is managed :


         Class A                     Class B                       Class A                                Class B
           alloc                          retain                         release                                 release
obj (retain count 1)     obj (retain count 2)         obj (retain count 1)          obj (retain count 0)


In our next tutorial we will discuss about autorelease pools and setter methods using memory management.

Please feel free to post your questions.



Sunday, 11 August 2013

UIAlertViewStyle property of UIAlertView

Hi Guys,

Hope everybody doing well. Recently I got a requirement in one of my project to create a UIAlertView with "User Name" and "Password" fields. Prior to iOS 5.0, to achieve this functionality we need to subclass UIAlertView and add UITextField as subviews to the UIAlertView.

Initially I thought of subclassing UIAlertView to achieve this functionality, but I came to know that from iOS 5.0 Apple has added a new property "UIAlertViewStyle alertViewStyle" to UIAlertView class.

Following are the various options available for UIAlertViewStyle property :


UIAlertViewStyleDefaultUIAlertViewStyleSecureTextInputUIAlertViewStylePlainTextInputUIAlertViewStyleLoginAndPasswordInput

Now, lets create a single view application and setup the view layout as show below :


Set tags to 1001 to "Default, 1002 to "Secure", 1003 to "Plain" and 1004 to "Login & Password" buttons using xib file.

Add following action method code to your implementation file :

- (IBAction)showAlert:(id)sender
{
    UIAlertView *alertView = [[UIAlertView alloc] init];
    
    switch (((UIButton *)sender).tag)
    {
        // Default Alert View
        case 1001:
            
            alertView.title = @"Default Alert View";
            alertView.message = @"UIAlertViewStyleDefault";
            [alertView addButtonWithTitle:@"OK"];
            
            break;
           
        // Secure Alert View
        case 1002:
            
            alertView.title = @"Secure Alert View";
            alertView.message = @"UIAlertViewStyleSecureTextInput";
            alertView.alertViewStyle = UIAlertViewStyleSecureTextInput;
            [alertView addButtonWithTitle:@"OK"];
            [alertView addButtonWithTitle:@"Cancel"];
            
            break;
            
        // Plain Alert View
        case 1003:
            
            alertView.title = @"Plain Alert View";
            alertView.message = @"UIAlertViewStylePlainTextInput";
            alertView.alertViewStyle = UIAlertViewStylePlainTextInput;
            [alertView addButtonWithTitle:@"OK"];
            [alertView addButtonWithTitle:@"Cancel"];

            break;
          
        // Login ALert View
        case 1004:
            
            alertView.title = @"Login Alert View";
            alertView.alertViewStyle = UIAlertViewStyleLoginAndPasswordInput;
            [alertView addButtonWithTitle:@"OK"];
            [alertView addButtonWithTitle:@"Cancel"];

            break;
    }
    
    [alertView show];
}


Now connect this action to all buttons in xib file to "Touch up inside" UIControlEvent. 

Run application and following is the output :

Default Style :


Secure Style :

Plain Style :

Login & Password :


This saved a lot of time for me. No need to subclass UIAlertView anymore to create a login view. Hope this will save time of your's too.



 

Thursday, 13 June 2013

Secure Text Field With Custom Numeric KeyPad

Hi Guys,

Today I have decided to discuss about a custom secure text field with custom numeric keypad. Usually, when we have a UITextField with secure option enabled and using a default keyboard, last character entered by user will be shown for some time and then it will be converted in to a dot. Please see below screenshot.

But this is not same if we use a custom keyboard. If we use a custom keyboard, last digit won't appear to end user. When ever we press a key in custom keyboard, a dot will be added directly with out any animation. Please see the below screenshot.


To have last character animation for custom keyboard, I came up with a Custom secured UITextField called MLKSecuredTextField. Lets see how I have implemented it. 

Create a Single View application as shown below :
Now, create MKLSecureTextField class which will be a subclass of UITextField as shown below :
The logic I have followed is, I have subclasses UITextField and created following initializers :

- (id)init
{
    if( self = [super init] )
    {
        [self setUpTextFieldProperties];
    }
    
    return self;
}

- (id)initWithFrame:(CGRect)frame
{
    if( self = [super initWithFrame:frame] )
    {
        [self setUpTextFieldProperties];
    }
    
    return self;
}

- (void)setUpTextFieldProperties
{
    // Following are default Values. Can assign custom values after creating MLKSecuredTextField.
    self.borderStyle = UITextBorderStyleRoundedRect;
    self.textColor = [UIColor clearColor];
    self.font = [UIFont systemFontOfSize:FONT_SIZE];
    self.clearButtonMode = UITextFieldViewModeAlways;
    self.placeholder = PLACEHOLDER_TEXT;
    self.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;
    
    self.dotViews = [[NSMutableArray alloc] init];
    
    self.textLength = 0;
    self.text = @"";
    
    // Add text changes observer to get notifications whenever text changes
    [self addObserver:self forKeyPath:TEXT options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
}

 setUpTextFieldProperties method will setup the default properties of our custom textfield and adds a observer to "text" property of textfield. We are observing changes made to text of the text field. I am setting the text color as clear color so that whatever text user enters won't appear.

Whenever there is a change in the text, I am updating the last character to dot and showing the current character for some time. If no text entered, last enter character will be changed to dot after 2 seconds time interval. I have used NSTimer to achieve this. Following is the code :

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context {
    
    if ([keyPath isEqual:TEXT])
    {
        [self textChanged];
    }
}

- (void)textChanged
{
    // Remove the dot view if a character removed
    if( self.textLength > [self.text length] )
    {
        [self invalidateDotViewTimerForIndex:([self.text length ]- 1)];
        
        [[self.dotViews objectAtIndex:(self.textLength - 1)] removeFromSuperview];
        [self.dotViews removeObjectAtIndex:(self.textLength - 1)];
    }
    else if( [self.text length] > 0 )
    {
        [self invalidateDotViewTimerForIndex:([self.text length] - 2)];
        
        [self addCharacterLabelAtIndex:([self.text length] - 1)];
        dotViewTimer = [NSTimer scheduledTimerWithTimeInterval:TIMER_INTERVAL target:self selector:@selector(addDotToLastCharacter) userInfo:nil repeats:NO];
    }
    
    // Capture new lenght
    self.textLength = [self.text length];
    
    // User clicked clear text button. Clear all dot views
    if( self.textLength == 0 )
    {
        [self clearAllDotViews];
    }
}

Override following UITextField methods to set the text rect and editing rect for our custom MLKSecureTextField :

- (CGRect)textRectForBounds:(CGRect) bounds
{
    CGRect origValue = [super textRectForBounds: bounds];
    
    return TEXT_LABEL_OFFSET;
}

- (CGRect)editingRectForBounds:(CGRect) bounds
{
    CGRect origValue = [super textRectForBounds: bounds];
    
    return TEXT_LABEL_OFFSET;
}

Now add business logic to add dots, to show last character for time and clearing all dots when user taps clear button on text field.

- (void)addDotToLastCharacter
{
    [self.characterLabel removeFromSuperview];
    [self addDotViewForCharAtIndex:([self.text length] - 1)];
}

- (void)addDotViewForCharAtIndex:(NSInteger)index
{
    UIView *dotView = [[UIView alloc] initWithFrame:DOT_VIEW_RECT];
    dotView.backgroundColor = [UIColor blackColor];
    [dotView.layer setMasksToBounds:YES];
    [dotView.layer setCornerRadius:DOT_RADIUS];
    
    [self addSubview:dotView];
    [self.dotViews addObject:dotView];
}

- (void)addCharacterLabelAtIndex:(NSInteger)index
{
    self.characterLabel = [[UILabel alloc] initWithFrame:CHAR_LABEL_RECT];
    self.characterLabel.text = [NSString stringWithFormat:@"%C",[self.text characterAtIndex:index]];
    self.characterLabel.font = self.font;
    self.characterLabel.backgroundColor = [UIColor clearColor];
    
    [self addSubview:self.characterLabel];
}

- (void)invalidateDotViewTimerForIndex:(NSInteger)index
{
    if( dotViewTimer.isValid )
    {
        [dotViewTimer invalidate];
        [self.characterLabel removeFromSuperview];
        [self addDotViewForCharAtIndex:index];
    }
}

- (void)clearAllDotViews
{
    while( self.dotViews.count )
    {
        [[self.dotViews objectAtIndex:self.dotViews.count-1] removeFromSuperview];
        [self.dotViews removeObjectAtIndex:self.dotViews.count-1];
    }
}

Here are the #defines I have used :

#define DOT_VIEW_RECT       CGRectMake(8 + (index * (9 + 1.5)), 13, 9, 9)
#define CHAR_LABEL_RECT     CGRectMake(8 + (index * (9 + 1.5)), 10, 9, 14)

#define TEXT_LABEL_OFFSET   CGRectOffset(origValue, 0.0f, 3.0f)

#define TEXT            @"text"
#define FONT_SIZE       17
#define TIMER_INTERVAL  2.0

#define DOT_RADIUS      4.5f

#define PLACEHOLDER_TEXT    @"MLKSecuredTextField"

Okay, we have completed creating custom secure text field. Now use it in a view controller and see the output. Create MLKSecureTextField and add it to the View :

secureTextField = [[MLKSecuredTextField alloc] initWithFrame:CGRectMake(20, 20, 280, 30)];
secureTextField.delegate = self;
[self.view addSubview:secureTextField];

For your understanding, I have used three text fields, one MLKTextFieldField with custom numeric keypad, one UITextField with default keypad and one UITextField with custom numeric keypad.
Now try to enter text in the UITextField with default keyboard :
See you are able to see last character for some time, after that it will be converted to a dot. Lets see what is the behavior with UITextField with custom numeric keypad :
Observe the behavior, when ever you press a key it will be directly added as a dot in the text field. Lets see behavior with our custom MLKSecureTextField :
Have you observed that, last character is appeared for some time and after that changed to a dot. Yeah!!!! we got the expected behavior. 

Thats all from this post. Please add your comments and suggestions.