Search Your Question

What is KVO?

Key-value observing is the ability for Swift to attach code to variables, so that whenever the variable is changed the code runs. It’s similar to property observers (willSet and didSet ), except KVO is for adding observers outside of the type definition.


KVO isn’t terribly nice in pure Swift code, because it relies on the Objective-C runtime – you need to use @objc classes that inherit from NSObject, then mark each of your properties with @objc dynamic.


For example, we could create a Car class like this:


@objc class Car: NSObject {

    @objc dynamic var name = "BMW"

}


let bmw= Car()

You could then observe that user’s name changing like this:


bmw.observe(\Car.name, options: .new) { car, change in

    print("I'm now called \(car.name)")

}

That asks BMW to watch for new values coming in, then prints the person’s name as soon as the new value is set.


To try it out, just change the car's name to something else:


bmw.name = "Mercedese"

That will print “I’m now called Mercedese.”


Although KVO is unpleasant in pure Swift code, it’s better when working with Apple’s own APIs – they are all automatically both @objc and dynamic because they are written in Objective-C.


However, one warning: even though large parts of UIKit might work with KVO, this is a coincidence rather than a promise – Apple makes no guarantees about UIKit remaining KVO-compatible in the future.

What is Protocol Oriented Programming?

Protocol-Oriented Programming is a new programming paradigm ushered in by Swift 2.0. In the Protocol-Oriented approach, we start designing our system by defining protocols. We rely on new concepts: protocol extensions, protocol inheritance, and protocol compositions.

In Swift, value types are preferred over classes. However, object-oriented concepts don’t work well with structs and enums: a struct cannot inherit from another struct, neither can an enum inherit from another enum. 

On the other hand, value types can inherit from protocols, even multiple protocols. Thus, with POP, value types have become first-class citizens in Swift.

Pillars of POPs

Protocol Extensions
Protocols serve as blueprints: they tell us what adopters shall implement, but you can’t provide implementation within a protocol. What if we need to define default behavior for conforming types? We need to implement it in a base class, right? Wrong! Having to rely on a base class for default implementation would eclipse the benefits of protocols. Besides, that would not work for value types. Luckily, there is another way: protocol extensions are the way to go! In Swift, you can extend a protocol and provide a default implementation for methods, computed properties, subscripts, and convenience initializers. In the following example, I provided default implementation for the type method uid().

extension Entity {
    static func uid() -> String {
        return UUID().uuidString
    }
}
swift
Now types that adopt the protocol need not implement the uid() method anymore.

struct Order: Entity {
    var name: String
    let uid: String = Order.uid()
}
let order = Order(name: "My Order")
print(order.uid)
// 4812B485-3965-443B-A76D-72986B0A4FF4

Protocol Inheritance

A protocol can inherit from other protocols and then add further requirements on top of the requirements it inherits. In the following example, the protocol Persistable inherits from the Entity protocol I introduced earlier. It adds the requirement to save an entity to file and load it based on its unique identifier.

protocol Persistable: Entity {
    func write(instance: Entity, to filePath: String)
    init?(by uid: String)
}
swift
The types that adopt the Persistable protocol must satisfy the requirements defined in both the Entity and the Persistable protocol.

If your type requires persistence capabilities, it should implement the Persistable protocol.

struct PersistableEntity: Persistable {
    var name: String
    func write(instance: Entity, to filePath: String) { // ...
    }  
    init?(by uid: String) {
        // try to load from the filesystem based on id
    }
}
swift
Whereas types that do not need to be persisted shall only implement the Entity protocol:

struct InMemoryEntity: Entity {
    var name: String
}

Protocol inheritance is a powerful feature that allows for more granular and flexible designs.

Protocol Composition

Swift does not allow multiple inheritances for classes. However, Swift types can adopt multiple protocols. Sometimes you may find this feature useful.

Here’s an example: let’s assume that we need a type that represents an Entity.

We also need to compare instances of a given type. And we want to provide a custom description, too.

We have three protocols that define the mentioned requirements:

Entity
Equatable
CustomStringConvertible
If these were base classes, we’d have to merge the functionality into one superclass; however, with POP and protocol composition, the solution becomes:

struct MyEntity: Entity, Equatable, CustomStringConvertible {
    var name: String
    // Equatable
    public static func ==(lhs: MyEntity, rhs: MyEntity) -> Bool {
        return lhs.name == rhs.name
    }
    // CustomStringConvertible
    public var description: String {
        return "MyEntity: \(name)"
    }
}
let entity1 = MyEntity(name: "42")
print(entity1)
let entity2 = MyEntity(name: "42")
assert(entity1 == entity2, "Entities shall be equal")

This design not only is more flexible than squeezing all the required functionality into a monolithic base class but also works for value types.

Difference between compact map and Flat map

Compact Map :

Use this method to receive an array of nonoptional values when your transformation produces an optional value.

let scores = ["1", "2", "three", "four", "5"]

let mapped: [Int?] = scores.map { str in Int(str) }
// [1, 2, nil, nil, 5] - Two nil values as "three" and "four" are strings.

let compactMapped: [Int] = scores.compactMap { str in Int(str) } 

// [1, 2, 5] - The nil values for "three" and "four" are filtered out. 

Flat Map :

Use this method to receive a single-level collection when your transformation produces a sequence or collection for each element.

Map vs FlatMap
let scoresByName = ["Henk": [0, 5, 8], "John": [2, 5, 8]]

let mapped = scoresByName.map { $0.value }
// [[0, 5, 8], [2, 5, 8]] - An array of arrays
print(mapped)

let flatMapped = scoresByName.flatMap { $0.value }
// [0, 5, 8, 2, 5, 8] - flattened to only one array

CompactMap vs FlatMap

Used on a sequence and having a transformation returning an optional value, use CompactMap. If not, either map or flatMap should give you the results you need.

How to switch from background queue to main queue?

If you're on a background thread and want to execute code on the main thread, you need to call async() again. However, this time, you do it on DispatchQueue.main, which is the main thread, rather than one of the global quality of service queues.


DispatchQueue.global(qos: .userInitiated).async {

    if let url = URL(string: urlString) {

        if let data = try? Data(contentsOf: url) {

            self.parse(json: data)

            return

        }

    }

    self.showError()

}


func showError() {

    DispatchQueue.main.async {

        let ac = UIAlertController(title: "Loading error", message: "There was a problem loading the feed; please check your connection and try again.", preferredStyle: .alert)

        ac.addAction(UIAlertAction(title: "OK", style: .default))

        self.present(ac, animated: true)

    }

}


Sof here, If I want to work with UI-related stuff, I must switch queue to main. So to execute that code under  DispatchQueue.main.async { } block.

Difference between FCM and APNS

  • FCM is sent as JSON payloads and APNS sends either string or dictionary.
  • FCM has a payload of 2KB while APNS has a payload of 4KB.
  • APNS saves 1 notification per App while FCM saves 100 notifications per device.
  • FCM supports multiple platforms while APNS requires their proprietary platform.
  • Acknowledgment can be sent in FCM if using XMPP, but it's not possible on APNS.

Advatage of FCM

  • Even if the user disallows notification, you can notify your app if the app is running in the foreground (using shouldEstablishDirectChannel).
  • Don't need to create dashboard to send notification on the device.
  • Notification analytics on FCM Dashboard.
  • Easy to create notification payload structure.
  • App Server side handling is easy, Only one key is required for multiple apps and platform (iOS, Android, Web)