Search Your Question

Showing posts with label Swift. Show all posts
Showing posts with label Swift. Show all posts

Difference between encapsulation and abstraction.

Ans :

Encapsulation hides variables or some implementation that may be changed so often in a class to prevent outsiders access it directly. They must access it via getter and setter methods.
Abstraction is used to hiding something too but in a higher degree(class, interface). Clients use an abstract class(or interface) do not care about who or which it was, they just need to know what it can do.

Encapsulation: Wrapping code and data together into a single unit. Class is an example of encapsulation, because it wraps the method and property. 
Abstraction: Hiding internal details and showing functionality only. Abstraction focus on what the object does instead of how it does. It provides generalized view of classes.
int number = 5;
string aStringNumber = number.ToString(); 
Here, ToString() is abstraction. And how this mechanism number variable converted to string and initialize into aStringNumber is encapsulation.
We can achieve abstraction using protocol in iOS, achieve encapsulation using access control in class or struct.



Different types of Control statements.

Ans. 

Control flow statements are used to control the flow of execution in a program.

1. Loop Statement : 

For-in

let names = ["Anna", "Alex", "Brian", "Jack"]
for name in names {
    print("Hello, \(name)!")

}


While 
var i:Int = 0
while i < 10 {
    print(i)
    i += 1
}

repeat-while
var j: Int = 10
repeat {
   print(j)
}
while(j < 10)

2. Branch Statement : 

If-else
var numArray = [10, 20, 30, 40, 50, 60, 70]
if(numArray.contains(20)){
    print("true it contains 20")
}else{
    print("number is not there")
}

guard
guard condition else {
    statements
}

The else clause of a guard statement is required, and must either call a function with the Never return type or transfer program control outside the guard statement’s enclosing scope using one of the following statements:  
  • return 
  • break 
  • continue
  •  throw
Switch
switch grade {
    
case 90 ..< 100:
    print("A")
case (80 ..< 90):
    print("B")
case (70 ..< 80):
    print("C")
case (0 ..< 70):
    print("D")
    
default:
    print("F. You failed")//Any number less than 0 or greater than 99
    
}

3. Control Transfer Statement : 
continue 
let numbersArray = [20, 30, 40, 50, 60, 70, 80, 90, 10]
for num in numbersArray{
    if(num > 10){
        continue
    }
    print(num)
}

// prints: 10

break 
let numbersArray = [20, 30, 40, 50, 60, 70, 80, 90, 10]
for num in numbersArray{
    if num > 30{
        break
    }
    print(num)
}


fallthrough : switch statements don’t fallthrough the bottom of each case and into the next one. That is, the entire switch statement completes its execution as soon as the first matching case is completed.

for num in numbersArray{
    switch num {
    case 10:
        print(num)
    case 20:
        print(num)
    case 30:
        print(num)
        fallthrough
    case 40:
        print(num)
    default:
        print("nothing here")
    }
}

return :
func myFunc() -> Int {
    let myNumber = 16 % 3
    if myNumber == 0 {
        return 0
    }
    else if myNumber == 1 {
        return 1
    }
    return 0
}

throw
enum ErrorsToThrow: Error {
    case fileNotFound
    case fileNotReadable
    case fileSizeIsTooHigh
}
class documents {
    
    init() {
        do {
            let dataFromString = try? readFiles(path: "")
            print(dataFromString)
        } catch ErrorsToThrow.fileNotFound {
            print("error generated1")
        } catch ErrorsToThrow.fileNotReadable {
            print("error generated2")
        } catch ErrorsToThrow.fileSizeIsTooHigh {
            print("error generated3")
        } catch {
                print("error")
        }
    }
    
func readFiles(path:String) throws  ->String {
        if path == "" {
            throw ErrorsToThrow.fileNotFound
        }
        return "Data from file"

    }
}



What is capture and capture list in closure?

Ans :

According to apple document :

Closures are self-contained blocks of functionality that can be passed around and used in your code. Closures in Swift are similar to blocks in C and Objective-C and to lambdas in other programming languages. 

Closures can capture and store references to any constants and variables from the context in which they are defined. This is known as closing over those constants and variables. Swift handles all of the memory management of capturing for you.

Closure is reference type

Capturelist is used to stop memory leakage.

Code for Example of memory leakage :


class Increment {
    var number = 0

     deinit {
        print(#function)
    }
    
    lazy var incrementNumber: (Int) -> () = { value in
        self.number += value
        print(self.number)
    }
}

 do {
  let increment = Increment()

  increment.incrementNumber(3
 }


This will cause memory leak, the closure refers back to the object itself, it refers to self in order to increment the number, and that will create a reference cycle:

We have an object and the object has a stored property that refers to a closure.
That closure refers back to self (means Increment instance)

In above example, deinit should be called. But it never due to retain cycle created.

To Stop memory leakage we use capture list :

1. [unowned self]
2. [weak self]
3. [strong self] - Default

1.

lazy var incrementNumber: (Int) -> () = { [unowned self] value in
        self.number += value
        print(self.number)
    }

If I use [unowned self] there here less chance to crash. But if we use
let increment = Increment().incrementNumber(3)
then there will be more chance to be crashed. We can not immediately call incrementNumber method after object instantiated. Because when the stored property has returned, the object (increment instance) can be deallocated, nothing else is referring to it.

2.

 let’s change [unowned self] to [weak self], that means that everywhere that self is accessed, we treat it as a weak property. While using weak, we should use optional self? to access property.

When the stored property has returned, if the object be deallocated, mean self is nil, then the number will not be incremented. This code will make it easy to handle if self is nil

So when no clue to what to use, we should use [weak self] as capture list.





What is Generics in Swift? Write a program to make and use generics.

Ans :

Apple doc says: Generic code enables you to write flexible, reusable functions and types that can work with any type. You can write code that avoids duplication by using generics in most cases.

Code for Example :


 let intArray = [1,2,3,4,5] // type int
 let stringArray = [“abhi”, “iOS”] // type string



If we want to print all values, we have to make 2 functions accepting integer array or string array.
But using Generic, we can make 1 method accepting generic type.



 func printAnyArray<T>(arr:[T]) {
       arr.map { print($0) }

 }


 <T> after the function name represents a generic function. A generic function can work with whatever type. We can put whatever instead of T. T is placeholder type. We can use for dictionary like Dictionary<key,value> and for array like Array<element> .

Generic function with parameter type : 


//Declare
func anotherMethod<T, U> (first: T, second: U) { print("first one called")}
func anotherMethod<T> (first: T, second: T) { print("second one called")}
//Call
anotherMethod(first: 123, second: "456"// T - Int, U - String
anotherMethod(first: 123, second: 456// T - Int




In above methods, we use different placeholder type in method1 and same placeholder type in method2. If out passing parameter types are different then 2nd method will be called, and if same then 1st method will be called.

Generic function with type constraints :


func middleVal<T>(array: [T]) -> T? {
  guard !array.isEmpty else { return nil }
  return array.sorted()[(array.count - 1) / 2]
}

   

Sometimes, we require specific types only i.e type which confirm comparable protocol


func middleVal<T: Comparable>(array: [T]) -> T? {
  guard !array.isEmpty else { return nil }
  return array.sorted()[(array.count - 1) / 2]
}

    

Above method will only accepts. int, float, double.


If you have any comment, question, or recommendation, feel free to post them in the comment section below!  

Json serialization and deserialization

Ans :  


JSON is a format that encodes objects in a string. Serialization means to convert an object into that string, and deserialization is its inverse operation (convert string -> object).
When transmitting data or storing them in a file, the data are required to be byte strings, but complex objects are seldom in this format. Serialization can convert these complex objects into byte strings for such use. After the byte strings are transmitted, the receiver will have to recover the original object from the byte string. This is known as deserialization.

import UIKit

var str = "Hello, playground"

// Starting decode -> json to class or object
// ------------- De-Serialization ----------------

let singleDict = """
{
    "foodName" : "Banana"
    "calories" : 100
}
""".data(using: .utf8)

class Food: Codable {
    
    let foodname : String
    let calories : Int
    
    init(foodname: String, calories: Int) {
        self.foodname = foodname
        self.calories = calories
    }
}

let jsonDecoder = JSONDecoder()
do {
    let foodResult = try jsonDecoder.decode(Food.self, from: singleDict!)
    print(foodResult.foodname)
} catch {
    print("failed to decode \(error.localizedDescription)")
}

// Starting encode -> class or object to json
// ------------- Serialization ----------------

let apple = Food(foodname: "apple", calories: 80)
let jsonEncoder = JSONEncoder()
jsonEncoder.outputFormatting = .prettyPrinted
do {
    let jsonData = try jsonEncoder.encode(apple)
    if let jsonString = String(data: jsonData, encoding: .utf8) {
        print(jsonString)
    }
} catch {
    

}

What is Codable?
Codable is a type alias for the Encodable and Decodable protocols. When you use Codable as a type or a generic constraint, it matches any type that conforms to both protocols.

Before Swift 4, You’d have to serialize the JSON yourself with JSONSerialization, and then typecast every property of the JSON to the right Swift type. We have to do manually map data with struct (Model) properties.
If we are using Codable, then we don't required to map response data with struct property manually. If response's name is different then we can use CodingKey

struct User:Codable 
{
    var firstName: String
    var lastName: String
    var country: String

    enum CodingKeys: String, CodingKey {
        case firstName = "first_name"
        case lastName = "last_name"
        case country
    }
}


If you have any comments, questions, or recommendations, feel free to post them in the comment section below!

What is subscript?

Ans : 

Subscripts are used to access information from a collection, sequence and a list in Classes, Structures and Enumerations without using a method.

These subscripts are used to store and retrieve the values with the help of index without the use of separate method.

To access elements via subscripts write one or more values between square brackets after the instance name.

For example: Array elements are accessed with the help of someArray[index] and its subsequent member elements in a Dictionary instance can be accessed as someDicitonary[key].

Code :

In coding, subscript is same as computed property.



 class monthsInYear {
 private var months = [“Jan”, “Feb”, “Mar”, “Apr”, “May”, “Jun”, “Jul”, "Aug",  "Sep" , "Oct", "Nov" , "Dec"
 subscript(index: Int) -> String {

 get {
       return months[index] // getter is mandatory
  }
 set(newValue) {
       self.months[index] = newValue // setter is optional
     }
   }
 }
 var p = monthsInYear()
 print(p[0]) // prints Jan
 p[0] = “Jan”
 print(p[0]) // prints Jan



If you have any comment, question, or recommendation, feel free to post them in the comment section below!