Search Your Question

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.....






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 error and exception? Difference between exception and error

Ans : 

Exception and Error is of course different. Following explanation in given for considering Objective-C.

Exception : Exceptions cause applications to crash if left unhandled. They generally occur when trying to perform an operation on an object incorrectly, such as using an out-of-bounds index to access an array item, or passing nil to a method that doesn’t accept it. In other words, they are caused by developer mistakes. Unhandled exceptions in your published apps must be avoided at all costs.

They are warnings to developers that a serious coding issue has occurred and needs to be fixed. They are expected to occur during development of you application, and provide information that will help you solve the issue before shipping your app.

In Objective-C, NSException is there to handle unwanted exception. This class contains 3 key points of information :

Name : Name identifies the type of exception that has occurred. The name property is used as the high level categorization.

Reason : Reason is a short explanation of why the exception has been thrown. For example “+[Class Selector] unrecognized selector sent to class 0x10866fb88”.

Userinfo : UserInfo is an NSDictionary of additional information that can help to debug the problem.

Error Errors don’t get thrown, and they don’t cause the application to crash. They are created to hold information about a failure

Errors in iOS are represented by the NSError class which provides these 3 properties:

domain is a high level grouping of errors.

code is used to distinguish different types of errors within a domain.

userInfo is an NSDictionary containing additional information about the error.

Exceptions are caused by programming faults, and must be fixed or handled. Errors are expected to happen from time to time and should be dealt with accordingly.



What is protocol extension? Why Swift called as Protocol Oriented Language?

Ans : It is same as we extend class to add functions to existing class. Here we can add functions to existing protocol by extending protocol.

protocol proto {
   func add()
}

extension proto {
   func sub()

}

Benefits :

1.

We can also add default body to protocol extension function. So any type which confirm protocol has choice to implement that method or not. In other words we can say that it become optional method. Protocol extension method must have body.

protocol proto {
    func add()
}

extension proto {
    func add()  {
        print("add method called")
    }
    
    func sub() { }
}

class cp : proto {
   
}

let pq = cp()
pq.add()



Output : 
add method called

2. 

We can confirm multiple protocol and we can say that is multiple inheritance.

protocol proto1 {
    func add()
}

protocol proto2 {
    func sub()
}

class cp : proto1,proto2 {
    func add() {
        
    }
    
    func sub() {
        
    }
}

let pq = cp()
pq.add()

3. 

We can make protocol comparable due to protocol extension.

protocol Score: Comparable {
  var value: Int { get }
}

struct RacingScore: Score {
  let value: Int
  
  static func <(lhs: RacingScore, rhs: RacingScore) -> Bool {
    lhs.value < rhs.value
  }

}

4.

Mutating function in protocol to change value of protocol.

Struct is value type. You can only change property of struct only if property declared as var and instance is also var.



So, if we add mutating before func, it allow to change value in struct type. Same thing also can be done with protocol and protocol extension.

5.

There's also obviously anything that you can do with generics in Swift that couldn't be done in Objective C.  So for instance the Indexable protocol could be extended to have a function that returned the index range length which might only apply if the index is an Int like this:

extension Collection where Self.Index == Int
{
  func length () -> Int
  {
     return endIndex - startIndex
  }

}


Due to this very powerful features of protocol in Swift, Swift is called Protocol Oriented  Programming Language.


What is accuracy of GPS location?

Ans : 

CLLocationAccuracy class provides accuracy constant.

kCLLocationAccuracyKilometer:
Accurate to the nearest kilometer.


kCLLocationAccuracyBestForNavigation:
The highest possible accuracy that uses additional sensor data to facilitate navigation apps. 
kCLLocationAccuracyBest:
The best level of accuracy available.
kCLLocationAccuracyNearestTenMeters:
Accurate to within ten meters of the desired target. 
kCLLocationAccuracyHundredMeters:
Accurate to within one hundred meters.
kCLLocationAccuracyThreeKilometers:
Accurate to the nearest three kilometres.



What is UIResponder Chain?

Ans : 

Apps receive and handle events using responder objects. A responder object is any instance of the UIResponder class, and common subclasses include UIView, UIViewController, and UIApplication. UIKit manages most responder-related behavior automatically, including how events are delivered from one responder to the next.

Example : 

For every event, UIKit designates a first responder and sends the event to that object first. The first responder varies based on the type of event. 

UIKit uses view-based hit testing to determine where touch events occur. Specifically, UIKit compares the touch location to the bounds of view objects in the view hierarchy. The hitTest:withEvent: method of UIViewwalks the view hierarchy, looking for the deepest subview that contains the specified touch. That view becomes the first responder for the touch event. 

If a touch location is outside of a view’s bounds, the hitTest:withEvent: method ignores that view and all of its subviews. As a result, when a view’s clipsToBounds property is NO, subviews outside of that view’s bounds are not returned even if they happen to contain the touch.

UIResponder Chain
  • If the view is the root view of a view controller, the next responder is the view controller. 
  • If the view is not the root view of a view controller, the next responder is the view’s superview. 
  • If the view controller’s view is the root view of a window, the next responder is the window object. 
  • If the view controller was presented by another view controller, the next responder is the presenting view controller. 
  • UIWindow. The window’s next responder is the application object. 
  • UIApplication. The app object’s next responder is the app delegate, but only if the app delegate is an instance of UIResponder and is not a view, view controller, or the app object itself.

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 AutoReleasePool?

Ans : 

In simple word, it is pool contained objects that will be released in some time.

Object's retain and release is constant action on object. For that Retain() and Release() methods called in objective c to control memory flow. As iOS objects work on retain count concept, it tells retain counts and it will be released if it reaches to 0.

Sometimes, we can not continuously use Release() method to release object.

Code for example :

 -(NSString *)getCoolLabel {
    NSString *label = [[NSString alloc] initWithString:@"SwiftRocks"];
    [label release];
    return label;
 }

    

Here label has 2 retain count and after return it has 1 retain count. It will be in memory as we can not execute release after return label; statement.

So solution :
return [label autorelease];
It will not release label instantly, but it inserts label in pool, and in some time, when autorelease pool thread execute, it

Note : Instead of instantly reducing the retain count of an object, autorelease() adds the object to a pool of objects that need to be released sometime in the future, but not now. By default, the pool will release these objects at the end of the run loop of the thread being executed, which is more than enough time to cover all usages of getCoolLabel() without causing memory leaks.

Whatever code that takes much memory we can add in autoreleasepool block.
I.e

@autoreleasepool {
           NSString *contents = [self getFileContents:files[i]];
           NSString *emojified = [contents emojified];
           [self writeContents:contents toFile:files[i]];

       }

Above all code written in objective - c, but in swift AutoReleasePool is required?

Yes, it depends on code.  It’s a different story if your code is dealing with legacy Obj-C code, specially old Foundation classes in iOS.

To put it short, autoreleasepool is still useful in iOS/Swift development as there are still legacy Obj-C classes in UIKit and Foundation that call autorelease, but we not have to worry where there is pure swift code.