Home

Awesome

Awesome iOS Developer Join the chat at https://gitter.im/awesome-ios-developer/community

<p> <!-- %%%%%%%%%%%%%%%%%%%%%%% %%%%%%UPDATE LIST%%%%%% %%%%%%%%%%%%%%%%%%%%%%% git useful https://www.gitkraken.com/ -> similar with git tower https://www.git-tower.com/mac -> observe filehistory https://kaleidoscope.app -> diff file manager reduce build time when TDD line 1819 add more description add more description about router service pattern add TCA description add domain pattern(layer) + robot testing in ios add dependency inversion + add service locator + dependency container add description about coordinator pattern add modular architecture add description for tuist template add useful debugging in XCode(Youtube iOS) + need to add more with pic using fastlane + periphery dependency container AR Kit add add book for debugging( ray wenderlich) add service locator pattern composition layer -sil option for optimization build for swift compile SwiftGen - auto generate string & asset enum opensource apple developer tutorial video link update --> <p align="center"> <img alt="awesome" src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" /> <a href="https://hits.seeyoufarm.com"> <img src="https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2Fjphong1111%2FUseful_Swift&count_bg=%2379C83D&title_bg=%23555555&icon=&icon_color=%23E7E7E7&title=hits&edge_flat=true"/> </a> </p> <p align="center"> 🌟Feel free to contribute this Repository!!🌟 </p>

πŸ”Ž Content

Coding convention

set of guidelines for a specific programming language that recommend programming style

Swift Style Guide

Swift Lint

The way of force you to adapt coding convention

otherwise project build will FAILED

if which swiftlint >/dev/null; then
  swiftlint
else
  echo "error: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
  exit 1
  fi

put .yml file into root folder and apply following code in Build Phases

You can modify(delete) SwiftLint Option with opening .yml file

Shift + Command + . will show the hidden file

<img src="https://github.com/jphong1111/Useful_Swift/blob/main/Images/swiftLintChange.png">

πŸ“šπŸ“š Recommend Book πŸ“šπŸ“š

Book NameAuthors Name
Clean Code: A Handbook of Agile Software CraftsmanshipRobert C. Martin
The Pragmatic Programmer Your Journey to Mastery, 20th Anniversary EditionAndrew Hunt David Hurst Thomas

App Life Cycle

iOS App Life Cycle

<p align="right"> <a href="#-content">Back to Content</a> </p>

ViewController Life Cycle

<img src = "https://github.com/jphong1111/awesome-ios-developer/blob/main/Images/iOSViewLifeCycle.png" width="70%" height="70%"/>

iOS View Controller Life Cycle

<p align="right"> <a href="#-content">Back to Content</a> </p>

Design Pattern

Check this website for design pattern in Swift

Adaptor

Adapter pattern is a structural design pattern that is useful for composing classes and objects into a larger system.

protocol Target {
    func request()
}

class Adaptee {
    func specificRequest() {}
}

class Adapter: Target {
    let adaptee: Adaptee
    
    init(adaptee: Adaptee) {
        self.adaptee = adaptee
    }
    
    func request() {
        adaptee.specificRequest()
    }
}

Coordinator

Delegation

Delegation is a design pattern that enables a class to hand off (or β€œdelegate”) some of its responsibilities to an instance of another class.

Example

Create a protocol

protocol SomeProtocol: AnyObject {
    func reload()
}

Create a delegate

weak var delegate: SomeProtocol?

You can check the code using delegation pattern here

Dependency Injection

Dependency injection is a pattern that can be used to eliminate the need for singletons in a project

  1. Raise Transparency
  2. Improve Testability

Type of Dependency Injection

1. initializer injection

class DataManager {

   private let serializer: Serializer

   init(serializer: Serializer) {
       self.serializer = serializer
   }

}

2. property injection

import UIKit

class ViewController: UIViewController {

   var requestManager: RequestManager?

}

3. method injection

import Foundation

class DataManager {

   func serializeRequest(request: Request, withSerializer serializer: Serializer) -> Data? {
       ...
   }

}

Nuts and Bolts of Dependency Injection in Swift

Factory

Factory method is a creational design pattern which solves the problem of creating product objects without specifying their concrete classes.

Observer

Observer is a behavioral design pattern that allows some objects to notify other objects about changes in their state.

<img src = "https://github.com/jphong1111/Useful_Swift/blob/main/Images/observer.png" />

Check following sites

TBD

KVO

KVO stands for Key Value Observing

KVC

KVO vs KVC

We are using KVC in Storyboard!

<p align="right"> <a href="#-content">Back to Content</a> </p>

Singleton

singleton pattern is to ensure only one instance of a class is alive at any one time.

class SingletonPattern {
    static let manager = SingletonPattern()
    
    private init() {}
}
<p align="right"> <a href="#-content">Back to Content</a> </p>

Swift DocC

Swift-DocC is a documentation compiler for Swift frameworks and packages aimed at making it easy to write and publish great developer documentation.

Simple goes to Product-Build Documentation and DocC will open

Code Structuring(Architecture)

πŸ“šπŸ“š Recommend Book πŸ“šπŸ“š

Book NameAuthors Name
Advanced iOS App Architecture : Real-world app architecture in Swiftraywenderlich Tutorial Team
Clean Architecture: A Craftsman's Guide to Software Structure and DesignRobert Martin

Clean Architecture

<img src="https://github.com/jphong1111/Useful_Swift/blob/main/Images/Clean_Architecture.png">

Clean Architecture

MVC

MVC pattern stands for Model - View - Controller

<img src="https://github.com/jphong1111/Useful_Swift/blob/main/Images/MVCModel.png">

MVP

<img src ="https://github.com/jphong1111/awesome-ios-developer/blob/main/Images/MVPdesign.png" />

MVVM

MVVM patterns stand for Model - View - ViewModel

MVC vs MVVM

<img src="https://github.com/jphong1111/Useful_Swift/blob/main/Images/MVVMvsMVC.png" width = "60%" height = "60%">

You can check App example of using MVVM here

VIPER

<img src="https://github.com/jphong1111/Useful_Swift/blob/main/Images/Viper.png">

Getting Started with the VIPER Architecture Pattern

The Composable Architecture

The Composable Architecture is a library for building applications in a consistent and understandable way, with composition, testing, and ergonomics in mind

<img src="https://github.com/jphong1111/Useful_Swift/blob/main/Images/SCA.png">
// example will update here

Reducer

A reducer describes how to evolve the current state of an application to the next state, given an action, and describes what Effects should be executed later by the store, if any.

<p align="right"> <a href="#-content">Back to Content</a> </p>

Repository Pattern

The Repository and Unit of Work Patterns

UIDesign

HIG(Human Interface Guidelines)

SwiftUI

SwiftUI is a user interface toolkit that lets us design apps in a declarative way(Declarative syntax).

Useful Cheat Sheet for SwiftUI

TBA

<p align="right"> <a href="#-content">Back to Content</a> </p>

iOS icon

UIdesign Inspiration

Vector Graphic Editors

Design Collaboration Tools

Design Tools

<p align="right"> <a href="#-content">Back to Content</a> </p>

Useful Sites

<p align="right"> <a href="#-content">Back to Content</a> </p>

Screen Layout Programmatically

TBA

<p align="right"> <a href="#-content">Back to Content</a> </p>

Bundle

You can use Bundle+Extension.swift file to configure your bundle to your application.

Source code from : PhoneNumberKit

Static Library

Dynamic Library

xcframework

XCFrameworks is a distributable binary package created by Xcode that contains variants of a framework or library so that it can be used on multiple platforms (iOS, macOS, tvOS, and watchOS), including Simulator builds

Creating a multiplatform binary framework bundle

<p align="right"> <a href="#-content">Back to Content</a> </p>

Helper

All files are resuable files and protocol oriented. Just Copy and Paste inside your project and use it!! πŸ‘

These helper files are not with Error Handling! careful at use

Email, Message, Call

You can check the file in the follow link

Usage

import MessageUI first

import MessageUI

Then use it

Don't forget to extend the mail, message delegate to your ViewController!

    lazy var conversation = ConversationManager(presentingController: self, mailDelegate: self, messageDelegate: self, viewController: self)
    
    @IBAction private func sendEmail(_ sender: UIButton) {
        conversation.sendEmail(feedback: MailFeedback(recipients: ["abcd@google.com"], subject: "FeedBack", body: "Write feedback here"))
    }
    @IBAction private func sendMessage(_ sender: UIButton) {
        conversation.sendMessage(feedback: MessageFeedBack(recipients: ["1111111111"], body: "Type here"))
    }
    @IBAction private func startCall(_ sender: UIButton) {
        conversation.makeCall(number: "1111111111")
    }

Good To GO πŸ‘πŸ‘πŸ‘

See Example here

<p align="right"> <a href="#-content">Back to Content</a> </p>

Network Layer

Usage

First, set the base URL in EndPointType file

Don't forget to put your API key in it!

var baseURL: URL {
        guard let url = URL(string: "https://api.openweathermap.org/data/2.5/") else {
            fatalError("baseURL could not be configured.")
        }
        return url
    }

then make a instance of router.swift file in your code

private let router = Router<YourAPI>()

for YourAPI part, simply create a new enum with cases about specific api URL

It will make your router more dynamic! Don't forget extension to EndPointType!

enum YourAPI {
    case first(country: String)
    case second(time: Int)
    case third(name: String)
}

extension YourAPI: EndPointType {
    var path: String {
        switch self {
        case .first(let country):
            return "\(country).json"
        case .second(let time):
            return "\(time).json"
        case .third(let name):
            return "\(name).json"
        }
    }
}

then, use it like this

router.request(.first(country: London)) { [weak self] (results: Result<CountryWeather, AppError>) in
            guard let self = self else { return }
            switch results {
            case .success(let data):
                // insert your modifications!
                
            case .failure(let error):
                // insert your modifications!
                print(error)
            }
        }

CountryWeather should be a model with Decodable

If you want to see how can I use Network Layer in Project, check this

This reusable network layer files for referenced from here

Also Alamofire will be a great option for Network Layer!

Image Picker

Usage

Copy and Paste in your project and then declare Image Picker object inside your project

lazy var imagePicker = ImagePicker(presentationController: self, delegate: self)

Then, extend ImagePickerDelegate to your viewController

extension ViewController: ImagePickerDelegate {
    func didSelect(image: UIImage?) {
        self.yourImageView.image = image
        self.dismiss(animated: true, completion: nil)
    }
}

Good To GO πŸ‘πŸ‘πŸ‘

See Example here

File Manager

Usage

Copy and Paste in your project

let readData = FileManageHelper.manager.readFile(filename: fileNameTextField.text ?? "", type: extensionTextField.text ?? "")
resultTextField.text = readData

File Manager are wrote with singleton pattern, therefore no need to declare in side your code!

Good To GO πŸ‘πŸ‘πŸ‘

Video Downloader

Usage

Make an object of VideoManager inside your code

let videoManager = VideoManager()

use downloadVideoLinkAndCreateAsset function to start download with entering URL

self.videoManager.downloadVideoLinkAndCreateAsset(text)

Good To GO πŸ‘πŸ‘πŸ‘

Image Downloader

There is no file for Image Downloader.

To download images into device, only thing is this

if let data = try? Data(contentsOf: urls),
   let image = UIImage(data: data) {
   UIImageWriteToSavedPhotosAlbum(image, nil, nilil)
}

Just change urls into your image URL

UIImageWriteToSavedPhotosAlbum will take care it to download to device.

For more info go here

Good To GO πŸ‘πŸ‘πŸ‘

Location Manager

Currently Working

<p align="right"> <a href="#-content">Back to Content</a> </p>

Local Notification Manager

<p align="right"> <a href="#-content">Back to Content</a> </p>

API

API(Application Programming Interface) is an interface that defines interactions between multiple software applications or mixed hardware-software intermediaries. It defines the kinds of calls or requests that can be made, how to make them, the data formats that should be used, the conventions to follow, etc.

Various API Site

<p align="right"> <a href="#-content">Back to Content</a> </p>

JSON

JSON is a language-independent data format

Which is relative with KEY - VALUE pair

{
    "main": [
        {
            "title": "example1",
            "body": "body1"
        },
        {
            "title": "example2",
            "body: "body2"
        }
    ]
}

JSON parser extension for Chrome

This extension makes JSON more structable JSON parser pro FREE :+1:

JSONDecoder

To use JSONDecoder in swift, you have to define the model to be Codable or Decodable

public typealias Codable = Decodable & Encodable

Decodable can only decode the json data. Can't encoded json file!!

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

To avoid snake_case in swift, use CodingKeys or JSONDecoder.KeyDecodingStrategy

To use JSONDecoding, declare JSONDecoder and use decode() function

 do {
    let data = try JSONDecoder().decode(T.self, from: unwrappedData)
    completionOnMain(.success(data))
} catch {
    print(error)
    completionOnMain(.failure(.parseError))
}

T.self -> Model(Struct) of the data that you want to decode

data will decoded to form of T

unwrappedData -> Input actual data from file or server

This should be a Data Type!!

JSONSerialization

JSONSerialization is a old way of decode the JSON file.

Apple populated Codable since Swift 4

Example

Example of number.json data

{
    "number": [
        {
            "name": "Dennis",
            "number": "111-222-3333"
        },
        {
            "name": "Jenny",
            "number": "444-555-6666"
        },
        {
            "name": "Ben",
            "number": "777-888-9999"
        }
    ]
}

Here is a example of JSONSerialization with actaul JSON file in project folder

Otherwise you can use URL!

    private func populateDataFromJson() {
        
        if let path = Bundle.main.path(forResource: "NumberData", ofType: "json") {
            do {
                let dataJson = try Data(contentsOf: URL(fileURLWithPath: path))
                let jsonDict = try JSONSerialization.jsonObject(with: dataJson, options: .mutableContainers)
                if let jsonResults = jsonDict as? [String: Any],
                   let results = jsonResults["number"] as? [[String: Any]] {
                    results.forEach { dict in
                        // simply appended to list(array)
                        self.phoneNumberList.append(PhoneNumber(name: dict["name"] as? String ?? "", number: (dict["number"] as? String ?? "")))
                        self.phoneNumberListClone.append(PhoneNumber(name: dict["name"] as? String ?? "", number: (dict["number"] as? String ?? "")))
                    }
                }
            } catch {
                print(error.localizedDescription)
            }
        }
    }

.mutableContainers allows to working like a array and dictionary type

JSON Parser Library

This library provide JSON parsing

<p align="right"> <a href="#-content">Back to Content</a> </p>

NotificationCenter

A notification dispatch mechanism that enables the broadcast of information to registered observers.

<p align="right"> <a href="#-content">Back to Content</a> </p>

UserDefaults

The UserDefaults class provides a programmatic interface for interacting with the defaults system. Check Apple Document for more info

UserDefaults has to have key-value pair

When do we use UserDafaults

How to find documentDirectory

Put this line of code inside of your project

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        print(NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).last ?? "")
        return true
    }
<img src = "https://github.com/jphong1111/Useful_Swift/blob/main/Images/DocumentPath.png" />

simply move into that path and you can find the documentDirectory of your Application

if Library is not shown up, just do Shift + Command + . to show hidden files in your folder

<img src = "https://github.com/jphong1111/Useful_Swift/blob/main/Images/UserDefaultPlistPath.png" />

Usage

As you can see in the below, intArray will stored inside the device through UserDefaults(), so that if device is shut down, changed value wil be stored in device.

class ViewController: UIViewController {
    var intArray = [1,2,3,4,5]
    let defaults = UserDefaults()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        intArray = defaults.array(forKey: "IntArray") as! [Int]
    }
    
    @IBOutlet weak var textField: UILabel!
    @IBAction private func isClicked(_ sender: UIButton) {
        intArray.append(6)
        defaults.set(intArray, forKey: "IntArray")
        textField.text = "\(intArray)"
    }
}

You can your plist file like this!

<img src = "https://github.com/jphong1111/Useful_Swift/blob/main/Images/UserDefaultPlist.png" />

Declare Userdefault like this!

let defaults = UserDefaults.standard

standard allows to access from anywhere inside device

With using set function, you can set userdefaults

<img src = "https://github.com/jphong1111/Useful_Swift/blob/main/Images/UserDefaultSet.png" width = "60%" height = "60%"/>

Also these function will allow to get a data from plist

<img src = "https://github.com/jphong1111/Useful_Swift/blob/main/Images/UserDefaultGet.png" width = "60%" height = "60%"/>

Store Object

Store Object

You are GOOD TO GO πŸ‘πŸ‘πŸ‘

<p align="right"> <a href="#-content">Back to Content</a> </p>

Core Data

Everything Core Data

Use Core Data to save your application’s permanent data for offline use, to cache temporary data, and to add undo functionality to your app on a single device.

Core Data in Swift is using SQLite as DEFAULT

<img src = "https://github.com/jphong1111/Useful_Swift/blob/main/Images/DataStoreInSwift.png" width = "50%" height = "50%"/>

Image From London App Brewery

πŸ“šπŸ“š Recommend Book πŸ“šπŸ“š

Book NameAuthors Name
Core Data by Tutorials: iOS 12 and Swift 4.2 Editionraywenderlich Tutorial Team

Core Data Stack

<img src = "https://github.com/jphong1111/awesome-ios-developer/blob/main/Images/Core_Data_Stack.png" width = "70%" height = "70%"/>

Set Up Core Data

Simply Click Core Data check box when you create a new project

<img src = "https://github.com/jphong1111/Useful_Swift/blob/main/Images/AddCoreData.png" width = "50%" height = "50%"/>

If you want to attach Core Data in exsiting project

Create Data Model file first

<img src = "https://github.com/jphong1111/Useful_Swift/blob/main/Images/AddDataModel.png" width = "50%" height = "50%"/>

Then import CoreData inside your AppDelegate.swift file

import CoreData

And Copy and Paste this lines of code inside your AppDelegate.swift file

    // MARK: - Core Data stack

    lazy var persistentContainer: NSPersistentContainer = {
        /*
         The persistent container for the application. This implementation
         creates and returns a container, having loaded the store for the
         application to it. This property is optional since there are legitimate
         error conditions that could cause the creation of the store to fail.
        */
        let container = NSPersistentContainer(name: "Your DataModel file name")
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                // Replace this implementation with code to handle the error appropriately.
                // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                 
                /*
                 Typical reasons for an error here include:
                 * The parent directory does not exist, cannot be created, or disallows writing.
                 * The persistent store is not accessible, due to permissions or data protection when the device is locked.
                 * The device is out of space.
                 * The store could not be migrated to the current model version.
                 Check the error message to determine what the actual problem was.
                 */
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        return container
    }()

    // MARK: - Core Data Saving support

    func saveContext () {
        let context = persistentContainer.viewContext
        if context.hasChanges {
            do {
                try context.save()
            } catch {
                // Replace this implementation with code to handle the error appropriately.
                // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                let nserror = error as NSError
                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
            }
        }
    }

Don't forget to change it

let container = NSPersistentContainer(name: "Your DataModel file name")

And goto SceneDelegate.swift file, copy below lines of code and replace yours

func sceneDidEnterBackground(_ scene: UIScene) {
        // Called as the scene transitions from the foreground to the background.
        // Use this method to save data, release shared resources, and store enough scene-specific state information
        // to restore the scene back to its current state.

        // Save changes in the application's managed object context when the application transitions to the background.
        (UIApplication.shared.delegate as? AppDelegate)?.saveContext()
    }

If your target is below iOS13, put this line of code in side your applicationWillTerminate of AppDelegate.swift file

self.saveContext()

Core Data Usage

Once you create your DataModel file, you can simply create a Entity(Class) and Attributes(Properties)

And then, change the type of attributes in inspector like this

<img src = "https://github.com/jphong1111/Useful_Swift/blob/main/Images/DataModelAttribute_inspector.png"/>

Once you create your own Entities & Attributes, go to Inspector and change Module to CurrentProductModule

<img src = "https://github.com/jphong1111/Useful_Swift/blob/main/Images/DataModelAttributes.png"/>

If you didn't set it, thats fine, but if you are working in big project, then you need to set it. Otherwise this can occurs some error.

Codegen

As you can see in above, there are three options

CoreDataClass, CoreDataProperties are located in below

/Users/dennis/Library/Developer/Xcode/DerivedData/CoreDataUserDefaultPractice-hisefjfyuvglrjekndpftwazftug/Build/Intermediates.noindex/CoreDataUserDefaultPractice.build/Debug-iphonesimulator/CoreDataUserDefaultPractice.build/DerivedSources/CoreDataGenerated/CoreDataUserDefaultPractice

And CoreDataClass, CoreDataProperties are looking like this,

<img src = "https://github.com/jphong1111/Useful_Swift/blob/main/Images/CoreDataClass_Properties.png"/>

If your code can run it but didn't get your Entities, Rebuild it or Restart your Xcode

The reason that files divided into two files is that one for writing Business Logic, one for Properties

Entities

An entity represents a table in your database. It is the blueprint for the NSManagedObject subclass instances that you will create and use throughout your application.

Attributes

Attributes are properties of your object. They translate to a column in your database table and a property in your managed object. You can choose from a variety of primitive values that the database has to offer such as a string, integer, or date.

Relationships

A relationship describes how one entity relates to another. Two important aspects of this are the cardinality and the deletion rule

Cardinality

Delete Rules

Core Data Relationships and Delete Rules

Store Data

Declare context as a global variable

let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

Get viewContext that we defined in AppDelegate.swift file

Simply you can use this code to save your data to CoreData

func saveItem() {
        do {
            try context.save()
        } catch {
            print("Error Saving Context: \(error.localizedDescription)")
        }
    }

Use it wherever you want

Data can be find if you print the path

print(FileManager.default.urls(for: .documentDirectory, in: .userDomainMask))
<img src = "https://github.com/jphong1111/Useful_Swift/blob/main/Images/CoreDataSQLite.png" />

You can check Entities, Properties inside that file

Load Data

Refer this code and apply it to your code wherever you want to reload it

    func loadItem() {
        let request: NSFetchRequest<Item> = Item.fetchRequest()
        do {
            itemArray = try context.fetch(request)
        } catch {
            print("Load Item Error: \(error.localizedDescription)")
        }
    }

Item will be your Entity, itemArray will be your Entity object Don't forget to import CoreData

Update Data

Simply use setValue function so that you can update your value in DB

itemArray[0].setValue(<#T##value: Any?##Any?#>, forKey: <#T##String#>)

if you are using TableView or CollectionView, change 0 to indexPath.row

Delete Data

Simply use delete function in context

context.delete(itemArray[0])

change number for dynamic!

You are GOOD TO GO πŸ‘πŸ‘πŸ‘

<p align="right"> <a href="#-content">Back to Content</a> </p>

Core Bluetooth

You are GOOD TO GO πŸ‘πŸ‘πŸ‘

<p align="right"> <a href="#-content">Back to Content</a> </p>

Third Party Library

Third Party Library saves you time as you do not need to develop the functionality that the library provides. SHOULD DEVELOPERS USE THIRD-PARTY LIBRARIES?

Relying on library(abused) is not a good idea

Dependency/Package Manager

A package manager is a tool that simplifies the process of working with code from multiple sources.

More Info

CocoaPods

Download cocoapods

$ sudo gem install cocoapods

After finish download cocoapods, go to your root folder of your project and make pod file

$ pod init

Click into your pod file and edit

Image

After finish editing, update your pod file

$ pod install

You are GOOD TO GO πŸ‘πŸ‘πŸ‘

<p align="right"> <a href="#-content">Back to Content</a> </p>

Carthage

First, install Carthage through HomeBrew

$ brew install carthage

if already installed, check if there is latest version.

$ carthage update

Then, go to your root project folder, and do this

touch Cartfile

open cartfile, put library that you want to use

github "<owner>/<repo>" == <version>

Example

github "Alamofire/Alamofire" == 4.9.0
github "Alamofire/AlamofireImage" ~> 3.4

And then, do this

carthage update --platform iOS

After finish downloading it, go to Xcode -> Build phases

TBD

You are GOOD TO GO πŸ‘πŸ‘πŸ‘

<p align="right"> <a href="#-content">Back to Content</a> </p>

Swift Package Manager

<img src = "https://github.com/jphong1111/awesome-ios-developer/blob/main/Images/SwiftPackageManager.png" width = "50%" height = "50%"/>

Enter url of library that you want to install

<img src = "https://github.com/jphong1111/awesome-ios-developer/blob/main/Images/SwiftPackageManager2.png" width = "50%" height = "50%"/> <img src = "https://github.com/jphong1111/awesome-ios-developer/blob/main/Images/SwiftPackageManager3.png" width = "50%" height = "50%"/>

You are GOOD TO GO πŸ‘πŸ‘πŸ‘

<p align="right"> <a href="#-content">Back to Content</a> </p>

Recommend Library

<p align="right"> <a href="#-content">Back to Content</a> </p>

Localization

Localization is the process of making your app support other languages. (Base language is English)

Localization Usage

First, you have to check Use Base Internationalization

It might be checked

<img src = "https://github.com/jphong1111/Useful_Swift/blob/main/Images/Internationalization.png" width="70%" height ="70%" />

English is a base Language

After you check it, add languages that you want to support in your App

<img src = "https://github.com/jphong1111/Useful_Swift/blob/main/Images/Internationalization2.png" width="70%" height ="70%" />

Then, you can check your language file like this!

<img src = "https://github.com/jphong1111/Useful_Swift/blob/main/Images/Internationalization3.png" width="70%" height ="70%" />

Create Localizable.strings file into your project

Unlike Swift, the .strings file requires that each line terminate with a semicolon .strings file is where you can add translation data as key-value pairs

<img src = "https://github.com/jphong1111/Useful_Swift/blob/main/Images/Internationalization4.png" width="70%" height ="70%" />

In your .strings file, check localization button and choose language

<img src = "https://github.com/jphong1111/Useful_Swift/blob/main/Images/Internationalization5.png" />

And then add Key - Value pairs for tanslation

<img src = "https://github.com/jphong1111/Useful_Swift/blob/main/Images/Internationalization6.png" width="70%" height ="70%"/>

To use localization, use NSLocalizedString to implement it

NSLocalizedString(<#T##key: String##String#>, comment: <#T##String#>)

Simple example below

@IBAction func showAlert() {
        let alertTitle = NSLocalizedString("Welcome", comment: "")
        let alertMessage = NSLocalizedString("How are you", comment: "")
        let cancelButtonText = NSLocalizedString("Cancel", comment: "")
        let signupButtonText = NSLocalizedString("Signup", comment: "")

        let alert = UIAlertController(title: alertTitle, message: alertMessage, preferredStyle: UIAlertController.Style.alert)
        let cancelAction = UIAlertAction(title: cancelButtonText, style: UIAlertAction.Style.cancel, handler: nil)
        let signupAction = UIAlertAction(title: signupButtonText, style: UIAlertAction.Style.default, handler: nil)
        alert.addAction(cancelAction)
        alert.addAction(signupAction)
        present(alert, animated: true, completion: nil)
    }

After that, we have to test if localization is working correctly or not

To test it, you can do either Edit Scheme or New Scheme

go to Run section, and change App Language

<img src = "https://github.com/jphong1111/Useful_Swift/blob/main/Images/Internationalization7.png" />

After finish setting Scheme try to run it!

<img src = "https://github.com/jphong1111/Useful_Swift/blob/main/Images/Internationalization8.png" width="50%" height ="50%" /> <img src = "https://github.com/jphong1111/Useful_Swift/blob/main/Images/Internationalization9.png" width="50%" height ="50%" />

You are GOOD TO GO πŸ‘πŸ‘πŸ‘

<p align="right"> <a href="#-content">Back to Content</a> </p>

Useful for Localization

<p align="right"> <a href="#-content">Back to Content</a> </p>

Accessibility

Accessibility is all about making the iPhone, iPod touch, and iPad work for as wide a range of people as possible. That can include the very young, the very old, people brand new to computers and mobile devices, and also people with disabilities and special needs.

Accessibility Usage

To use accessibility, you have to enable this

For most UIKit classes, the default is true, but for UILabel it’s false

label.isAccessibilityElement = true
<p align="right"> <a href="#-content">Back to Content</a> </p>

GCD

GCD(Grand Central Dispatch) is a low-level API for managing concurrent operations. It can help you improve your app’s responsiveness by deferring computationally expensive tasks to the background.

DispatchQueue

An object that manages the execution of tasks serially or concurrently on your app's main thread or on a background thread.

main

We can say main is a serial queue

global()

We can say global is a concurrent queue

Thread Safety

Concurrency & Thread Safety in Swift Thread Safety in Swift

Use a barrier to synchronize the execution of one or more tasks in your dispatch queue.

Dispatch Barrier Apple Documentation

Dispatch Semaphore Apple Documentation

An object that coordinates the operation of multiple threads of execution within the same application.

NSLock

DispatchGroup

DispatchGroup Apple Document

DispatchWorkItem

The work you want to perform, encapsulated in a way that lets you attach a completion handle or execution dependencies.

DispatchWorkItem Apple Document

Operation

NSOperation Apple Documentation

OperationQueue

NSOperationQueue Apple Documentation

<p align="right"> <a href="#-content">Back to Content</a> </p>

Thread Sanitizer

Thread Sanitizer is a tool to identifies the potential thread-related corruption issues. And it is a good way to find the Readers and Writers problem in your application.

<p align="right"> <a href="#-content">Back to Content</a> </p>

How to Use Thread Sanitizer

Go to this Option and Click EDIT SCHEME... πŸ‘ˆ

<img src="https://github.com/jphong1111/Useful_Swift/blob/main/Images/address_sanitizer.png">

And then go to RUN and check THREAD SANITIZER πŸ‘ˆ

<img src="https://github.com/jphong1111/awesome-ios-developer/blob/main/Images/thread_sanitizer.png">

Testing

Five Factor Testing

Five Factor Testing

Test Double

Test Double is a generic term for any case where you replace a production object for testing purposes.

// exaple code will update
// exaple code will update
// exaple code will update
// exaple code will update
// exaple code will update

Useful Debugging Technique

Debugging in Xcode 13: Tips & Tricks (2022) – iOS

1. Change expression in debugging stage

<img src="https://github.com/jphong1111/Useful_Swift/blob/main/Images/debugging_expression.png" width = "80%" height = "80%">

Use expression at the beginning and then add whatever what you want to change into. It will change in debugging stage πŸ‘

2. Symbolic Breakpoint

If we want to know whenever hit certain function, use symbolic breakpoint

TDD

Test Driven Development

<img src="https://github.com/jphong1111/awesome-ios-developer/blob/main/Images/TDD.png" width="30%" height="30%"/>

Reduce Build Time

Normally in complicated Application, build time for testing is crazy therefore, TDD spent most of time in building the project.

Here are useful ways that we can reduce build time when we are working with TDD style.

1. tuist focus

2. Detach debugger in Edit Scheme

un-check Debugger option

<img src = "https://github.com/jphong1111/awesome-ios-developer/blob/main/Images/detach_debuger.png"/>

Check build time in Xcode

Enter below code in your terminal, be sure to restart Xcode after enter this code and Command + B

defaults write com.apple.dt.Xcode ShowBuildOperationDuration YES
<img src = "https://github.com/jphong1111/awesome-ios-developer/blob/main/Images/show_build_time.png"/>

BDD

<img src="https://github.com/jphong1111/awesome-ios-developer/blob/main/Images/BDDvsTDD.png" width="70%" height="70%"/>

BDD improves communication between tech and non-tech teams and stakeholders. In BDD, tests are more user-focused and based on the system’s behavior.

Behavior Driven Development

Three Steps(Iterative) in BDD

First, take a small upcoming change to the system – a User Story – and talk about concrete examples of the new functionality to explore, discover and agree on the details of what’s expected to be done.

Next, document those examples in a way that can be automated, and check for agreement.

Finally, implement the behaviour described by each documented example, starting with an automated test to guide the development of the code.

Code Coverage

Before start your Testing, add coverage will be a good option to show the result of test

First, check code coverage

<img src ="https://github.com/jphong1111/awesome-ios-developer/blob/main/Images/addCoverage1.png"/>

Then, go to EDIT SHEME, check like this

<img src ="https://github.com/jphong1111/awesome-ios-developer/blob/main/Images/addCoverage2.png"/>

Integration Testing

Integration Testing Swift by Sundell

Unit Testing

Unit Testing Swift by Sundell

πŸ“šπŸ“š Recommend Book πŸ“šπŸ“š

Book NameAuthors Name
iOS Unit Testing by ExampleJon Reid

UI Testing

UI Testing, also known as GUI Testing is basically a mechanism meant to test the aspects of any software that a user will come into contact with. This usually means testing the visual elements to verify that they are functioning according to requirements – in terms of functionality and performance. UI testing ensures that UI functions are bug-free.

Robot Testing

Robot testing is a test design pattern that makes you to create stable, readable, and maintainable tests.

<img src ="https://github.com/jphong1111/awesome-ios-developer/blob/main/Images/robot_testing.png"/>

Snapshot Testing

Snapshot Testing is a testing technique that can be used in Swift (and other programming languages) to test the user interface (UI) of an application.

In Snapshot Testing, a snapshot of the UI is taken and compared to a previously saved snapshot to check if any changes have been made. This technique can be used to ensure that changes to the UI do not break the existing functionality of the application.

Environment Variable

With using Environment Variable in Xcode, we can directly re-capture failing snapshot test cases

<img src ="https://github.com/jphong1111/awesome-ios-developer/blob/main/Images/env_variable.png"/>

SNAPSHOT_TESTING = YES

TestFlight

TestFlight makes it easy to invite users to test your apps and App Clips and collect valuable feedback before releasing your apps on the App Store.

CI/CD

CI and CD stand for continuous integration and continuous delivery/continuous deployment

Fastlane

The easiest way to build and release mobile apps.

<img src ="https://github.com/jphong1111/awesome-ios-developer/blob/main/Images/fastlane.png" />

Jenkins

Jenkins is most popular CI/CD tools

Jenkins

Jira

Jira is project management software first and foremost, but it began its life in 2002 as an issue tracking platform for software developers

CircleCI

CircleCI

You can integrate Circle CI into Github repo, therefore we can use it in PR.

Danger

Danger

Codemagic

Codemagic - Build, test and deliver your mobile projects 20% faster.

Xcode Cloud

WWDC21 Apple released Xcode Cloud for continuous integration

For more info, go to Apple Developer Website

<p align="right"> <a href="#-content">Back to Content</a> </p>

Tuist

In App Purchase(IAP)

Requirement

Simulator can not test IAP!!

Paywall

<img src ="https://github.com/jphong1111/awesome-ios-developer/blob/main/Images/paywall.jpeg" />

Paywall is a way to restrict access to their information so that only paying users can use it.

Lots of developer recommend 80% - (Paywall) - 20%

Set Up

TBD

For more info about getting start of IAP, go here πŸ“‘

<p align="right"> <a href="#-content">Back to Content</a> </p>

Notification

Local Notification

If you set repeatation less than 60 sec, it will cause ERROR!

<img src ="https://github.com/jphong1111/awesome-ios-developer/blob/main/Images/Repeatation_Error.png"/> <p align="right"> <a href="#-content">Back to Content</a> </p>

Remote Notification

APNs

APNS stands for Apple Push Notification service

APNs Setting

First, go to Signing & Capabilities and add two features like this

<img src = "https://github.com/jphong1111/awesome-ios-developer/blob/main/Images/apsn_Setting.png"/>

APNs Usage

FRP

Functional Reactive Programming

Rxswift

πŸ“šπŸ“š Recommend Book πŸ“šπŸ“š

Book NameAuthors Name
RxSwift: Reactive Programming with Swiftraywenderlich Tutorial Team
<p align="right"> <a href="#-content">Back to Content</a> </p>

Combine

Combine released on iOS13 from Apple for Functional Reactive Programming.

Swiftbysundell

πŸ“šπŸ“š Recommend Book πŸ“šπŸ“š

Book NameAuthors Name
Combine: Asynchronous Programming with Swiftraywenderlich Tutorial Team

RxCombine

RxCombine provides bi-directional type bridging between RxSwift and Apple's Combine framework.

RxCombine

Security

Security secure the data your app manages, and control access to your app.

Check below for more detail about iOS Security as well as Application security

<p align="right"> <a href="#-content">Back to Content</a> </p>

Checklist For App Security

Keychain

SSL Pinning

<img src = "https://github.com/jphong1111/awesome-ios-developer/blob/main/Images/SSLCertificate.png"/>

When a mobile app communicates with a server, it uses SSL(Secure Socket Layer) pinning technique for protecting the transmitted data against tampering and eavesdropping.

How SSL Works

  1. A browser attempts to connect with a website which is secured with a SSL. The browser then requests the web server to identify itself.
  2. Web server then sends the browser its SSL certificate copy.
  3. The browser checks if the SSL certificate must be trusted. If it can be, a message is sent to the web server.
  4. Web server then sends back an acknowledgement to begin the SSL encrypted session.
  5. The encrypted data is then finally shared between the browser and web server.

SSL pinning methods

Using URLSession

func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
    if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
        if let serverTrust = challenge.protectionSpace.serverTrust {
            var secresult = SecTrustResultType.invalid
            let status = SecTrustEvaluate(serverTrust, &secresult)
            
            if (errSecSuccess == status) {
                if let serverCertificate = SecTrustGetCertificateAtIndex(serverTrust, 0) {
                    let serverCertificateData = SecCertificateCopyData(serverCertificate)
                    let data = CFDataGetBytePtr(serverCertificateData);
                    let size = CFDataGetLength(serverCertificateData);
                    let cert1 = NSData(bytes: data, length: size)
                    let file_der = Bundle.main.path(forResource: "name-of-cert-file", ofType: "cer")
                    
                    if let file = file_der {
                        if let cert2 = NSData(contentsOfFile: file) {
                            if cert1.isEqual(to: cert2 as Data) { completionHandler(URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust:serverTrust))
                                return
                            }
                        }
                    }
                }
            }
        }
    }
    
    // Pinning failed completionHandler(URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge, nil)
}

Using Alamofire 5

If you are using above version, this code should be changed

More Info

First, Download SSL certificate to your project folder

https://www.yourdomain.com (NOT IN THIS WAY)

openssl s_client -showcerts -connect yourdomain.com:443 < /dev/null | openssl x509 -outform DER > yourdomain.cer

Make a SessionManager to get SSL Pinning


let sessionManager: SessionManager = {
    let serverTrustPolicies: [String: ServerTrustPolicy] = ["yourdomain.com": .pinCertificates(certificates: ServerTrustPolicy.certificates(),
                                                                                                validateCertificateChain: true,
                                                                                                validateHost: true)]
    
    return SessionManager(serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies))
}()

request from sessionManager, if it is invalid, print error

sessionManager.request("https://yourdomain.com").responseString { (dataResponse) in
    switch dataResponse.result {
    case .failure(let err):
        print(err)
    case .success(let val):
        print(val)
        if let headerFields = dataResponse.response?.allHeaderFields {
            print(headerFields)
        }
    }
}

Relative Stuff

TrustKit makes it easy to deploy SSL public key pinning

TrustKit

Code Obfuscation

Code obfuscation is the act of deliberately obscuring source code, making it very difficult for humans to understand, and making it useless to hackers who may have ulterior motives.

Cryptography

Introducing Swift Crypto

Biometric Access

Apple made a big change when it released the iPhone X: It ditched Touch ID fingerprint security for a new face-based biometric sign-on tool called Face ID. The fingerprint scanner on most post-iPhone X Apple products is gone, and in its place is a new camera array capable of capturing a face map that is, according to Apple, 20 times less likely to be hacked than a Touch ID fingerprint.

Apple's Face ID: Cheat sheet

Face ID & Touch ID

To use Face ID, Add Privacy - Face ID Usage Description into your info.plist file in your project

<img src = "https://github.com/jphong1111/Useful_Swift/blob/main/Images/FaceID_Info.png" width = "50%" height = "50%"/>

import LocalAuthentication, which can allow you to implement Biometric Access

import LocalAuthentication

After that, using LAContext() we can implement Face ID

Here are simple example that how Face ID can impelement

@IBAction private func isTouched(_ sender: UIButton!) {
        let context = LAContext()
        var error: NSError? = nil
        if  context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
            let reason = "touch id"
            context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { [weak self](success, error) in
                DispatchQueue.main.async {
                   
                    guard success, error == nil else {
                        // If Fail
                        let alert  = UIAlertController(title: "FAceID Fail", message: "error", preferredStyle: .alert)
                        let action = UIAlertAction(title: "cancle", style: .cancel, handler: nil)
                        alert.addAction(action)
                        self?.present(alert, animated: true, completion: nil)
                        return
                    }
                    // If success
                    let vc = UIViewController()
                    vc.title = "hi"
                    vc.view.backgroundColor = .blue
                    self?.present(vc, animated: true, completion: nil)
                }
            }
        } else {
            // If device is not supporting Face ID
        }
    }

Error Handling is your own part

You are GOOD TO GO πŸ‘πŸ‘πŸ‘

<p align="right"> <a href="#-content">Back to Content</a> </p>

Objective-C

Still we need to study Objective-C for legacy code which is still remain in our project!

Here are some useful website that you can study about simple concept of Obj-C!!

Learn Objective-C in 24 Days

πŸ“šπŸ“š Recommend Book πŸ“šπŸ“š

Book NameAuthors Name
Objective-C Programming: The Big Nerd Ranch GuideAaron Hillegass, Mikey Ward

Pure Swift Application?

Can we really say "Our application is built with pure Swift"?. NO! Lots of Objective-C codes are running in the background to built swift.

Here is a example that you can try

Simply create a pure swift application and use this lines in debug console!!

break set -r "-\[.*\]"
break set -r DebugMode
break set -r Emoji

Use one of above line when you want to find out how many Objective-C codes are consist in simple pure swift application!!

<img src="https://github.com/jphong1111/awesome-ios-developer/blob/main/Images/ObjcBreakPoint.png" /> <p align="right"> <a href="#-content">Back to Content</a> </p>

Bridging Header

Bridging header means access classes and other declarations from your Objective-C code in Swift.

Importing Objective-C into Swift Apple Documentation

<p align="right"> <a href="#-content">Back to Content</a> </p>

Error Search

Find your common error here

Error Search

Useful Stuff

I listed some of the useful & interesting stuff related with Swift

<p align="right"> <a href="#-content">Back to Content</a> </p>

Useful Blogs for iOS Developers

Here are the useful blog list which you can get references & knowledges about iOS development

How to submit your app to the AppStore

iOS Version Adoption Tracker

You can check the iOS Version adoption in this site

iOS Version Adoption Tracker

<img src="https://github.com/jphong1111/awesome-ios-developer/blob/main/Images/iOS16_adoption.png" /> <p align="right"> <a href="#-content">Back to Content</a> </p>

Online Swift Playground

SwiftPlayground - Online Swift Playground

Show Preview in UIKit(Build UI with Code Base) πŸ‘ πŸ‘ πŸ‘ πŸ‘ πŸ‘

Inject (3rd Party Library)

Copy this code and Paste into your controller

#if canImport(SwiftUI) && DEBUG
import SwiftUI
struct SwiftLeeViewRepresentable: UIViewRepresentable {
    func makeUIView(context: Context) -> UIView {
        return UIStoryboard(name: "Main", bundle: Bundle.main).instantiateInitialViewController()!.view
    }
    
    func updateUIView(_ view: UIView, context: Context) {
        
    }
}

@available(iOS 13.0, *)
struct SwiftLeeViewController_Preview: PreviewProvider {
    static var previews: some View {
        SwiftLeeViewRepresentable()
    }
}
#endif

Enable canvas option like this

<img src="https://github.com/jphong1111/Useful_Swift/blob/main/Images/preview%20using%20canvas.png"> <img src="https://github.com/jphong1111/Useful_Swift/blob/main/Images/preivew_screenShot.png">

You are GOOD TO GO πŸ‘πŸ‘πŸ‘

Compare Changes in Swift Version

You can compare changes based on Swift Verison

Whatsnewinswift

Managing Xcode Space

This will be helful when you are running out of storage in your mac

# 1
echo "Removing Derived Data..."
rm -rf ~/Library/Developer/Xcode/DerivedData/

# 2
echo "Removing Device Support..."
rm -rf ~/Library/Developer/Xcode/iOS\ DeviceSupport
rm -rf ~/Library/Developer/Xcode/watchOS\ DeviceSupport
rm -rf ~/Library/Developer/Xcode/tvOS\ DeviceSupport

# 3
echo "Removing old simulators..."
xcrun simctl delete unavailable

# 4
echo "Removing caches..."
rm -rf ~/Library/Caches/com.apple.dt.Xcode
rm -rf ~/Library/Caches/org.carthage.CarthageKit

# 5
if command -v pod  &> /dev/null
then
    # 6
    pod cache clean --all
fi

echo "Done!"

After writing, run it with this command

chmod u+x clean-xcode.sh

And then

./clean-xcode.sh

This will cleans out derived data, device support, simulators and caches. So that once you execute it, You have to build your project AGAIN

For More Info, visit here

<p align="right"> <a href="#-content">Back to Content</a> </p>

Roadmap for iOS Developer

check this out here

Use VIM in Xcode

Check this site for more info!

Since Xcode 13(BETA), you can find Vim in Preference -> Text Editing -> Editing -> Enable Vim Key bindings this feature deprecated in Xcode 13(BETA) <img src="https://github.com/jphong1111/Useful_Swift/blob/main/Images/Vim.png">

Write README.md

how-to-write-a-readme will help you to write a README.md file more dynamically πŸ‘

Also you can edit Readme.md file with VSCode Extension! Check out in VSCode!

Markdown Preview Enhanced

<p align="right"> <a href="#-content">Back to Content</a> </p>

❀ Supporters

⭐ Stargazers

<a href="https://github.com/jphong1111/awesome-ios-developer/stargazers"> <img src="https://reporoster.com/stars/jphong1111/awesome-ios-developer"></a>

🍴 Forks

<a href="https://github.com/jphong1111/awesome-ios-developer/fork"> <img src="https://reporoster.com/forks/jphong1111/awesome-ios-developer"></a>

🌟 GitHub Stargazers

Stargazers over time

Author

This README.md file is written by Jungpyo Hong (Dennis) email: ghdwjdvy96@gmail.com

<p align="right"> <a href="#-content">Back to Content</a> </p>