Sunday, 30 September 2018

Extensions

Extensions means add additional functionality to existing types.
Extensions add new functionality to existing class, struct, enum or protocols.
Extensions are similar to categories in Objective-C.

Extension syntax
Declare Extension with "extension" keyword

extension Type {
    ///Additional functionality add hear

}

An Extension can extends one or more protocols.

extension Type : Protocol{
    ///protocols method hear
}

Example

extension String{
    ///Trim string value
    func toTrim() -> String{
        return self.trimmingCharacters(in: .whitespacesAndNewlines)
    }
}

///Simply use like below
let strName = " use of string extension "
print(strName)
print(strName.toTrim())

Output : 

 use of string extension 
use of string extension

Another example

extension UIView {
    func defaultRadius() {
        self.layer.cornerRadius = self.frame.size.width / 2
    }
}

let parentView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: 50, height: 50))
parentView.backgroundColor = UIColor.red
parentView.defaultRadius()

Output: 

UIView Extension


Computed Properties

Extension can add computed instance property and computed type property to existing type.

Example

extension Int{
    var squareRoot : Int {
        return self * self
    }
}

let iValue = 5
print(iValue.squareRoot)

Output : 

25

Methods

Extensions add new instance method and type method to existence type.

Example

extension Int{
    func repeatValue(value : () -> Void) {
        for _ in 0..<self{
            value()
        }
    }
}

5.repeatValue {
    print("hello world")

}

Output :

hello world
hello world
hello world
hello world
hello world

For more about Extensions watch below video



Monday, 24 September 2018

UITableViewCell Animation

Hello friends,
This article is use for UITableViewCell animation.
In most of the application for represent data you can use UITableView.
When UITableView represent at that time you need to animated UITableViewCell for best UI experience of application.

How to use
You need to implement UITableView method 

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
     
        ///Animation code
    
    }

Now you need to developed FadeIn animation like this

cell.alpha = 0
        UIView.animate(withDuration: 0.1, delay: (0.1 * Double(indexPath.row)),  animations: {
            cell.alpha = 1.0
        }, completion: nil)

For more animation see this video



For above animation I have created extension for UITableViewCell

extension UITableViewCell{
    
    /// Table view cell fade in animation for best way to represent
    /// tableview
    ///
    /// - Parameters:
    ///   - duration: animation duration default value 0.1
    ///   - index: cell index
    func fadeInAnimation(withDuration duration: Double = 0.1,forIndex index : Int) {
        self.alpha = 0
        UIView.animate(withDuration: duration, delay: (duration * Double(index)),  animations: {
            self.alpha = 1.0
        }, completion: nil)
    }
    
    /// Table view cell bounce animation for best way to represent
    /// tableview
    ///
    /// - Parameters:
    ///   - duration: animation duration default value 0.8
    ///   - delay: animation delay default value 0.05
    ///   - index: cell index
    func bouncingAnimation(withDuration duration: Double = 0.8,withDelay delay : Double = 0.05,forIndex index : Int) {
        self.transform = CGAffineTransform(translationX: 0, y: self.frame.height)
        UIView.animate(withDuration: duration,delay: delay * Double(index),usingSpringWithDamping: 0.8,initialSpringVelocity: 0.1,animations: {
            self.transform = CGAffineTransform(translationX: 0, y: 0)
        })
    }
    
    /// Table view cell move in animation for best way to represent
    /// tableview
    ///
    /// - Parameters:
    ///   - duration: animation duration default value 0.5
    ///   - delay: animation delay default value 0.08
    ///   - index: cell index
    func moveInAnimation(withDuration duration: Double = 0.5,withDelay delay : Double = 0.08,forIndex index : Int) {
        self.alpha = 0
        self.transform = CGAffineTransform(translationX: 0, y: self.frame.height / 2)
        UIView.animate(withDuration: duration,delay: delay * Double(index),animations: {
            self.alpha = 1
            self.transform = CGAffineTransform(translationX: 0, y: 0)
        })
    }
    
    /// Table view cell right side to in animation for best way to represent
    /// tableview
    ///
    /// - Parameters:
    ///   - duration: animation duration default value 0.5
    ///   - delay: animation delay default value 0.08
    ///   - index: cell index
    func rightInAnimation(withDuration duration: Double = 0.5,withDelay delay : Double = 0.08,forIndex index : Int) {
        self.transform = CGAffineTransform(translationX: self.bounds.width, y: 0)
        UIView.animate(withDuration: duration,delay: delay * Double(index),animations: {
            self.transform = CGAffineTransform(translationX: 0, y: 0)
        })
    }
    
    /// Table view cell left side to in animation for best way to represent
    /// tableview
    ///
    /// - Parameters:
    ///   - duration: animation duration default value 0.5
    ///   - delay: animation delay default value 0.08
    ///   - index: cell index
    func leftInAnimation(withDuration duration: Double = 0.5,withDelay delay : Double = 0.08,forIndex index : Int) {
        self.transform = CGAffineTransform(translationX: -self.bounds.width, y: 0)
        UIView.animate(withDuration: duration,delay: delay * Double(index),animations: {
            self.transform = CGAffineTransform(translationX: 0, y: 0)
        })
    }
}

And you can simply use like 

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        if (animationType == .bounce){
            cell.bouncingAnimation(forIndex: indexPath.row)
        }else if (animationType == .moveIn){
            cell.moveInAnimation(forIndex: indexPath.row)
        }else if (animationType == .leftIn){
            cell.leftInAnimation(forIndex: indexPath.row)
        }else if (animationType == .rightIn){
            cell.rightInAnimation(forIndex: indexPath.row)
        }else if (animationType == .side){
            if (indexPath.row % 2 == 0){
                cell.leftInAnimation(forIndex: indexPath.row)
            }else{
                cell.rightInAnimation(forIndex: indexPath.row)
            }
        }else{
            cell.fadeInAnimation(forIndex: indexPath.row)
        }
    }

The sample code for illustrated in this post is available on GitHub

Thank you.

Wednesday, 19 September 2018

Optional Types

Optional represents either wrapped value or nil.
Optionals are generic enum type that works as wrapper.

Basically wrapper allow variable have 2 states:

  1. User define type
  2. nil (that represent no value)
In swift nil value must be optional.
Optional can be created by appending either "?" or "!".

example :

var name : String? = nil
var lname : String! = nil

"?" must be explicitly unwrapped where as "!" automatically unwrapped.
Conditionally unwrapped use "?" optional binding where as force unwrapped use "!" operator. If you force unwrapped variable and value is nil then program will throw exception and crash so be careful.

example :

var lname : String! = nil
print(lname!)

Output :

fatal error: unexpectedly found nil while unwrapping an Optional value

Safe unwrapping :

Using if-let statement safe unwrap

example :

func safeUnwrap(withName name : String?){
    if let userName = name{
        print(userName)
    }else{
        print("name value is nil")
    }
}

safeUnwrap(withName: "Pratik")

Output :

Pratik

safeUnwrap(withName: nil)


Output :

name value is nil

Using guard-let statement safe unwrap

example :

func safeUnwrap(withName name : String?){
    guard let userName = name else{
        print("user name not found")
        return
    }
    print(userName)
}

safeUnwrap(withName: "Pratik")

Output :

Pratik

safeUnwrap(withName: nil)


Output :

user name not found

Using Coalescing operator safe unwrap

example :

var name : String? = nil
print(name ?? "name value is nil")


Output :

name value is nil

var name : String? = nil
name = "Pratik"
print(name ?? "name value is nil")


Output :

Pratik

You can also use Optional chaining in order to call method,property or subscript.

example : 

struct Family{
    func printName() {
        print("Hello friends")
    }
}

var objFamily : Family?
objFamily?.printName()

Output :

no print 

var objFamily : Family? = Family()
objFamily?.printName()

Output :

Hello friends



unwrapped using optional type in swift
Optional types unwrapped

Monday, 17 September 2018

Logger

Hello friends this article is use for developer debugging print values in LLDB debug area.
There are multiple functions available in swift

print(),debugPrint(),dump(),NSLog()

use of these functions in swift

print : print(_ items: Any..., separator: String = default, terminator: String = default)

print is use for some textual representations in debug area. 

example : 

print("hello friends")

Output : 

hello friends

debugPrint : debugPrint(_ items: Any..., separator: String = default, terminator: String = default)

debugPrint is use for shows the instance of some textual representations in debug area.

example : 

debugPrint("hello friends")

Output : 

"hello friends"

dump : dump<T>(_ value: T, name: String? = default, indent: Int = default, maxDepth: Int = default, maxItems: Int = default)

dump is use for print the contents of an object via reflection like mirroring. dump prints details hierarchy

example : 

dump(["iOS","Android"])

Output : 

2 elements
  - "iOS"
  - "Android"

NSLog : NSLog(_ format: String, _ args: CVarArg...)

NSLog is use for print the contents with timestamp. It will also print project_name along with timestamp.

example :

NSLog("hello iOS developers")

Output : 

2018-09-17 15:18:10.522 DebuggerDemo[2022:4583274]hello iOS developers

print() vs dump()

Let’s create simple “Student” class

class Student{
    let name = "Pratik"
    let lname = "Lad"
}

now print Student() class using print() & dump() 

print(Student())

Output :

__lldb_expr_81.Student

dump(Student())

Output : 

__lldb_expr_81.Student #0
  - name: "Pratik"
  - lname: "Lad"

You can see the difference of printing in debug area result. print() simple print the class name where as dump() print the whole class hierarchy. 

Sunday, 16 September 2018

class vs struct

Class

  • class is reference type.
  • class object is created on Heap memory.
  • For class member variable can initialised directly.
  • class have constructor and destructor methods of all types.
  • class can inherit another class.
  • class are good for larger or complex object.

Struct


  • struct is value type.
  • struct object is created on Stack memory.
  • For struct member vaiable can not initialised directly.
  • struct can't be abstract.
  • stucts are good for small and isolated model object.  


Example of class

created one Student class with name and lname property with init method
class Student{
    var name : String?
    var lname : String?
    init(name : String?,lname : String?) {
        self.name = name
        self.lname = lname
    }

}
- now create one object for Student class called objStudent and print
let objStudent = Student(name: "Pratik", lname: "Lad")
dump(objStudent)

Output :
__lldb_expr_44.Student #0
  name: Optional("Pratik")
    - some: "Pratik"
  lname: Optional("Lad")
    - some: "Lad"

- now one more object create and assign older object of Student class
let obj1Student = objStudent
- now change the name of obj1Student object
obj1Student.name = "Bunty"
- now print both object 
dump(objStudent)

Output :
__lldb_expr_44.Student #0
  name: Optional("Bunty")
    - some: "Bunty"
  lname: Optional("Lad")
    - some: "Lad"

dump(obj1Student)

Output :
__lldb_expr_44.Student #0
   name: Optional("Bunty")
    - some: "Bunty"
   lname: Optional("Lad")
    - some: "Lad"
you can see the objStudent object name also change because class is reference type.

Example of struct

created one Student struct with name and lname property with init method
struct Student{
    var name : String?
    var lname : String?
    init(name : String?,lname : String?) {
        self.name = name
        self.lname = lname
    }

}
- now create one object for Student struct called objStudent and print
let objStudent = Student(name: "Pratik", lname: "Lad")
dump(objStudent)

Output :
__lldb_expr_44.Student #0
   name: Optional("Pratik")
    - some: "Pratik"
   lname: Optional("Lad")
    - some: "Lad"

- now one more object create and assign older object of Student struct
var obj1Student = objStudent
- now change the name of obj1Student object
obj1Student.name = "Bunty"
- now print both object 
dump(objStudent)

Output :
__lldb_expr_44.Student #0
   name: Optional("Pratik")
    - some: "Bunty"
   lname: Optional("Lad")
    - some: "Lad"

dump(obj1Student)

Output :
__lldb_expr_44.Student #0
   name: Optional("Bunty")
    - some: "Bunty"
   lname: Optional("Lad")
    - some: "Lad"
you can see the objStudent and obj1Student object name not change because struct is value type.

Thanks for reading this article.