Search Your Question

Showing posts with label Network18. Show all posts
Showing posts with label Network18. Show all posts

What are different type of Queues in GCD?

Ans :

Queue : 

A Queue is a linear structure that follows the First In First Out (FIFO) order. Here we are going to use two types of queue Serial queue and Concurrent queue.

Serial Queue : 


Serial Queue

In the serial queue, only one task runs at a time. Once the first task ends then only the second task will begin. All the task follow the same sequence they have to wait until running task finish.

Create our own serial queue using GCD:


let serialQueue = DispatchQueue(label: "mySerialQueue")
 serialQueue.async {
  // Add your serial task

 }

Download images using serial queue : 


let myArray = [img1, img2, img3, img4, img5, img6]
   
   for i in 0 ..< myArray.count {
     serialQueue.async {
       do {
         let data = try Data(contentsOf: URL(string: myArray[i])!)
         if let image = UIImage(data: data) {
           DispatchQueue.main.async {
             self.imageSerial[i].image = image
           }
         }
       } catch {
         print("error is \(error.localizedDescription)")
       }
     }

   }


Concurrent Queue : 


Concurrent Queue

In the Concurrent queue, multiple tasks can run at the same time. The start time of the task will be the order they are added, means Task 0 start first then Task 1 will start after that and so on. Tasks can finish in any order.

Global queue is example of Concurrent queue.


// Synchronous
DispatchQueue.global().sync {
 // write your code here
}

// Asynchronous
DispatchQueue.global().async {
 // write your code here
}

Let's create own concurrent queue using GCD: 


let concurrentQueue = DispatchQueue(label: "myConcurrentQueue", qos: .default, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)

 concurrentQueue.async {
  // Add your concurrent task
 }

Download images using concurrent queue:

let myArray = [img1, img2, img3, img4, img5, img6]

for i in 0 ..< myArray.count {
  concurrentQueue.async {
    do {
      let data = try Data(contentsOf: URL(string: myArray[i])!)
      if let image = UIImage(data: data) {
        DispatchQueue.main.async {
          self.imageConcurrent[i].image = image
        }
      }
    } catch {
      print("error is \(error.localizedDescription)")
    }
  }
}


What is NSNotification?

Ans :  Apple has provided an Observer Pattern in the Cocoa library called the NSNotificationCenter.

The basic idea is that a listener registers with a broadcaster using some predefined protocol. At some later point, the broadcaster is told to notify all of its listeners, where it calls some function on each of its listeners and passes certain arguments along. This allows for asynchronous message passing between two different objects that don't have to know about one-another, they just have to know about the broadcaster.

NSNotification is like notifying the other class about the changes that will happen if some action takes place in another class.

Simple :

NSNotificationCenter can be thought of as a broadcaster and we can tune into different stations, or channels to listen for any changes.

Example : 

NotificationCenter.default is where all notifications are posted to and are observed from. Each notification must have a unique way to identify themselves. If we were to observe, or listen, to any channel, we would call on the observe method available to us through NotificationCenter.default and perform some type of action based on this listening.

We have two view controllers named VC1 and VC2. We having observer in VC1 and when we select something in VC2, VC2 post notifications to observer methods.

VC1 :

 func setToIndia(notification: NSNotification) {
     cityChosenLabel.text = "India"
 }
 func setToPakistan(notfication: NSNotification) {
     cityChosenLabel.text = "Pakistan"

 }

Now, we create notification.name extension to set unique name to notification.

 extension Notification.Name {
     static let india = Notification.Name("India")
     static let  pakistan = Notification.Name("Pakistan")
 }

Now we add observer methods,


 NotificationCenter.default.addObserver(self, selector:   #selector(setToIndia(notification:)), name: .india, object: nil)

 NotificationCenter.default.addObserver(self, selector:  #selector(setToPakistan(notfication:)), name: .pakistan, object: nil)


VC2:

We will post notification on selecting something here :


 @IBAction func indiaButton(_ sender: Any) {
     NotificationCenter.default.post(name: .india, object: nil)
 }

 @IBAction func pakistanButton(_ sender: Any) {
      NotificationCenter.default.post(name: .pakistan, object: nil
 }


* When indaButton clicked, Notification Center broadcast notification with message to all listeners name India. 

If you didn't understand still, consider notification center is radio station and our mobile device has observer methods so it can listen radio station's voice.

Simple.....Huah.....






What is lazy loading?

Ans :  Lazy Loading Images is a technique to resolve loading image from the web. The thing is that, I need to display images directly from the web in UIImageView or any other control. 

For this, if you simply try to set the image using in-built setImage method then your application gets stuck while loading image from the web. To overcome this issue, there is a technique generally known as Lazy Loading Image. The thing actually happening in lazy loading is that the task of image loading from web is performed in background and at that time a temporary placeholder image is displayed in the control. When the actual image is fully loaded from the web, it is replaced with the placeholder image and you get your actual image on the control without having stuck interface.

You can use third party library to load image :  SDWebImage

Try to make own coding for loading image from URL and Save in cache and display in imageView.



Difference between KVO and KVC and Delegate

Ans : There is no way to find any differences between KVC and KVO. Both are different things.

1. KVC - Key Value Coding

We can get and set value of class property using string.

Code for example :

import UIKit

class Employee : NSObject {
    @objc var name = String()
    @objc var age = 0
    @objc var assets = ["ID Card", "Macbook"]

}

We should make sure that Employee inherits from NSObject because it confirms protocol named NSKeyValueCodiing.

We also make sure that @objc should be added as it is objective c runtime for making those properties available for coding. emp.setValue("Manna", forKeyPath: #keyPath(<#T##@objc property sequence#>))

Using KVC,
let emp = Employee()
emp.setValue("Manan", forKey: "name")

Here, we set value of name property using string "name". Here there is chance to misspell property name.

Another way,

emp.setValue("Manna", forKeyPath: #keyPath(Employee.name))

Benefit of this way,  There is no any chance to misspell as it only accepts valid key path other wise it gives compile time error.

Another way,

emp.setValuesForKeys([
                        "name" : "Manan",
                        "age"  : 29

                ])

What will happened, if we have some private properties in class. They are not accessible directly using their value. We have to make extension of class to use their values.
or

@objc private var name = String()

emp.setValue("Manan", forKey: "name")
emp.value(forKey: "name")

We can access private properties as above using KVC. emp.name will give compile time error as name is private,  but using KVC it is possible to access.

We can access array and add item in this array,

let mutableArray = emp.mutableArrayValue(forKeyPath: #keyPath(Employee.assets))
mutableArray.add("Laptop Bag")


2. KVO - Key value observer

When we want to do something when property values changes, we can use KVO concept. We can observer property and on value changed we can take action.

For that,
A special method named observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) should be implemented to the observing class.


self.child1.addObserver(self, forKeyPath: "name",  optional: [.new, .old], context: child1context]


There are some parameters :

  • addObserver:  This is the observing class, usually the self object. 
  • forKeyPath: I guess you can understand what’s this for. It is the string you used as a key or a key path and matches to the property you want to observe. Note that you specify here either a single key, or a key path. 
  • options: an array of NSKeyValueObservingOptions values. 
  • context: This is a pointer that can be used as a unique identifier for the change of the property we observe. Usually this is set to nil or NULL. We’ll see more about this later.
We have to implement  following observerValue method and it is mandatory to adopt KVO concept.




Sometimes, we don't want notification when some  property value changed. Then we do following :


Credit : HackerMoon

Know more about KVO : Click here

Difference between Delegate, Notification and KVO


Use a delegate if you want to talk to only one object. For example, a tableView has a delegate - only one object should be responsible for dealing with it.

Use notifications if you want to tell everyone that something has happened. For example in low memory situations, a notification is sent telling your app that there has been a memory warning. Because lots of objects in your app might want to lower their memory usage it's a notification.

I don't think KVO is a good idea at all and try not to use it but, if you want to find out if a property has changed you can listen for changes.

What is closure? Why we use closure instead of function sometime?

Ans : 

The two most used cases are completion blocks and higher order functions in Swift. 

Completion blocks: for example, when you have some time consuming task, you want to be notified when that task is finished. You can use closures for that, instead of a delegate (or many other things)


func longAction(completion: () -> ()) {
    for index in veryLargeArray {
        // do something with veryLargeArray, which is extremely time-consuming
    }
    completion() // notify the caller that the longAction is finished
}

//Or asynch version
func longAction(completion: () -> ()) {
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
        
        for elem in veryLargeArray {
            // do something with veryLargeArray, which is extremely time-consuming
        }
        dispatch_async(dispatch_get_main_queue(), {
            completion() // notify the caller that the longAction is finished
        })
    }
}

longAction { print("work done") }

In the example above, when you have a time consuming task, you want to know when the for loop finishes iterating through the very large array. You put the closure { println("work done") } as an input parameter for the function which will be executed after the for loop finishes its work, and print "work done". And what happened is that you gave a function (closure) to longAction and name it to completion, and that function will be executed when you call completion in longAction.

Sorted method works using closure.

About how sorted (probably) works: So the idea is, that sorted will go through the array, and compare two consecutive elements (i, i + 1) with each other, and swap them, if needed. What does it mean "if needed"? You provided the closure { (s1: String, s2: String) -> Bool in return s1 > s2 }, which will return true if s1 is greater than s2. And if that closure returned true, the sorted algorithm will swap those two elements, and continues this with the next two elements (i + 1, i + 2, if the end of the array is not reached). So basically you have to provide a closure for sorted which will tell "when" to swap to elements.

Understand Closure


Difference Between If Let And Guard Let?

Ans : 

Basic Difference :

Guard let 

Early exist process from the scope
Require score existing like return, Throw etc.
Create a new variable those can be access out the scope.

if let 

Can not access out the scope.
no need to return statement. But we can write

Note : Both are used to unwrapped the Optional variable.


Guard let


  • A guard statement is used to transfer program control out of a scope if one or more conditions aren’t met. 
  • The value of any condition in a guard statement must be of type Bool or a type bridged to Bool. The condition can also be an optional binding declaration.


guard condition else { //Generally return }
func submit() {
guard let name = nameField.text else {
    show("No name to submit")
    return

}

If let
  • Also popular as optional binding 
  • For accessing optional object we use if let
if let roomCount = optionalValue {
        print("roomCount available")
} else {
       print("roomCount is nil")

}



Q. return is mandatory in guard let statement ?
A. Exit is mandatory in guard let statement. So return or throw is mandatory in guard let. Otherwise it gives compile time error.


What is lazy property?

Ans : 

When to use lazy initialization is when the initial value for a property is not known until after the object is initialized.

For example, if you have a Person class and a personalizedGreeting property. The personalizedGreeting property can be lazily instantiated after the object is created so it can contain the name of the person.

class Person {      
  var name: String
    
  lazy var personalizedGreeting: String = {
    return "Hello, \(self.name)!"
  }()
    
  init(name: String) {
    self.name = name
  }
}

When you initialize a person, their personal greeting hasn’t been created yet:

let person = Person(name: "John Doe") // person.personalizedGreeting is nil But when you attempt to print out the personalized greeting, it’s calculated on-the-fly:

NSLog(person.personalizedGreeting)

Bonus Tip : You do need to declare your lazy property using the var keyword, not the let keyword, because constants must always have a value before initialization completes.

Benefit of lazy property increase performance in terms of speed.

Multi threading, GCD, Operation Queue

Ans : 

1.
Thread : It is lightweight way to implement multiple paths of execution inside of an application.

2. Multi threading : iPhone CPU can only perform one operation at a time – once per clock cycle. Multi threading allows the processor to create concurrent threads it can switch between, so multiple tasks can be executed at the same time.

It appears as if the two threads are executed at the same time, because the processor switches rapidly between executing them. As a smartphone or desktop user, you don’t notice the switches because they occur so rapidly.

Multi threading allows a CPU to rapidly switch between multiple tasks in such a way that it appears as if the tasks are executed simultaneously.

You can’t update an app’s UI outside the main thread.

Race Condition  A race condition occurs when two tasks are executed concurrently, when they should be executed sequentially in order to be done correctly. You cant change view constraint while it is being calculated. So UI activity should be done in main thread so it is executed sequentially.


3. GCD : Grand Central Dispatch is a wrapper around creating threads and managing that code. Its emphasis is on dispatching. The Grand Central Dispatch (GCD) is a is a low-level API provided by Apple. GCD is used for managing concurrent operations. GCD has lots of benefits like

– It improves application performance and responsiveness.
– The app will become more smooth.
– Execute multiple tasks at a time or one by one as per your requirements.
GCD operates at the system level, it is managing the resources in a balanced way for all running application.



GCD & Operation Queues help keep your app user interface responsive by running slow task of main queue.

low_level_C coding :

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
    // Download file or perform expensive task

    dispatch_async(dispatch_get_main_queue()) {
        // Update the UI
    }
}

Swift 3+ code :

DispatchQueue.global(qos: .userInitiated).async {
    // Download file or perform expensive task

    DispatchQueue.main.async {
        // Update the UI
    }
}

There are 4 qos - quality of service level (Priority) from higher to low :

.userInteractive,
.userInitiated,
.utility
.background.

Learn more about QOS

For delaying task :

let delay = DispatchTime.now() + .seconds(60)
DispatchQueue.main.asyncAfter(deadline: delay) {
    // Dodge this!
}

Multi threading, GCD, Operation Queue

Ans : 

1.
Thread : It is lightweight way to implement multiple paths of execution inside of an application.

2. Multi threading : iPhone CPU can only perform one operation at a time – once per clock cycle. Multi threading allows the processor to create concurrent threads it can switch between, so multiple tasks can be executed at the same time.

It appears as if the two threads are executed at the same time, because the processor switches rapidly between executing them. As a smartphone or desktop user, you don’t notice the switches because they occur so rapidly.

Multi threading allows a CPU to rapidly switch between multiple tasks in such a way that it appears as if the tasks are executed simultaneously.

You can’t update an app’s UI outside the main thread.

Race Condition  A race condition occurs when two tasks are executed concurrently, when they should be executed sequentially in order to be done correctly. You cant change view constraint while it is being calculated. So UI activity should be done in main thread so it is executed sequentially.


3. GCD : Grand Central Dispatch is a wrapper around creating threads and managing that code. Its emphasis is on dispatching.

low_level_C coding :

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
    // Download file or perform expensive task

    dispatch_async(dispatch_get_main_queue()) {
        // Update the UI
    }
}

Swift 3+ code :

DispatchQueue.global(qos: .userInitiated).async {
    // Download file or perform expensive task

    DispatchQueue.main.async {
        // Update the UI
    }
}

There are 4 qos - quality of service level (Priority) from higher to low :

.userInteractive,
.userInitiated,
.utility
.background.

For delaying task :

let delay = DispatchTime.now() + .seconds(60)
DispatchQueue.main.asyncAfter(deadline: delay) {
    // Dodge this!
}

4. Operation Queue : 

Operations in Swift are a powerful way to separate responsibilities over several classes while keeping track of progress and dependencies. They’re formally known as NSOperations and used in combination with the OperationQueue.

An Operation is typically responsible for a single synchronous task. It’s an abstract class and never used directly. You can make use of the system-defined BlockOperation subclass or by creating your own subclass. You can start an operation by adding it to an OperationQueue or by manually calling the start method. However, it’s highly recommended to give full responsibility to the OperationQueue to manage the state.

//Making use of the system-defined BlockOperation looks as follows:

let blockOperation = BlockOperation {
    print("Executing!")
}

let queue = OperationQueue()
queue.addOperation(blockOperation)
//And can also be done by adding the block directly on the queue:

queue.addOperation {
  print("Executing!")
}

//The given task gets added to the OperationQueue that will start the execution as soon as possible.

Different states of an operation
An operation can be in several states, depending on its current execution status.
  • Ready: It’s prepared to start
  • Executing: The task is currently running
  • Finished: Once the process is completed
  • Canceled: The task canceled


Explain Apple push notification working

Ans : Push notifications allow developers to reach users and perform small tasks even when users aren’t actively using an app.

In iOS 10, User can do following task :

  • Display a short text message
  • Play a notification sound
  • Set a badge number on the app’s icon
  • Provide actions the user can take without opening the app
  • Show a media attachment
  • Be silent, allowing the app to wake up in the background and perform a task
Now following steps to follow to configure push notification :

1. Create app id in developer account with your app bundle id. Push notification entitlement must be enabled for this app id. (or another way for go to App Settings > Capabilities and enable push notification switch). You also have to create CSR(Certificate Signing Request) file from your keychain and assign to this app id push notification feature in developer account.

2. Now in terms of coding, first we need to ask to user for allowing user notification. After allowing, we need to register for remote notification. If all goes good, system provides you 'token' which is address of this app for this device.

3. In code, first import usernotification. Then for registering for remote notification, in didFnishLaunchingWithOptions

UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge])  {
    (granted, error) in
   
       print("Permission granted: \(granted)")
    
       guard granted else { return }
       self.getNotificationSettings()

  }

 func getNotificationSettings()  {
       UNUserNotificationCenter.current().getNotificationSettings { (settings) in
       print("Notification settings: \(settings)")
       guard settings.authorizationStatus == .authorized else { return }
       UIApplication.shared.registerForRemoteNotifications()
  }


4. If registered for remote notification successfully, then one of the following two method will be called,

func application(_ application: UIApplication,
                 didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)  {

       let tokenParts = deviceToken.map { data -> String in
              return String(format: "%02.2hhx", data)
        }

       let token = tokenParts.joined()
       print("Device Token: \(token)")
}

func application(_ application: UIApplication,
                 didFailToRegisterForRemoteNotificationsWithError error: Error)  {
  print("Failed to register: \(error)")
}

5. Device token is provided by APNS and this token will be converted to string. This device token shold be sent to application server or stored to database on server side.

Now lets study about payload or notification message,

Payload looks like :

{
  "aps": {
    "alert": "Breaking News!",
    "sound": "default",
    "link_url": "https://raywenderlich.com"
  }
}

aps is fixed key in payload dictionary json. aps is also dictionary itself.

alert : Display text message
sound : Which sound when notification come
link_url : custom key, we can any such custom key for data
badge : number of count of badge that is displayed on app icon
category : which type of custom action notification have

Payload maximum size is 4096 kb (4 mb).


Now what when notification comes

1. If app is closed didFinishLaunchingWithOptions is called.
2. If open in background or foreground, then didReceiveRemoteNotification is called.

For 1st case,

In didFinishLaunchingWithOptions method
// Check if launched from notification

if let notification = launchOptions?[.remoteNotification] as? [String: AnyObject] {

  let aps = notification["aps"] as! [String: AnyObject]
  _ = NewsItem.makeNewsItem(aps)

  (window?.rootViewController as? UITabBarController)?.selectedIndex = 1
}

For 2nd case,

In didReceiveRemoteNotification,

let aps = userInfo["aps"] as! [String: AnyObject]
  _ = NewsItem.makeNewsItem(aps)

Actionable Notification

Actionable notifications let you add custom buttons to the notification. You can put reply,retweet,like button as you seen our favourite apps. This type of notification can be defined by Category.

In this type notification, we have to register category like following instead of UIApplication.shared.registerForRemoteNotifications().

func registerForPushNotifications() {
  UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) {
    (granted, error) in   
    print("Permission granted: \(granted)")
 
    guard granted else { return }
 
    // 1
    let viewAction = UNNotificationAction(identifier: viewActionIdentifier,
                                          title: "View",
                                          options: [.foreground])
 
    // 2
    let newsCategory = UNNotificationCategory(identifier: newsCategoryIdentifier,
                                              actions: [viewAction],
                                              intentIdentifiers: [],
                                              options: [])
    // 3
    UNUserNotificationCenter.current().setNotificationCategories([newsCategory])
 
    self.getNotificationSettings()
  }
}


Above things is not enough for taking action on button. We have to add extension of UNUserNotificationCenterDelegate.

Silent Notification 

If we want to do something task without knowing to user in background, then we can send silent notification to user device. For this background modes of push notification must be checked. For push notification aps, there is key named content-available. That's value should be 1 for silent notification.

For more detail, click here.



What is delegate?

Ans : Delegate is means of communication between objects of iOS Applications. Delegate allows one object to send message to another object when an event occurs.

i.e
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@”title” message:@”message” delegate:self cancelButtonTitle:@”Ok” otherButtonTitle:nil];

Here delegate is self. So now self is responsible for handling  all event fired by this instance of UIAlertView class.

Which button of UIAlertView is clicked, for that, event is clickedButtonAtIndex is called in or by Self or currentViewController.

Create PreDefined delegate :

  1. There are two ViewController NameVC and SurNameVC.
  2.  In NameVC, there are 2 textfield named as Name and FullName and 1 button as Submit.
  3. If I write in name and click on submit, it went to SurNameVC to take Surname parameter.
  4. On SurNameVC, after write Surname, on clicking of Submit, It call delegate method and went back to NameVC and Print Full Name in FullName textfield.

Implement above delegate and protocol in Objective-C : 


I have made protocol on SurNameVC like
    @protocol SurNameVCDelegate
      -(void)setSurName:(NSString *) strSurName;
    @end
    
    @property (nonatomic, retain) id delegate;

Now on NameVC submit button click, choose delegate of  SurNameVC object as self.

   objSurNameVC.delegate = self

and create method -(void)setSurName:(NSString *) strSurName;

on NameVC and it is called from surNameVC submit button. So setSurName is delegate method. We can print fullname by concatenating Name and Surname in FullName textfield.

So we delegate just pass message from one view controller to another view controller by delegate method.

Implement delegate and protocol in Swift

I have made custom UISlider. I want to send some value from custom UISlider value changed to view controller in which it is used. So for that, I have used delegate - protocol method.

customSlider.swift  Custom Slider file


import UIKit
protocol SliderDelegate: class {
    func sliderValueChanged(_ sender : UISlider)
}


class mpgpsSlider: UIView {
     
      weak var delegateSliderDelegate?

      required init?(coder aDecoder: NSCoder) {

        super.init(coder: aDecoder)
        
        let bundle = Bundle.init(for: type(of: self))
        let nib = UINib(nibName: "Slider", bundle: bundle)
        let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
        view.frame = bounds
        view.autoresizingMask = [.flexibleWidth,.flexibleHeight]
        addSubview(view)
        
        slider.addTarget(self, action: #selector(sliderValueChanged(_:)), for:                  .valueChanged)
    }

     @objc func sliderValueChanged(_ sender : UISlider)  {
        delegate?.sliderValueChanged(sender)
      }

}

ViewController.swift ViewController in which custom slider is used.

import UIKit

class VehicleProfileVC: BaseViewController,SliderDelegate{
    
    override func viewDidLoad() {
        super.viewDidLoad()
        slider.delegate = self
    }
    
    func sliderValueChanged(_ sender: UISlider) {
        label.text = String(sender.value)
    }
}