Showing posts with label Xcode. Show all posts
Showing posts with label Xcode. Show all posts

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.

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. 

Monday, 10 September 2018

Codable with CoreData

Swift define standard approach to data encoding and decoding which combines the Encodable and Decodable protocols that is called Codable.

In this block I illustrated Codable using API parse and store into CoreData.
First you need to create entity called "List" and create attribute(id,user_id,title,body) like below

CoreData
List Entity

and then create NSManageObject subclass for List entity.
Now create encode and decode method like below

import Foundation
import CoreData

@objc(List)
public class List: NSManagedObject,Codable {
    
    ///From api response key if changed
    enum apiKey: String, CodingKey {
        case id
        case user_id = "userId"
        case title
        case body
    }

    // MARK: - Decodable
    required convenience public init(from decoder: Decoder) throws {
        
        ///Fetch context for codable
        guard let codableContext = CodingUserInfoKey.init(rawValue: "context"),
            let manageObjContext = decoder.userInfo[codableContext] as? NSManagedObjectContext,
            let manageObjList = NSEntityDescription.entity(forEntityName: "List", in: manageObjContext) else {
                fatalError("failed")
        }
        
        self.init(entity: manageObjList, insertInto: manageObjContext)
        
        let container = try decoder.container(keyedBy: apiKey.self)
        self.user_id = try container.decodeIfPresent(Int64.self, forKey: .user_id) ?? 0
        self.id = try container.decodeIfPresent(Int64.self, forKey: .id) ?? 0
        self.title = try container.decodeIfPresent(String.self, forKey: .title)
        self.body = try container.decodeIfPresent(String.self, forKey: .body)
    }
    
    // MARK: - encode
    public func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: apiKey.self)
        try container.encode(user_id, forKey: .user_id)
        try container.encode(id, forKey: .id)
        try container.encode(title, forKey: .title)
        try container.encode(body, forKey: .body)
    }

}

Now send server request and parse response using Codable and store into CoreData.

///get data from api
    func getListData()  {
        guard let listURL = URL(string: "https://jsonplaceholder.typicode.com/posts/")else {
            return
        }
        URLSession.shared.dataTask(with: listURL){
            (data,response,error) in
            guard let jsonData = data else { return }
            DispatchQueue.main.async {
                self.parseResponse(forData: jsonData)
            }
        }.resume()
    }
    
    ///parse response using decodable and store data 
    func parseResponse(forData jsonData : Data)  {
        do {
            guard let codableContext = CodingUserInfoKey.init(rawValue: "context") else {
                fatalError("Failed context")
            }
            
            let manageObjContext = appDelegate.persistentContainer.viewContext
            let decoder = JSONDecoder()
            decoder.userInfo[codableContext] = manageObjContext
            // Parse JSON data
            _ = try decoder.decode([List].self, from: jsonData)
            ///context save
            try manageObjContext.save()
            UserDefaults.standard.set(true, forKey: "isAllreadyFetch")
            self.fetchLocalData()
        } catch let error {
            print("Error ->\(error.localizedDescription)")
            self.errorMessage(error.localizedDescription)
        }
    }

And fetch data like below 

    ///Local data fetch from core data
    func fetchLocalData()  {
        let manageObjContext = appDelegate.persistentContainer.viewContext
        let fetchRequest = NSFetchRequest<List>(entityName: "List")
        ///Sort by id
        let sortDescriptor = NSSortDescriptor(key: "id", ascending: true)
        fetchRequest.sortDescriptors = [sortDescriptor]
        do {
            self.arrayOfList = try manageObjContext.fetch(fetchRequest)
        } catch let error {
            print(error)
            self.errorMessage(error.localizedDescription)
        }
    }

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

Sunday, 9 September 2018

Tuples

Why Tuples ?
Swift 4 has introduced tuples to help us to return multiple values from a function instead of only one value.
Tuples is multiple values grouped into a single compound value. The values can be of any type, it need not necessarily to be of same type.
Tuples type is comma-seperated list types, enclosed in parentheses.
Tuples are created by grouping any amount of values.

Please check below examples for different uses of tuples :
---------------------------------------------------------------------------------
Displaying tuple value using variable name

1) Same Data type

let multipleValue : (value1 : String,value2 : String) = ("iOS","Android")

print(multipleValue.value1)
print(multipleValue.value2)

Output
iOS
Android
---------------------------------------------------------------------------------
Different Data type

1) Displaying tuple value using index (without variable name)

let multipleValue = ("iOS""Android"5)

print(multipleValue.0
print(multipleValue.1)
print(multipleValue.2)

Output :
iOS
Android
5

2) Displaying tuple value using variable names

let multipleValue = (name: "iOS",name1: "Android",value1: 5)

print(multipleValue.name)
print(multipleValue.name1)
print(multipleValue.value1)

Output :
iOS
Android
5
---------------------------------------------------------------------------------
Displaying tuples as optionals

var multipleValue : (name: String,name1: String?,value1: Int)
multipleValue = ("iOS",nil,5)

print(multipleValue.name)
print(multipleValue.name1)
print(multipleValue.value1)

Output
iOS
nil
5

---------------------------------------------------------------------------------
Tuples usage in function return type

1) Displaying tuple value using index (without variable name)

func test() -> (String,Int) {
    return ("iOS",11)
}

print(test().0)
print(test().1)

Output
iOS
11

2) Displaying tuple value with variable name


func test() -> (name : String,version : Int) {
    return ("iOS",11)
}
print(test().name)
print(test().version)

Output
iOS
11
---------------------------------------------------------------------------------

For more info, click on below link :-

https://www.youtube.com/watch?v=MwOv844k9-4&t=222s




Thank you.


Animation

Animation interaction is best way to deal with different type of interact with application functionality. Now a days Animation is big part of Application for success.
In this article you can create easy way to animated object in Swift Xcode.
If you want to object zoomin, zoomout, move, roted. bounce etc.,

Example of code :

import UIKit

enum Axis {
    case x
    case y
    case both
}
extension UIView{
    func zoomAnimation(withDuration duration: Double, withZoomLevel zoomLevel: CGFloat, complition : ((Bool) -> Swift.Void)?)  {
        UIView.animate(withDuration: duration, animations: {
            self.transform = CGAffineTransform(scaleX: zoomLevel, y: zoomLevel)
        }) { _ in
            UIView.animate(withDuration: duration, animations: {
                self.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
            },completion : {_ in
                complition?(true)
            })
        }
    }
    
    func rotedAnimation(withDuration duration: Double,withAngle angle : CGFloat,withRepetation isRepeat:Bool , complition : ((Bool) -> Swift.Void)?) {
        if isRepeat
        {
            UIView.animate(withDuration: duration, delay: 0.0, options: .repeat, animations: {
                self.transform = self.transform.rotated(by: angle)
            }) { _ in
                complition?(true)
            }
        }
        else
        {
            UIView.animate(withDuration: duration, animations: {
                self.transform = self.transform.rotated(by: angle)
            }, completion: {_ in
                complition?(true)
            })
        }
    }
    
    func moveAnimation(withDuration duration : Double,withAxis axis:Axis,withAnimStepCount step:CGFloat,complition : ((Bool) -> Swift.Void)?) {
        let oldFrame = self.frame
        UIView.animate(withDuration: duration, animations: {
            if axis == .both
            {
                self.frame.origin.x += step
                self.frame.origin.y += step
            }
            else if axis == .y
            {
                self.frame.origin.y += step
            }
            else
            {
                self.frame.origin.x += step
            }
        }) { _ in
            UIView.animate(withDuration: duration, animations: {
                self.frame = oldFrame
            }, completion: { _ in
                complition?(true)
            })
        }
    }
    
    func bounceAnimation(withDuration duration : Double,withAxis axis:Axis,withBounceStepCount step:Int,withAxisStepCount bounceStep : CGFloat ,complition : ((Bool) -> Swift.Void)?) {
        let oldFrame = self.frame
        UIView.animate(withDuration: duration/Double(step), animations: {
            if axis == .x
            {
                self.frame.origin.x  += bounceStep
            }
            else
            {
                self.frame.origin.y += bounceStep
            }
        }, completion: { _ in
            UIView.animate(withDuration: duration/Double(step), animations: {
                if axis == .x
                {
                    self.frame.origin.x -= (bounceStep * 2)
                }
                else
                {
                    self.frame.origin.y -= (bounceStep * 2)
                }
            },completion:{_ in
                complition?(true)
                UIView.animate(withDuration: duration/Double(step), animations: {
                    self.frame.origin.x = oldFrame.origin.x
                    self.frame.origin.y = oldFrame.origin.y
                    
                },completion:{_ in
                    complition?(true)})
            })
        })
    }
}


You can put above code in file and easy to use
-> for example zoom-in object then

obj.zoomAnimation(withDuration: 1.0, withZoomLevel: 0.5, complition: nil)

-> zoom-out

obj.zoomAnimation(withDuration: 1.0, withZoomLevel: 1.5 ,complition: {_ in
            print("zoom complition")
        })

-> Bounce 

        sender.bounceAnimation(withDuration: 1.0, withAxis: .x, withBounceStepCount: 10, withAxisStepCount: 20, complition: nil)


For more info watch this video for different animation 
Github project link is available in video description 




Another example of Add to cart animation 



If you like my video then please like and subscribe and also share with iOS community.

Thank you.