Saturday 13 October 2018

Lazy Properties

Lazy store properties value not calculated until first accessed.
You can declare a lazy property with simply "lazy" keyword.
The closure associated to lazy property is executed only if you read the property.
Lazy properties works with class or struct.
Lazy store properties must be declare with var, because it's initial value might note be retrieved until after instance initialization complete.

Example : 


class LazyExample{
    var iCount = 0
    func testFunc() -> String{
        iCount += 1
        return "iCount Value \(iCount)"
    }
    lazy var tempLazy : String  = {
        print("access value")
        return testFunc()
    }()
}
let lazyObj = LazyExample()

print(lazyObj.tempLazy) ///Only single time value access
print(lazyObj.tempLazy)

print(lazyObj.tempLazy)

Output: 

access value
iCount Value 1
iCount Value 1
iCount Value 1





Another example :

class ViewController: UIViewController {

    lazy var buildVersion : String = {
        print("only once initialize after that get from session")
        print("every time not get from app bundle")
        return (Bundle.main.infoDictionary?["CFBundleVersion"]  asString) ?? ""
    }()
    override func viewDidLoad() {
        super.viewDidLoad()
        
        print(buildVersion)
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        print(buildVersion)
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        /*
         this is simple buildVerison property
         that get session after once initialize
         */
        print(buildVersion)
    }

}

For more info about lazy properties  watch below video




Monday 1 October 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.