Tic Tac Toe in SwiftUI


Hi Friends,

Here I share knowledge about game logic and UI implementation in SwiftUI.

Follow my channel on YouTube and Facebook

Part 1
Part 2
Part 3

– How to make an iOS App

Kathiresan Murugan

Design Tack Shipping screen in SwiftUI


Hi Friends,

Basic SwiftUI screen designing of Track shipping screen in SwiftUI | How to make an iOS App

 

– How to make an iOS App

  Kathiresan Murugan

Subscribe

https://www.youtube.com/channel/UC6nWavOGjtz8bhwUTBoQWFg

Basic design on SwiftUI


Check my channel on YouTube and subscribe.

Hi Friends,

Learn SwiftUI from YouTube by my channel. Subscribe my channel and learn more and more.

Adopting Dark mode


Hi Friends,

Basically iOS 13 applications are supporting Dark Mode.
Dark Mode is based on colour and Image. One is Light Mode and another one is Dark Mode.

Here we focus on implementing UIColor for dark mode by programmatically.

This few lines of code will bring your application to support Darkmode feature for iOS 13 and above and also iOS 12 and older

  var bgColor: UIColor {
        if #available(iOS 13.0, *) {
           return UIColor.init(dynamicProvider: {$0.userInterfaceStyle == .dark ? UIColor.black: UIColor.blue })
        } else {
            // Fallback on earlier versions
            return UIColor.blue
        }
    }

For your Quick learn checkout my video tutorial on YouTube. and also subscribe my channel for learn more and more

– How to make an iOS App

Kathiresan Murugan

SwiftUI + Combine.Framework


Hi Friends,

Apple introduced SwiftUI and Combine.Framework at WWDC’19

SwiftUI is most powerful UI Framework better than UIKit

SwiftUI has No Storyboard, No Xib, No AutoLayout, No ViewController

Here I’m using Combine.Framework for value passing from Model class to SwiftUI ContentView

import SwiftUI
import Combine
struct User: Identifiable {
    let name: String
    let country: String
    let gender: String
    let id = UUID()
}

class Model: ObservableObject{
    
    @Published var users: [User] = []
    
    func loadValue() {
        users = [.init(name: "John", country: "US", gender: "Male"),
                 .init(name: "Jolye", country: "US", gender: "Female"),
                 .init(name: "Kathiresan", country: "India", gender: "Male"),
                 .init(name: "Kattte", country: "Canada", gender: "Female")]
    }
}
import SwiftUI
import Combine

struct ContentView: View {
    
    @ObservedObject var model = Model()
    
    var body: some View {
        
        VStack {
            Button(action: {
                       self.model.loadValue()
                   }, label: {
                       Text("Load Values from Model")
                   })
            
            List(self.model.users) { item in
                Text(item.name)
                Spacer()
                Text(item.country)
            }
        }
    }
}

Also learn on YouTube. Subscribe my channel and learn more and more

– How to make an iOS App
kathiresan Murugan

Custom StoryboardSegue in swift


Hi Friends,

Easy to create your own custom animation for storyboardSegue.

         Based on your project you can customise your storyboardSegue animations. If your application contains same background images in all screens means this fadeInPushSegue and fadeOutPopSegue animation will give better experience for customers (People can assume In this project developer used only one screen and implemented hole project in a single viewcontroller. But, we used multiple view controllers in our project.)

Here I have implemented a push and pop segue with fadeIn and fadeOut animations. Its better that pushViewController and popViewController Animations.

class FadeInPushSegue: UIStoryboardSegue {
    
    var animated: Bool = true
    
    override func perform() {
                
        let transition: CATransition = CATransition()
        transition.duration = 0.4
        transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeIn)
        transition.type = CATransitionType.fade
        source.view.window?.layer.add(transition, forKey: "kCATransition")
        source.navigationController?.pushViewController(destination, animated: false)
    }
}
class FadeOutPopSegue: UIStoryboardSegue {
    
    override func perform() {
        
        let transition: CATransition = CATransition()
        
        transition.duration = 0.4
        transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut)
        transition.type = CATransitionType.fade
        source.view.window?.layer.add(transition, forKey: "kCATransition")
        source.navigationController?.popViewController(animated: false)
    }
    
}

– How to make an iOS App
Kathiresan Murugan

Launch multiple simulator on a single compile in Xcode


Hi Friends,

I have develop a communication application. I will run same build in multiple simulators each time to test a design. So, I did like run on iPhone X and Stop. Then run on iPhone 7 and stop. This method of developing was ate my time for running with multiple simulator for any single changes.

So, That I found a solution for Launch multiple simulator on a single compile in Xcode

It is easy to setup and useful for developers to develop or test a Design changes for various device sizes, pair to pair communications and etc.

Lets step in.

Follow this 4 steps.

Step 1:

Create a new simulator named “Custom Simulators” in the pre-action build script.

In Xcode -> Edit schema (Near run, stop button at top left corner) -> Build -> Pre-actions. Add Run Script by clicking + button on the bottom left.

custom_sim=`xcrun simctl list | grep 'Custom Simulators' | awk -F'[()]' '{print $2}'`
if [ -z "${custom_sim}" ]; then
    xcrun simctl create Custom\ Simulators com.apple.CoreSimulator.SimDeviceType.iPhone-X `xcrun simctl list runtimes | grep iOS | tail -1 | sed -e 's/^.*) - //p' | sort -u`
fi

Copy this script and paste it in script field.

This will creates a simulator named “Custom Simulators” with a device type of iPhone X running on the latest iOS runtime. If you didn’t find this in device drop down list. reopen the Xcode and build your project.

Step 2:

Create a MultiSimConfig.txt file in the root directory of your project. This file specifies list of simulators which you are going to run.

find Simulators identifier open your Terminal and run

instruments -s devices

This will list all available simulators and respective identifiers. They will appear like

iPhone Model (iOS version) [IDENTIFIER] (Simulator)

Here I selecting two simulators

806E56CE-8919-4337-8ABD-2A8277599982
D2900E07-7B3F-4AA9-A874-F4227A001487

Step 3:

Create a script file launch_multiple_simulators.sh file in the root directory of your project. That consumes MultiSimConfig.txt and launch the simulators specified.

xcrun simctl shutdown all # Remove this line if you dont need to launch every time

path=$(find ~/Library/Developer/Xcode/DerivedData/${project_name}-*/Build/Products/Debug-iphonesimulator -name "${app_name}.app" | head -n 1)
echo "${path}"

filename=MultiSimConfig.txt
grep -v '^#' $filename | while read -r line
do
xcrun simctl boot "$line" # Boot the simulator with identifier hold by $line var
xcrun simctl install "$line" "$path" # Install the .app file located at location hold by $path var at booted simulator with identifier hold by $line var
xcrun simctl launch "$line" ${bundle_identifier} # Launch .app using its bundle at simulator with identifier hold by $line var
done

Copy this script and paste it.

In this script replace
${project_name} as your project’s name
${app_name} as your name of the .app
${bundle_identifier} as your project bundle identifier.

The script begins by shutting down any simulators you have opened. Read your MultiSimConfig file and loops each simulator and launches it.

Step 4:

Setup your project to this script on the post build action.

Project’s target -> Build Phases -> New Run Script Phase by clicking + button and choose New Run Script.

custom_sim=`xcrun simctl list | grep 'Custom Simulators' | awk -F'[()]' '{print $2}'`
if [ ! -z "${custom_sim}" ] && [ "${TARGET_DEVICE_IDENTIFIER}" = "${custom_sim}" ]; then
/bin/sh launch_multiple_simulators.sh
fi

This script saves the UUID of your “Custom Simulators” to a custom_Sim variable and executes your launch_multiple_simulators.sh script if the current target device matches your “Custom Simulators” UUID.

Build your project and run your project with the “Custom Simulators”


Check Live demo on below Video and Subscribe my channel on YouTube

– How to make an iOS App
Kathiresan Murugan

DynamicFontSize for custom fonts in Swift


Hi Friends,
Set your custom fonts with dynamic font size.

Screenshot 2020-02-07 at 11.23.56 PM

extension UIFont {
    
    /// CustomFont
    /// - Parameter style: UIFont.TextStyle
    static func customFont(style textStyle: UIFont.TextStyle) -> UIFont {
        let fontName = "Arial"
        let fontDescripter = UIFontDescriptor.preferredFontDescriptor(withTextStyle: textStyle)
        
        guard let customFont = UIFont(name: fontName, size: fontDescripter.pointSize) else {
            fatalError("failed to load the \(fontName) font.")
        }
        
        return UIFontMetrics.default.scaledFont(for: customFont)
    }
}

You can use this dynamic fonts like below

        title1Label.font = UIFont.customFont(style: .title1)
        title2Label.font = UIFont.customFont(style: .title2)
        title3Label.font = UIFont.customFont(style: .title3)
        largeTitleLabel.font = UIFont.customFont(style: .largeTitle)
        bodyLabel.font = UIFont.customFont(style: .body)
        caption2Label.font = UIFont.customFont(style: .caption2)
        caption1Label.font = UIFont.customFont(style: .caption1)
        footnoteLabel.font = UIFont.customFont(style: .footnote)
        headlineLabel.font = UIFont.customFont(style: .headline)
        subHeadLabel.font = UIFont.customFont(style: .subheadline)
        calloutLabel.font = UIFont.customFont(style: .callout)

adjustsFontForContentSizeCategory is automatically updates its font when the device’s content size category changes.

title1Label.adjustsFontForContentSizeCategory = true

– How to make an iOS App
Kathiresan Murugan

PDFView in Swift


Hi Friends,

PDFKit framework is available in iOS 11.0* and macOS 10.4*
Implement few lines of code to view your pdf document in you ViewController.

import PDFKit

Implement in UIViewController.viewDidLoad()

        let pdfView = PDFView(frame: view.bounds)
        pdfView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
        view.addSubview(pdfView)
        
        pdfView.autoScales = true
        
        let filePath = Bundle.main.url(forResource: "Sample", withExtension: "pdf")
        pdfView.document = PDFDocument(url: filePath!)

Simulator Screen Shot - iPhone Xʀ - 2020-01-23 at 15.15.07
Sample PDFView snapshot

– How to make an iOS App
Kathiresan Murugan

Protocol Oriented programming in Swift


Hi Friends,

One of the powerful concept called Protocol Oriented Programming (POP) was introduced in WWDC 2015

Here I have some eg. for understanding POP

Basically we use protocols to implement delegation. But now protocols will split a logics from class, structures and enums.

struct People {
    var fatherName: String

    var name: String

    var age: Int
}

Here I create People structure. Its contains name, age properties.

Declaring Protocol

/// Report protocol
protocol Report {
    
    var fullName: String { get }
    
    func textualDescription()
    
    func myAge() -> Int
}

Here I create a protocol named Report contains variable with get and set (read and write) permission.

functions with return types.

Notes: let is not allowed in protocols.

/// Extending people struct. conforming Report protocol
extension People: Report {
    var fullName: String {
        get {
            return name + " " + fatherName
        }
    }
    
    func textualDescription() {
        print("Father's name: \(fatherName), Name: \(name), Age: \(age)")
    }
    
    func myAge() -> Int {
        age
    }
}

Here I extend people struct with conforming Report protocol. and added protocols stubs.

// Implementation
let people = People(fatherName: "Murugan", name: "Kathiresan", age: 27)
people.fullName 
//Kathiresan Murugan

people.textualDescription() 
//Father's name: Murugan, Name: Kathiresan, Age: 27

people.myAge() 
//27

Protocol Composition

protocol Named {
    var name: String { get }
}
protocol Aged {
    var age: Int { get }
}

Here I created two protocols Named and Aged.

struct Person: Named, Aged {
    var name: String
    var age: Int
}

Person structure conformed with Named and Aged protocols.

Implementation

func wishHappyBirthday(to celebrator: Named & Aged) {
    print("Happy birthday, \(celebrator.name), you're \(celebrator.age)!")
}

let birthdayPerson = Person(name: "Kathiresan", age: 27)
wishHappyBirthday(to: birthdayPerson)
//Happy birthday, Kathiresan, you're 27!

Another eg. with class

class Location {
    var latitude: Double
    var longitude: Double
    init(latitude: Double, longitude: Double) {
        self.latitude = latitude
        self.longitude = longitude
    }
}
class City: Location, Named {
    var name: String
    init(name: String, latitude: Double, longitude: Double) {
        self.name = name
        super.init(latitude: latitude, longitude: longitude)
    }
}

Implementation

func beginConcert(in location: Location & Named) {
    print("Hello, \(location.name)!")
}

let seattle = City(name: "Seattle", latitude: 47.6, longitude: -122.3)
beginConcert(in: seattle)
// Prints "Hello, Seattle!"

 
Try POP in your project and optimise your code.

– How to make an iOS App
Kathiresan Murugan

Easy TextField Validation in Swift5


Hi Friends,

I have a easy logic to validate a textFields easily.

for eg. I have implemented a email validation for this textfield.

/// Validate type
enum ValidateType {
    case email
}

Validation properties with User experience.

extension ValidateType {
    
    /// Validation
    /// - Parameter text: text
    func isValid(text: String?) -> ValidationResult {
      guard let text = text else { return .init(isSuccess: false, error: "can't be empty") }

      switch self {
      case .email: return text.isEmail
      }

    }

    /// Keyboard type
    func keyboardType() -> UIKeyboardType {
        switch self {
        case .email: return .emailAddress
        }
    }

    /// Text content type
    func textContentType() -> UITextContentType {
        switch self {
        case .email: return .emailAddress
        }
    }
}

Validation Result is really help to validate a textFields

/// Validation result
struct ValidationResult {
    
    /// is Success Bool
    var isSuccess: Bool
    
    /// Error description default nil
    var error: String?
    
    /// Init
    /// - Parameters:
    ///   - isSuccess: success bool. default true
    ///   - debug: debug string. default nil
    init(isSuccess: Bool = true, error description: String? = nil) {
        self.isSuccess = isSuccess
        self.error = description
    }
}

String Validation. check my

post String Validation using Swift3

/// String Validation
extension String {

    /// Is not blank
    var isNotBlank: ValidationResult {
        if self.trimmingCharacters(in: .whitespaces).isEmpty {
            return .init(isSuccess: false, error: "Can't empty")
        } else {
            return .init()
        }
    }

    /// Trimmed string
    var trimmedString: String {
        self.trimmingCharacters(in: .whitespacesAndNewlines)
    }

    /// Email string is valid
    var isEmail: ValidationResult {
        
        let notBlankResult = self.isNotBlank
        
        if notBlankResult.isSuccess {
            
            let actualText = self.trimmedString
            
            let emailRegEx = "^[a-zA-Z0-9_+&*-]+(?:\\." + "[a-zA-Z0-9_+&*-]+)*@" + "(?:[a-zA-Z0-9-]+\\.)+[a-z" + "A-Z]{2,7}$"
            //"[A-Z0-9a-z._%+-]+@[A-Za-z0-9-]+\\.[A-Za-z]{2,}"
            let emailTest = NSPredicate(format:"SELF MATCHES %@", emailRegEx)
            
            if emailTest.evaluate(with: actualText) {
                return ValidationResult()
            } else {
                return ValidationResult(isSuccess: false, error: "Not in email format")
            }
        } else {
            return notBlankResult
        }
    }
    
}

Eg. Custom textField class
You can use textField with ValideType. It will help easy validate your forms

/// Custom textField with Validation type
class customTextField: UITextField {

    /// Validate type. default .none
    var validateType: ValidateType = .none

    /// Optional field. default false
    var isOptional: Bool = false

    /// Is valid text
    func isValid() -> ValidationResult {
        return validateType.isValid(text: text)
    }
}

Implementation. In ViewController.swift

/// Is Valid fields are valid
func isValidateForm() -> Bool {

 if !emailTextField.isValid() {
  // Show error alert
  return false
 }
 return true
}

 

Ep1

Ep2

 

– How to make an iOS App
Kathiresan Murugan

Use Any datatype for struct property in swift


Hi Friends,

Here I have implemented a sample code to implement Model class. Property may be String or Int. So, that I set it as Any.

struct MyStruct: Decodable {
    let anyProperty: Any
    
    enum CodingKeys: String, CodingKey {
        case anyProperty
    }
    
    init(from decoder: Decoder) throws {
        do {
            let container = try decoder.container(keyedBy: CodingKeys.self)
            if let stringProperty = try? container.decode(String.self, forKey: .anyProperty) {
                anyProperty = stringProperty
            } else if let intProperty = try? container.decode(Int.self, forKey: .anyProperty) {
                anyProperty = intProperty
            } else {
                throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: container.codingPath, debugDescription: "Not a JSON"))
            }
        }
    }
    
}

– How to make an iOS App
Kathiresan Murugan

Disable Dark mode in iOS 13 for your app


Hi Friends,

Basically iOS 13 application UI appearance will automatically support dark mode.

Basically some of the application didn’t need dark mode support so, They will start searching how to disable dark mode in my application?

We can handle for a particular viewController

In ViewDidLoad()

overrideUserInterfaceStyle = .light

check for overrideUserinterface

check for developer.apple/…/interfaceStyle

Or else you can disable for hole application by adding UIUserInterfaceStyle as Light in info.plist

key = UIUserInterfaceStyle
value = Light

– How to make an iOS App
ktrkathir

Captcha Generator Swift Package


Hi Friends,

As per comment of captcha Objective-CScreenshot 2019-12-15 at 9.40.26 AM

Screenshot 2019-12-15 at 9.53.39 AM
Captcha generator swift

SwiftPackage Source code GitHub

Implementation

  /// Captcha generator
  var captcha = CaptchaGenerator()
  captchaLabel.attributedText = captcha.generate()
/// Validation
 if captcha.isMatched(text: field.text ?? "") {
   // success
 }

– How to make an iOS App
ktrkathir

MediaPicker Swift Package


Hi Friends,

Here I posted MediaPicker Swift Package. Its contains a Custom ImagePicker and Image storing in document directory.

You can download this swift package from GitHub.com

example code to pick a image form take photo, camera roll and gallery.

ImagePicker

override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        //ImagePicker example code
        let imagePicker = ImagePicker(presentationController: self, delegate: self)
        imagePicker.present(from: self.view)
}
extension ViewController: ImagePickerDelegate {
    
    func imagePicker(picker: ImagePicker, didSelected image: UIImage?, apikey key: String?) {
        guard let image = image else { return }
        // write your code here...
    }
    
    
}

 


MediaManager – Download image from url and store to document directory

// Media manager example code
        let imageURL = URL(string: "http://mediastore.com/public/avatar/134356300.jpeg")!
        MediaManager.shared.downloadImage(url: imageURL, completion: { (image) in
            guard let image = image else { return }
            // write your code here...

        }) { (errorLog) in
            guard let errorLog = errorLog else { return }
            
            print(errorLog)
        }

MediaManager – Download image from url and show in UIImageView

 // MediaManager + UIImageView
        let bannerURLString = "http://mediastore.com/public/banner/001.jpeg"
        UIImageView().imageFromURL(urlString: bannerURLString)

– How to make an iOS App
ktrkathir

HttpConnection Swift Package


Hi Friends,

Here I posted my first swift package in Swift5.1.
Purpose of this package is helps to retrieve data from url.

You can download this swift package from GitHub.com

example code to retrieve personal detail from url.

Modelclass for personal detail

import HttpConnection

/// Personal detail
struct PersonalDetail: Decodable {
    let name: String
    let age: Int
    let dob: String
    let address: String
}

Extens for api calling

extension PersonalDetail {
    
    /// Fetch from url
    /// - Parameter result: Personal detail
    static func fetch(result: @escaping((Result) -> Void)) {
        
        let urlString = "http://enterpriseManage.com/db/v1/personal_detail"
        // create URL
        guard let url = URL(string: urlString) else {
            result(.failure(.invalidURL))
            return
        }
        // Create URLInputs using url.
        let urlInput: URLInputs = .init(requestURL: url)
        
        fetchResource(urlInputs: urlInput, completion: result)
    }
}

– How to make an iOS App
ktrkathir

Starter, show at first time launching your app


Hi Friends,

Here I developed a feature list viewController like Apple native apps.
Most of the apple native apps was showing major features list at first time of application opened. Its simple, clear designed.

So, I just develop like a feature list screen. I will call this the “Starter

Starter is used to show major 3 features at center of the screen.

StarterViewController

I have created a GitHub Repository for Starter. You can easily download here

Drag and drop Get Start folder and implement in AppDelegate didFinishLaunchingWithOptions

 /// Show starter
        let startVC = StarterViewController.loadFromNib()
        startVC.loadView()
        startVC.themeColor = UIColor.blue.withAlphaComponent(0.7)
        startVC.welcomeLabel.text = "Welcome to"
        startVC.appNameLabel.text = "Starter"
        startVC.featureDescriptionLabel.text = "You can use starter show release notes better and clearly like Apple native apps."
        startVC.dismiss.setTitle("Continue", for: .normal)
        
        let details = [FeatureDetail(icon: #imageLiteral(resourceName: "photos"),
                                     title: "Clear details",
                                     subTitle: "Present a major features to yours like this."),
                       FeatureDetail(icon: #imageLiteral(resourceName: "photos"),
                                     title: "Fully Customized",
                                     subTitle: "Full permission to customise what you need."),
                       FeatureDetail(icon: #imageLiteral(resourceName: "photos"),
                                     title: "Press continue",
                                     subTitle: "Press continue button below of this to start using your application.")]
        startVC.features = details
        startVC.delegate = self
        window?.rootViewController = startVC
    

protocol implementation

/// MARK: Starter View Delegate
extension AppDelegate: StarterViewDelegate {
    
    func continueButtonWasTapped(startViewController: StarterViewController) {
        // StarterViewController continue button was tapped.
        
        let initialVC = UIStoryboard(name: "Main", bundle: Bundle.main).instantiateInitialViewController()
        window?.rootViewController = initialVC
    }
    
}

How to make an iOS App
– ktrkathir

“Finding Emojis in String😀” using Swift


Hi Friends,

Emoji detection is very Important in Chat application.

After I done chat conversation screen and I saw a WhatsApp application and I find a Emoji dictation That will show little bit larger than text. So, I analyse how they are finding the emoji in string?.

Finally I found the solution for this.

Using CoreText Framework, UnicodeScalar in Foundation

import Foundation
import CoreText

extension UnicodeScalar {
    /// Note: This method is part of Swift 5, so you can omit this.
    /// See: https://developer.apple.com/documentation/swift/unicode/scalar
    var isEmoji: Bool {
        switch value {
        case 0x1F600...0x1F64F, // Emotions
        0x1F300...0x1F5FF, // Misc Symbols and Pictographs
        0x1F680...0x1F6FF, // Transport and Map
        0x1F1E6...0x1F1FF, // Regional country flags
        0x2600...0x26FF, // Misc symbols
        0x2700...0x27BF, // Dingbats
        0xE0020...0xE007F, // Tags
        0xFE00...0xFE0F, // Variation Selectors
        0x1F900...0x1F9FF, // Supplemental Symbols and Pictographs
        0x1F018...0x1F270, // Various asian characters
        0x238C...0x2454, // Misc items
        0x20D0...0x20FF: // Combining Diacritical Marks for Symbols
            return true
            
        default: return false
        }
    }
    
    var isZeroWidthJoiner: Bool {
        return value == 8205
    }
}

In String Extension class

extension String {
    
    // Not needed anymore in swift 4.2 and later, using `.count` will give you the correct result
    var glyphCount: Int {
        let richText = NSAttributedString(string: self)
        let line = CTLineCreateWithAttributedString(richText)
        return CTLineGetGlyphCount(line)
    }
    
    var isSingleEmoji: Bool {
        return glyphCount == 1 && containsEmoji
    }
    
    var containsEmoji: Bool {
        return unicodeScalars.contains { $0.isEmoji }
    }
    
    var containsOnlyEmoji: Bool {
        return !isEmpty
            && !unicodeScalars.contains(where: {
                !$0.isEmoji && !$0.isZeroWidthJoiner
            })
    }
    
    // The next tricks are mostly to demonstrate how tricky it can be to determine emoji's
    // If anyone has suggestions how to improve this, please let me know
    var emojiString: String {
        return emojiScalars.map { String($0) }.reduce("", +)
    }
    
    var emojis: [String] {
        var scalars: [[UnicodeScalar]] = []
        var currentScalarSet: [UnicodeScalar] = []
        var previousScalar: UnicodeScalar?
        
        for scalar in emojiScalars {
            if let prev = previousScalar, !prev.isZeroWidthJoiner, !scalar.isZeroWidthJoiner {
                scalars.append(currentScalarSet)
                currentScalarSet = []
            }
            currentScalarSet.append(scalar)
            
            previousScalar = scalar
        }
        
        scalars.append(currentScalarSet)
        
        return scalars.map { $0.map { String($0) }.reduce("", +) }
    }
    
    fileprivate var emojiScalars: [UnicodeScalar] {
        var chars: [UnicodeScalar] = []
        var previous: UnicodeScalar?
        for cur in unicodeScalars {
            if let previous = previous, previous.isZeroWidthJoiner, cur.isEmoji {
                chars.append(previous)
                chars.append(cur)
                
            } else if cur.isEmoji {
                chars.append(cur)
            }
            
            previous = cur
        }
        
        return chars
    }
}

Here I unit test emojis

  func testEmojo() {
        
        XCTAssertTrue("😀".isSingleEmoji)
        XCTAssertTrue("👋🏽🏛".containsOnlyEmoji)
        XCTAssertTrue("Hello 👨‍👩‍👧‍👧".containsEmoji)
        
        XCTAssertFalse("a".isSingleEmoji)
        XCTAssertFalse("🙀1😈".containsOnlyEmoji)
        XCTAssertFalse("Hello world".containsEmoji)
        
        XCTAssertEqual("🙀5🎃".emojis, ["🙀","🎃"])
        XCTAssertEqual("👣1🙏🏽".emojiString, "👣🙏🏽")
        XCTAssertEqual("👨".glyphCount, 1)
        XCTAssertEqual("👨‍👨‍👧🤳".glyphCount, 2)

        XCTAssertEqual("🐽".count, 1)
        XCTAssertEqual("🦊🥛".count, 2)
        
        XCTAssertNotEqual("🛴1🚘".emojis, ["🛴"])
        XCTAssertNotEqual("🚄asdf🚜".emojiString, "🚄asdf🚜")
        XCTAssertNotEqual("🗽US🌂".emojiString, "🗽US")
        XCTAssertNotEqual("🗽US🌂".emojiString, "US🌂")
    }

– How to make an iOS App
ktrkathir