Apple Challenge 1

/* A FunkyNotificationCenter object that broadcasts events within a program.

Code that wants to observe notification events registers a closure via the addObserver(:for:block:) method.

Code that sends notifications uses the post(notificationName:) method. Each closure that was registered for that notification name should be called. */

import Foundation

class FunkyNotificationCenter { typealias notifBlock = () -> Void var entries: [String: [notifBlock]] = [:] init() // mynotif, block1, block2 /// Post a notification with the given name. /// /// - Parameters: /// - name: The notification to post /// func post(notificationName: String) { // TODO // go through all entries // execute block //print(notificationName) if entries[notificationName] != nil { for entry in entries[notificationName]! { entry() } } }

/// Registers a closure to be called for a notification name.
/// When a notification is posted with the same name,
/// the provided closure will be called.
/// 
/// - Parameters:
///    - name: Notification name the object is observing
///    - block: Closure to be executed when the notification is posted
/// 
func addObserver(for notificationName: String, block: @escaping () -> Void) -> Void {
    // TODO.DONE
    //print(notificationName)
    if entries[notificationName] != nil {
        // existing entries
        // entries[notificationName]
        var current = entries[notificationName]
        current?.append(block)
        entries[notificationName] = current
    } else {
        // new entries
        entries[notificationName] = [block]
                print(notificationName)

    }
}

}

// Example Usage

let notificationCenter = FunkyNotificationCenter()

notificationCenter.addObserver(for: “MyNotification1”) { print(“Received notification: MyNotification1”) } notificationCenter.addObserver(for: “MyNotification1”) { print(“Received notification again: MyNotification1”) }

notificationCenter.post(notificationName: “MyNotification1”)

// Expected Output: // Received notification: MyNotification1 // Received notification again: MyNotification1

notificationCenter.post(notificationName: “MyNotification2”)

// Expected Output: none

Interview Questions

SSL Pinning

import Foundation

final class SampleNetworkManager: NSObject {
    private lazy var certificates: [Data] = {
        let url = Bundle.main.url(forResource: "ty", withExtension: "der")!
        let data = try! Data(contentsOf: url)
        return [data]
    }()
    
    private var session: URLSession!
    
    override init() {
        super.init()
        session = URLSession(configuration: .default, delegate: self, delegateQueue: nil)
    }
}

// MARK: - URLSessionDelegate
extension SampleNetworkManager: URLSessionDelegate {
    func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        if let trust = challenge.protectionSpace.serverTrust, SecTrustGetCertificateCount(trust) > 0 {
            if let certificate = SecTrustGetCertificateAtIndex(trust, 0) {
                let data = SecCertificateCopyData(certificate) as Data
                if certificates.contains(data) {
                    completionHandler(.useCredential, URLCredential(trust: trust))
                    return
                }
            }
        }
        completionHandler(.cancelAuthenticationChallenge, nil)
    }
}

This code is an example of how to implement SSL pinning in Swift using the URLSession API. The SampleNetworkManager class is a custom network manager that uses a URLSession to handle network requests.

The certificates property is a private lazy variable that loads a DER encoded certificate from the application’s main bundle using the Bundle class. The DER encoded certificate is loaded from a file named “ty.der”.

The session property is a private variable that holds a URLSession instance. It is initialized in the init() method of the class and sets the class as the delegate of the session.

The class conforms to the URLSessionDelegate protocol, and implements the urlSession(_:didReceive:completionHandler:) method. This method is called by the URLSession when a server’s certificate or public key is presented during an SSL/TLS handshake.

The method first checks if the server trust object, which holds the server’s certificate or public key, is not nil, and there are more than zero certificates. Then it retrieves the certificate at index 0 from the trust object. It then copies the data from the certificate, and checks if it exists in the certificates property. If it exists, it calls the completion handler with .useCredential and a new URLCredential object created with the trust object.

If the certificate data is not present in the certificates property, the completion handler is called with .cancelAuthenticationChallenge and nil, which will cancel the authentication challenge and the connection will fail.

In this way this code ensures that the server is presenting a certificate that is known and trusted by the app.

Swift iOS interview questions and answers • ishtiz.com #weblinks

Codable protocols allows easy conversion between loosely typed JSON and strong Swift type.

interview questions #weblinks