3D Touch – Home screen quick actions dynamically in Swift


Hello Friends,

Here I have implemented a dynamic Home screen Quick action – shortcutItems

Home screen QuickActions

In this tutorial I have created 3 shortcuts to access a TabBarController screens.

  • Dashboard
  • Health
  • Games

UIApplicationShortcutItem contains

  • Type
  • localizedTitle
  • localizedSubtitle
  • icon and UserInfo
let dashboard = UIApplicationShortcutItem(type: "Screen1", localizedTitle: "Dashboard", localizedSubtitle: nil, icon: UIApplicationShortcutIcon(templateImageName: "dashboard"), userInfo: nil) // shortcut 1
        
let health = UIApplicationShortcutItem(type: "Screen2", localizedTitle: "Health", localizedSubtitle: nil, icon: UIApplicationShortcutIcon(templateImageName: "Health"), userInfo: nil) // shortcut 2
        
let games = UIApplicationShortcutItem(type: "Screen3", localizedTitle: "Games", localizedSubtitle: nil, icon: UIApplicationShortcutIcon(templateImageName: "Games"), userInfo: nil)
// shortcut 3
 
UIApplication.shared.shortcutItems = [dashboard, health, games] // Assigning all shortcuts

Handle user tapped shortcut item in AppDelegate.

   func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
        
       if let tabController = window?.rootViewController as? UITabBarController {
            switch shortcutItem.type {
            case "Screen1":
                tabController.selectedIndex = 0
            case "Screen2":
            tabController.selectedIndex = 1
            default:
                tabController.selectedIndex = 2
            }
        }
        completionHandler(true)
    }

– How to make an iOS App
ktrkathir

Advertisements

Dynamic App icon in iOS 10.3 and above


Hi Friends,

iOS 10.3 Apple gives ability to change App icon by programmatically. Its powerfull. But, You can’t able to update like clock app.

Dynamic AppIcon
Simulator screenshot

AppIcons pixel size.

      • 2x.png = 120×120
      • 3x.png = 180×180

Resource files

      • stack2x.png
      • stack3x.png
      • victory2x.png
      • victory3x.png
      • world2x.png
      • world3x.png

Follow 3 steps to archive dynamic app icon in iOS

      1. Drag and drop AppIcon 2x and 3x images to project
      2. Register AppIcons in info.plist using CFBundleIcons
      3. Set AppIcon dynamically using setAlternateIconName

Lets start.

Step 1:  Drag and drop AppIcon images is project navigator. Dynamic AppIcon - Project navigation

Step 2:  Use CFBundleIcons in info.plist. Use three dictionary keys to register primary icon and Alternate icons.

      • Primaty icon – CFBundlePrimaryIcon
      • Alternate icon – CFBundleAlternateIcons

Dynamic AppIcon info.plist

Step 3: Use setAlternateIconName method and set update registered AppIcon.

As I mentioned at top of the post. (image: Simulator screenshot)

I have designed there UIButton and set AppIcon images for that. In ViewController.swift I have created a three UIButton Actions and additional method to update AppIcon.

Check Alternate AppIcon is supported this is app. Using UIApplication.shared.supportsAlternateIcons

Update Alternate AppIcon using UIApplication.shared.setAlternateIconName

    @IBAction func icon1(_ sender: Any) {
        setIcon(iconName: "AppIcon-1")
    }
    
    @IBAction func icon2(_ sender: Any) {
        setIcon(iconName: "AppIcon-2")
    }
    
    @IBAction func icon3(_ sender: Any) {
        setIcon(iconName: "AppIcon-3")
    }
    
    func setIcon(iconName: String) {
        
        guard UIApplication.shared.supportsAlternateIcons else {
            return
        }
        
        UIApplication.shared.setAlternateIconName(iconName) { (error) in
            if let error = error {
                print("Error: \(error)")
            } else {
                print("App icon updated.")
            }
        }
    }

That all. Done it.

Notes:

To reset AppIcon to primary. Set AlternateIcon name as nil.

UIApplication.shared.setAlternateIconName(nil)

Source code: download

– How to make an iOS App
ktr kathir

Design a Bus | Theatre tickets booking screen UI in Swift


Hi Friends,

I have achieved a design of Bus tickets booking screen UI on Swift.
Yes.

How did this?
I used CAShapeLayer.

SeatShapeLayer
Bus ticket UI

Here I have created a subclass for CAShapeLayer as SeatShapeLayer.

/// Seat shape layer
class SeatShapeLayer: CAShapeLayer {
    
    override init(layer: Any) {
        super.init(layer: layer)
    }
    
    fileprivate var size: CGSize!
    
    init(frame: CGRect) {
        super.init()
        self.frame = frame
        size = frame.size
        setup()
    }
    
    override init() {
        super.init()
        setup()
    }
    
    /// Setup
    func setup() {
        strokeColor = UIColor.lightGray.cgColor
        fillColor = UIColor.clear.cgColor
        
        let drawPath = CGMutablePath()
        drawPath.addRoundedRect(in: CGRect(x: 0, y: 0, width: size.width, height: size.height), cornerWidth: 4, cornerHeight: 4, transform: .identity)
        path = drawPath
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
    
    /// Selected
    func selected() {
            let textLayer = CATextLayer()
            textLayer.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height)
            textLayer.alignmentMode = .center
            textLayer.fontSize = 15
            textLayer.cornerRadius = 4
            textLayer.backgroundColor = UIColor.lightGray.cgColor
            textLayer.foregroundColor = UIColor.white.cgColor
            addSublayer(textLayer)
    }
}

In your viewController. You can call SeatShapeLayer.

//In viewDidLoad
 var x = 10
        var y = 100
        
        for _ in 0...10 {
            for i in 0...2 {
                let seatLayer = SeatShapeLayer(frame: CGRect(x: x, y: y, width: 20, height: 20))
                view.layer.addSublayer(seatLayer)
                x = x + 20 + 5
                if i % 2 == 0 {
                    x = x + 10
                }
            }
            x = 10
          y = y + 20 + 5
        }

Use touches ended to track if the seat was clicked.

 override func touchesEnded(_ touches: Set, with event: UIEvent?) {
        if let touch = touches.first {
            let point = touch.location(in: self.view)
            
            if let layer = self.view.layer.hitTest(point) as? SeatShapeLayer {
                layer.selected()
            } else if  let layer = self.view.layer.hitTest(point) as? CATextLayer {
               layer.removeFromSuperlayer()
            }
        }
    }

– How to make an iOS App
ktrkathir

Draw shapes using CAShapeLayer iOS


Hi Friends,

Using CAShapeLayer you can crop your UIImageView with any shapes. Here I done a small example like below.

Layer crop

let shapeLayer = CAShapeLayer()
        shapeLayer.strokeColor = UIColor.black.cgColor
        shapeLayer.fillColor = UIColor.blue.cgColor
        shapeLayer.lineWidth = 2
        
        let path = CGMutablePath()
        path.addEllipse(in: CGRect(x: 0, y: 0, width: 100, height: 100))
        path.move(to: .zero)
        path.addLine(to: CGPoint(x: 0, y: 50))
        path.addQuadCurve(to: CGPoint(x: 50, y: 0), control: CGPoint(x: 7, y: 7))
        
        shapeLayer.path = path
        imageView.layer.mask = shapeLayer

– How to make an iOS App
ktrkathir

Convert String to Image using UIGraphics


Hi Friends,

Its Simple to convert a String to image by using UIGraphics. Here I have shared a code. This is a extension function of String. It will return a Image.

// MARK: - String Extension functions.
extension String {
    
    /// Convert String to Image
    ///
    /// - Returns: image.
    func image() -> UIImage? {
        // Size of Image
        let size = CGSize(width: 100, height: 100)
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        UIColor.white.set() //clear.set()
        
        let rect = CGRect(origin: CGPoint(), size: size)
        UIRectFill(CGRect(origin: CGPoint(), size: size))
        (self as NSString).draw(in: rect, withAttributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 90)])
        
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}

– How to make an iOS App
ktrkathir

Location based Augmented Reality using ARKit in iOS


Hi Friends,

Its time to learn ARKit in iOS. Yes. I have start learning of ARKit in iOS.

Scope: Showing information for particular location coordinates. Like below image

Location based AR

Using ARKit and CoreLocation Framework‘s. Its possible to archive.

I have set of places like

 var places: [Place] = [Place(name: "L", lati: 11.053791, lngi: 76.990920, id: 1),Place(name: "R", lati: 11.051854, lngi: 76.991360, id: 2),Place(name: "F", lati: 11.052917, lngi: 76.990507, id: 3),Place(name: "B", lati: 11.053418, lngi: 76.992725, id: 4)]

What I done this is project is.

    1. I have used above static places and converted to SCNNode(SceneNode).
    2. Placing each SCNNode in position of location coordinates. Have to convert coordinates to XYZ Axis.
    3. Based on Z axis have to scale a SCNNode. Then only It will show big when user reach near to the place.
    4. While user rotate iPhone. SCNNode will automatically rotate by using transformMatrix.
    5. When SCNNode is visible. Automatically Particular position information will be show on the top of the screen.

For your Understanding Here I added this image how Scene kit axis are.
Scene kit Axis

Source code: GitHub

– How to make an iOS App
ktrkathir

Custom DatePickerViewController in Swift


Preview screenshot
Custom DatepickerViewController

Call this Class like below

let picker = CustomDatePickerViewController(title: "Schedule", from: Date())
        picker.okButtonSelected { (selectedDate) in
            print(selectedDate.time)
            print(selectedDate.day)
        }
        
        DispatchQueue.main.async {
            self.present(picker, animated: true, completion: nil)
        }

Download complete source code: Custom DatePickerViewController


– How to make an iOS App
ktrkathir

Check your network connection using Network.framework in iOS 12.0 and above.


HI Developer,

When ever we are calling url on iOS. Before we will check is we are connected to network or not.
Many ways in iOS to detect a network connection state. Here I have tried. by Network.Framework

Class for Checking reachability connection

import Network

/// Network connection
class NetworkConnection {
    
    /// Dispatch queue
   private var queue = DispatchQueue(label: "Monitor", qos: .default, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)
    
    /// Network connection monitor. It will automatically notify when ever you connection was update.
    ///
    /// - Parameter isConnected: isConnected to internet or not.
    func networkMonitor(isConnected: @escaping((_ state: Bool,_ interfare: String?) -> ())) {
        
        let pathMonitor = NWPathMonitor(requiredInterfaceType: .wifi)
        
        pathMonitor.pathUpdateHandler = { path in
            
            if path.status == NWPath.Status.satisfied {
                
                if path.usesInterfaceType(.wifi) {
                    isConnected(true, "WiFi")
                } else if path.usesInterfaceType(.cellular) {
                    isConnected(true, "cellular")
                } else if path.usesInterfaceType(.wiredEthernet) {
                    isConnected(true, "wiredEthernet")
                } else {
                    isConnected(true, "others")
                }
            } else {
                isConnected(false, nil)
            }
            print("is Cellular data: \(path.isExpensive)") //Checking is this is a Cellular data
        }
        pathMonitor.start(queue: queue)
    }
}

On your ViewController.swift

        //Handle your network updations
        let networkConnection = NetworkConnection()
        networkConnection.networkMonitor { (isConnected, connection) in
            if isConnected {
                let mainQueue = DispatchQueue.main
                mainQueue.async {
                    self.view.backgroundColor = UIColor.green.withAlphaComponent(0.9)
                    self.title = "Network connected to \(connection!)"
                }
            } else {
                let mainQueue = DispatchQueue.main
                mainQueue.async {
                    self.view.backgroundColor = UIColor.orange.withAlphaComponent(0.8)
                    self.title = "Network not connected"
                }
            }
        }

GitHub link – NetworkChecker

– How to make an iOS App
ktrkathir

Internal Browser in Swift 4.2


Hi Friends,

When ever load a browser inside of application. Apple is preferred SafariServices.
This class will help to load a url from anywhere in your project. like from ViewController or any NSObject class.

So, that I have created a class to call a SafariViewController.

import UIKit
import SafariServices

/// Internal browser - Safari service view controller
class Browser: NSObject {
    
    /// SafariViewController
    fileprivate var safariVC: SFSafariViewController!
    
    weak var delegate: BrowserDelegate!
    
    /// Config
    fileprivate func config(_ loadUrl: URL) {
        
        if #available(iOS 11.0, *) {
            let config = SFSafariViewController.Configuration()
            config.barCollapsingEnabled = true
            config.entersReaderIfAvailable = true
            safariVC = SFSafariViewController(url: loadUrl, configuration: config)
        } else {
            // Fallback on earlier versions
            safariVC = SFSafariViewController(url: loadUrl)
        }
    }
    
    /// Initialize Browser
    ///
    /// - Parameter loadUrl: url
    init(loadUrl: URL) {
        super.init()
        config(loadUrl)
    }
    
    /// Start loading url on browser
    func startLoading() {
        
        DispatchQueue.global().sync {
            self.safariVC.delegate = self
        }
        
        if let delegate = delegate { delegate.browserWillAppear(self) }
        UIApplication.shared.keyWindow?.rootViewController?.present(safariVC, animated: true, completion: nil)
    }
}

SFSafariViewControllerDelegate

// MARK: - SFSafariViewControllerDelegate
extension Browser: SFSafariViewControllerDelegate {
    
    func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
        if let delegate = delegate { delegate.browserWillDisappear(self) }
    }
    
}

BrowserDelegate

/// Browser Delegate
protocol BrowserDelegate: NSObjectProtocol {
    
    /// Browser will appeared
    ///
    /// - Parameter browser: browser
    func browserWillAppear(_ browser: Browser)
    
    /// Browser will disappear
    ///
    /// - Parameter browser: browser
    func browserWillDisappear(_ browser: Browser)
}

You can use this class in your ViewController as like below

/// Browser for internal
    fileprivate var browser: Browser!
 browser = Browser(loadUrl: url)
 browser.delegate = self
 browser.startLoading()
// MARK: - BrowserDelegate
extension ViewController: BrowserDelegate {
    
    func browserWillAppear(_ browser: Browser) {
        // Do something here
    }
    
    func browserWillDisappear(_ browser: Browser) {
       // Do something here
    }
}

– How to make an iOS App
ktrkathir

Layout constraints in Swift


Hi Friends,

AutoLayout constraints are easy now.

Bellow extension class was helpful to set a constraints. Check out below

import UIKit

struct AnchoredConstraints {
    var top, leading, bottom, trailing, width, height: NSLayoutConstraint?
}
extension UIView {
    
    @discardableResult
    func anchor(top: NSLayoutYAxisAnchor?, leading: NSLayoutXAxisAnchor?, bottom: NSLayoutYAxisAnchor?, trailing: NSLayoutXAxisAnchor?, padding: UIEdgeInsets = .zero, size: CGSize = .zero) -> AnchoredConstraints {
        
        translatesAutoresizingMaskIntoConstraints = false
        var anchoredConstraints = AnchoredConstraints()
        
        if let top = top {
            anchoredConstraints.top = topAnchor.constraint(equalTo: top, constant: padding.top)
        }
        
        if let leading = leading {
            anchoredConstraints.leading = leadingAnchor.constraint(equalTo: leading, constant: padding.left)
        }
        
        if let bottom = bottom {
            anchoredConstraints.bottom = bottomAnchor.constraint(equalTo: bottom, constant: -padding.bottom)
        }
        
        if let trailing = trailing {
            anchoredConstraints.trailing = trailingAnchor.constraint(equalTo: trailing, constant: -padding.right)
        }
        
        if size.width != 0 {
            anchoredConstraints.width = widthAnchor.constraint(equalToConstant: size.width)
        }
        
        if size.height != 0 {
            anchoredConstraints.height = heightAnchor.constraint(equalToConstant: size.height)
        }
        
        [anchoredConstraints.top, anchoredConstraints.leading, anchoredConstraints.bottom, anchoredConstraints.trailing, anchoredConstraints.width, anchoredConstraints.height].forEach{ $0?.isActive = true }
        
        return anchoredConstraints
    }
}
    func fillSuperview(padding: UIEdgeInsets = .zero) {
        translatesAutoresizingMaskIntoConstraints = false
        if let superviewTopAnchor = superview?.topAnchor {
            topAnchor.constraint(equalTo: superviewTopAnchor, constant: padding.top).isActive = true
        }
        
        if let superviewBottomAnchor = superview?.bottomAnchor {
            bottomAnchor.constraint(equalTo: superviewBottomAnchor, constant: -padding.bottom).isActive = true
        }
        
        if let superviewLeadingAnchor = superview?.leadingAnchor {
            leadingAnchor.constraint(equalTo: superviewLeadingAnchor, constant: padding.left).isActive = true
        }
        
        if let superviewTrailingAnchor = superview?.trailingAnchor {
            trailingAnchor.constraint(equalTo: superviewTrailingAnchor, constant: -padding.right).isActive = true
        }
    }
    
    func centerInSuperview(size: CGSize = .zero) {
        translatesAutoresizingMaskIntoConstraints = false
        if let superviewCenterXAnchor = superview?.centerXAnchor {
            centerXAnchor.constraint(equalTo: superviewCenterXAnchor).isActive = true
        }
        
        if let superviewCenterYAnchor = superview?.centerYAnchor {
            centerYAnchor.constraint(equalTo: superviewCenterYAnchor).isActive = true
        }
        
        if size.width != 0 {
            widthAnchor.constraint(equalToConstant: size.width).isActive = true
        }
        
        if size.height != 0 {
            heightAnchor.constraint(equalToConstant: size.height).isActive = true
        }
    }
    

– How to make an iOS App
ktrkathir

How to implement custom UIMenuController in Swift


Hi Friends,

Its time to learn how to show a custom UIMenuController for any views. Like

Its easy to implement.

Follow below steps:

  • Enable user interaction for particular view
  • Add long press gesture recognizer.
  • Implement custom UIMenuItem and add to UIMenuController
  • Enable can become first responder

In ViewController.swift add a view and set long press gestureRecognizer

let bgView = UIView(frame: CGRect(x: 20, y: 200, width: 100, height: 30))
bgView.backgroundColor = UIColor.gray
bgView.isUserInteractionEnabled = true
view.addSubview(bgView)
        
let gestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(longPressGesture(rec:)))
bgView.addGestureRecognizer(gestureRecognizer)

// Long press gestureRecognizer handler

 @objc func longPressGesture(rec: UIGestureRecognizer) {
        
        if let recView = rec.view, let superRecView = recView.superview {
            // Creating a custom UIMenu Controller
            UIMenuController.shared.menuItems = [UIMenuItem(title: "Save", action: #selector(saveContent))]
            
            UIMenuController.shared.setTargetRect(recView.frame, in: superRecView)
            UIMenuController.shared.arrowDirection = .default
            UIMenuController.shared.setMenuVisible(true, animated: true)
        }
    }

Implement a save button action like below

  @objc func saveContent(_ sender: Any) {
        print("Copy content")
    }

And one more thing. Must have to set true for viewController to canBecomeFirstResponder. So,

override var canBecomeFirstResponder: Bool {
        return true
}

That all. Run your code.

– How to make an iOS App
ktrkathir

Check you are connected to internet by SystemConfiguration Framework in Swift


HI Developer,

When ever we are calling url on iOS. Before we will check is we are connected to internet or not.
Many ways in iOS to detect a network connection state. Here I have tried. by SystemConfiguration.framework

Class for Checking reachability connection

import Foundation
import SystemConfiguration

public class Reachability {
    
   class private var netWorkReachability: SCNetworkReachability? {
        var zeroAddress = sockaddr_in(sin_len: 0, sin_family: 0, sin_port: 0, sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
        zeroAddress.sin_len =  UInt8(MemoryLayout.size)
        zeroAddress.sin_family = sa_family_t(AF_INET)
        
        // Passes the reference of the struct
        let defaultRouteReachable = withUnsafePointer(to: &zeroAddress, { pointer in
            // Converts to a generic socket address
            return pointer.withMemoryRebound(to: sockaddr.self, capacity: MemoryLayout.size) {
                // $0 is the pointer to `sockaddr`
                return SCNetworkReachabilityCreateWithAddress(nil, $0)
            }
        })
        
        return defaultRouteReachable
    }
    
    
    class func isConnected() -> Bool {
        
        var flags = SCNetworkReachabilityFlags()
        if !SCNetworkReachabilityGetFlags(netWorkReachability!, &flags) {
            return false
        }
        
        let isReachable: Bool = flags.contains(.reachable)
        let needConnection = flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired) != 0
        
        return (isReachable && !needConnection)
    }
}

Follow this code to validate a network connection

if Reachability.isConnected() {
    print("You are connected.")
} else {
    print("You are not connected.")
}

– How to make an iOS App
ktrkathir

Tic Tac Toe-Algorithm in Swift


My First Game – Tic Tac Toe
/// Placed Object
///
/// - computer: computer
/// - player: player
enum Placed: String {
    case none = " "
    case computer = "X"
    case player = "O"
}
/// Next move
///
/// - computer: computer turn
/// - player: player turn
enum Turn {
    case computer
    case player
}
/// Game state
    ///
    /// - play: continue to play
    /// - draw: match draw
    /// - wonByComputer: Computer win the game
    /// - wonByPlayer: player win the game
    enum GameState {
        case play
        case draw
        case wonByComputer
        case wonByPlayer
    }
  /// Result of the game
    func result() ->GameState {
        
        let indexes = source.placedIndex
        
        if indexes.computer.isValid() {
            newGame()

            return GameState.wonByComputer
        } else if indexes.player.isValid() {
            newGame()

            return GameState.wonByPlayer

        } else if indexes.empty.count > 0 {
            return GameState.play
        } else {
            newGame()
            return GameState.draw
        }
    }
    
    /// Insert new index
    ///
    /// - Parameter at: position
    func insert(at: Int, doneBy: Placed) {
        
        if source[at] == .none {
           source[at] = doneBy
        }
    }
    
    /// Best move
    ///
    /// - Returns: best posibile index
    func bestMove() -> Int {
        
        let indexes = source.placedIndex
        
        if indexes.player.count == 0 {
            return indexes.empty.randomElement() ?? 0
        } else if indexes.player.count  == 1 {
            
            if let first = indexes.player.first {
                switch first {
                case 0:
                    return [1,2,3,4,6,8].randomElement() ?? 1
                case 1:
                    return [0,2,4,7].randomElement() ?? 0
                case 2:
                    return [0,1,4,5,6,8].randomElement() ?? 0
                case 3:
                    return [0,4,5,6].randomElement() ?? 0
                case 4:
                    return indexes.empty.randomElement() ?? 0
                case 5:
                    return [2,3,4,8].randomElement() ?? 2
                case 6:
                    return [0,2,3,4,7,8].randomElement() ?? 0
                case 7:
                    return [1,4,6,8].randomElement() ?? 1
                default:  // 8
                    return [0,2,4,5,6,7].randomElement() ?? 8
                }
            }
            return indexes.empty.randomElement() ?? 0
        } else  {
            
            let computerPosibileIndex = getPosibilities(playiedIndexies: indexes.computer, emptyIndexies: indexes.empty)
            
            var temp = indexes.computer
            temp.append(computerPosibileIndex)
            
            if temp.isValid() {
                return computerPosibileIndex
            } else {
                return getPosibilities(playiedIndexies: indexes.player, emptyIndexies: indexes.empty) // Get posibilities
            }
        }
    }
    
    // variadic function
    func isPosibleIndex(_ index: Int, places: [Int]..., empties: [Int], placedIndex: [Int]) -> Bool {
        
        var posibile: Bool = false
        
        if empties.contains(index) {
            
            for item in 0..<places.count {
                let place = places[item]
                
                if let first = place.first, let last = place.last {
                    if placedIndex.contains(first), placedIndex.contains(last) {
                        posibile = true
                        break
                    } else {
                        posibile = false
                    }
                }
            }
        }
        return posibile
    }
    
    /// get Posibile index
    ///
    /// - Parameters:
    ///   - placedIndex: already placed index
    ///   - empties: empty indexes
    /// - Returns: posibile index
    public func getPosibilities(playiedIndexies: [Int], emptyIndexies: [Int]) -> Int {
        
        if isPosibleIndex(0, places: [1,2], [4,8], [3,6], empties: emptyIndexies, placedIndex: playiedIndexies) {
            return 0
        } else if isPosibleIndex(1, places: [0,2], [4,7], empties: emptyIndexies, placedIndex: playiedIndexies) {
            return 1
        } else if isPosibleIndex(2, places: [0,1],[4,6],[5,8], empties: emptyIndexies, placedIndex: playiedIndexies) {
            return 2
        } else if isPosibleIndex(3, places: [0,6],[4,5], empties: emptyIndexies, placedIndex: playiedIndexies) {
            return 3
        } else if isPosibleIndex(4, places: [0,8],[1,7],[2,6],[3,5], empties: emptyIndexies, placedIndex: playiedIndexies) {
            return 4
        } else if isPosibleIndex(5, places: [2,8],[4,3], empties: emptyIndexies, placedIndex: playiedIndexies) {
            return 5
        } else if isPosibleIndex(6, places: [3,0],[2,4],[7,8], empties: emptyIndexies, placedIndex: playiedIndexies) {
            return 6
        } else if isPosibleIndex(7, places: [1,4],[6,8], empties: emptyIndexies, placedIndex: playiedIndexies) {
            return 7
        } else if isPosibleIndex(8, places: [0,4],[2,5],[6,7], empties: emptyIndexies, placedIndex: playiedIndexies) {
            return 8
        } else {
            return emptyIndexies.randomElement() ?? 8
        }
    }
In ViewController

/// Game state
    ///
    /// - play: continue to play
    /// - draw: match draw
    /// - wonByComputer: Computer win the game
    /// - wonByPlayer: player win the game
    enum GameState {
        case play
        case draw
        case wonByComputer
        case wonByPlayer
    }
   
    var source: [Placed] = Array(repeatElement(Placed.none, count: 9))
    
    var turn: Turn = .player
    
    var lastWon: Turn = .player
    
    func newGame() {
        source = Array(repeatElement(Placed.none, count: 9))
    }
extension Array where Element == Placed {
    
    /// Placed Indexes - Filter each index and find which item was filled that.
    /// return empty object index, computer placed index, player placed index
    var placedIndex: (empty: [Int], computer: [Int], player: [Int]) {
        
        let empty = self.indexes(of: .none)
        let computer = self.indexes(of: .computer)
        let player = self.indexes(of: .player)
        
        return (empty, computer, player)
    }
}

extension Array where Element == Int {
    /// Posibilities check and validate rows based on item index
    func isValid() -> Bool {
        
        let places: [Int] = self
        
        func verify(first: Int, second: Int, last: Int) -> Bool {
            
            if places.contains(first), places.contains(second), places.contains(last) {
                return true
            }
            return false
        }
        
        if verify(first: 0, second: 1, last: 2) || verify(first: 3, second: 4, last: 5) || verify(first: 6, second: 7, last: 8) || verify(first: 0, second: 3, last: 6) || verify(first: 1, second: 4, last: 7) || verify(first: 2, second: 5, last: 8) || verify(first: 0, second: 4, last: 8) || verify(first: 2, second: 4, last: 6) {
            return  true
        } else {
            return false
        }
    }
    
}

extension Array where Element: Equatable {
    
    /// Indexes of elements
    ///
    /// - Parameter element: search Element
    /// - Returns: indexes
    func indexes(of element: Element) -> [Int] {
        return self.enumerated().filter({ element == $0.element }).map({ $0.offset })
    }
    
}

– How to make an iOS

   App ktrkathir

Register UIFont by programmatically in swift


  1. Download  .ttf format
  2. Drag and drop in project
  3. run this code at first
func installFont(_ font:String) -> Bool {

    guard let fontUrl = Bundle.main.url(forResource: font, withExtension: "ttf") else {
        return false
    }

    let fontData = try! Data(contentsOf: fontUrl)

    if let provider = CGDataProvider.init(data: fontData as CFData) {

        var error: Unmanaged<CFError>?

        let font:CGFont = CGFont(provider)
        if (!CTFontManagerRegisterGraphicsFont(font, &error)) {
            print(error.debugDescription)
            return false
        } else {
            return true
        }
    }
    return false
}

After that you can check. is font installed or not. by using following code

 /// Available fonts in App
    func availableFontsInApp() {
        
        let fontFamilyNames = UIFont.familyNames
        
        for familyName in fontFamilyNames {
            print("------------------------------")
            print("Font Family Name = [\(familyName)]")
            let names = UIFont.fontNames(forFamilyName: familyName )
            print("Font Names = [\(names)]")
        }
    }

– How to make an iOS App ktrkathir

How to change UIImage dimension to (299 * 299) on Swift


func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
      
  picker.dismiss(animated: true)
  classifier.text = "Analyzing Image..."
  guard let image = info["UIImagePickerControllerOriginalImage"] as? UIImage else {
            return
        } 
        
  UIGraphicsBeginImageContextWithOptions(CGSize(width: 299, height: 299), true, 2.0)
  image.draw(in: CGRect(x: 0, y: 0, width: 299, height: 299))
  let newImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        
  let attrs = [kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue, kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue] as CFDictionary
  
var pixelBuffer : CVPixelBuffer?
let status = CVPixelBufferCreate(kCFAllocatorDefault, Int(newImage.size.width), Int(newImage.size.height), kCVPixelFormatType_32ARGB, attrs, &pixelBuffer)
  guard (status == kCVReturnSuccess) else {
            return
        } 
        
  CVPixelBufferLockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))
  let pixelData = CVPixelBufferGetBaseAddress(pixelBuffer!)
        
  let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
  let context = CGContext(data: pixelData, width: Int(newImage.size.width), height: Int(newImage.size.height), bitsPerComponent: 8, bytesPerRow: CVPixelBufferGetBytesPerRow(pixelBuffer!), space: rgbColorSpace, bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue) //3
        
        context?.translateBy(x: 0, y: newImage.size.height)
        context?.scaleBy(x: 1.0, y: -1.0)
        
        UIGraphicsPushContext(context!)
        newImage.draw(in: CGRect(x: 0, y: 0, width: newImage.size.width, height: newImage.size.height))
        UIGraphicsPopContext()
        CVPixelBufferUnlockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))
        imageView.image = newImage
    }

– How to make an iOS App
ktrkathir

Remove UserNotifications in Lock screen on Swift


Generally We will remove our application delivered notifications by requestIdetifier. But In this post we are going to remove our application delivered notifications by notification category name.

This is very simple and more effective. 

/// Remove all Chat Notifications from User notification
func removeChatRichNotification() {       
   UNUserNotificationCenter.current().getDeliveredNotifications { (notifications) in
   let chatNotifications = notifications.filter({ $0.request.content.categoryIdentifier == Constants.userNotification.normalCategory.chatNotification})
            
   if chatNotifications.count > 0 {
            let chatNotificationIds = chatNotifications.map({ $0.request.identifier })
                UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: chatNotificationIds)
            }
        }
    }

– How to make an iOS App
ktrkathir

Find bike image in Swift4.1 using CoreML & Vision


In this Post Inception V3 mlModel was used to find car image
Download and Drag InceptionV3 mlModel file and Drop to Xcode project.

 

 

integrating CoreML and Vision functions and find car image

import UIKit
import CoreML
import Vision

@available(iOS 11.0, *)
class ViewController: UIViewController {
    
    @IBOutlet weak var informationLabel: UILabel!
    @IBOutlet weak var imageView: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    // MARK : - ML
    /// - Tag: MLModelSetup
    lazy var classificationRequest: VNCoreMLRequest = {
        do {
            /*
             Use the Swift class `Inceptionv3` Core ML generates from the model.
             To use a different Core ML classifier model, add it to the project
             and replace `MobileNet` with that model's generated Swift class.
             */
            let model = try VNCoreMLModel(for: Inceptionv3().model)
            
            let request = VNCoreMLRequest(model: model, completionHandler: { [weak self] request, error in
                self?.processClassifications(for: request, error: error)
            })
            request.imageCropAndScaleOption = .centerCrop
            return request
        } catch {
            fatalError("Failed to load Vision ML model: \(error)")
        }
    }()
    
    func updateclassification(for image: UIImage) {
        
        informationLabel.text = "Classifying.."
        
        let orientation = CGImagePropertyOrientation(image.imageOrientation)
        guard let ciImage = CIImage(image: image) else { fatalError("Unable to create \(CIImage.self) from \(image).") }
        
        DispatchQueue.global(qos: .userInitiated).async {
            
            let handler = VNImageRequestHandler(ciImage: ciImage, orientation: orientation, options: [:])
            
            do {
                try handler.perform([self.classificationRequest])
            } catch let error {
                print(error.localizedDescription)
            }
            
        }
    }
    
    /// Updates the UI with the results of the classification.
    /// - Tag: ProcessClassifications
    func processClassifications(for request: VNRequest, error: Error?) {
       
        DispatchQueue.main.async {
            guard let results = request.results else {
                self.informationLabel.text = "Unable to classify image.\n\(error!.localizedDescription)"
                return
            }
            
            // The `results` will always be `VNClassificationObservation`s, as specified by the Core ML model in this project.
            let classifications = results as! [VNClassificationObservation]
            
            if classifications.isEmpty {
                self.informationLabel.text = "Nothing recognized."
            } else {
                // Display top classifications ranked by confidence in the UI.
                let topClassifications = classifications.prefix(2)
                
                let identifer = topClassifications.map({$0.identifier})
                
                identifer.forEach({ (id) in
                    let iDs = id.components(separatedBy: ", ")
                    let filtered = iDs.filter({$0 == "bike"})
                    
                    if filtered.count > 0 {
                       print("This is bike")
                    }
                })
                
                let descriptions = topClassifications.map { classification in
                    // Formats the classification for display; e.g. "(0.37) cliff, drop, drop-off".
                    return String(format: "  (%.2f) %@", classification.confidence, classification.identifier)
                }
                
                self.informationLabel.text = "Classification:\n" + descriptions.joined(separator: "\n")
            }
        }
    }
    
    // MARK: - Button action
    func presentPhotoPicker(sourceType: UIImagePickerControllerSourceType) {
        let picker = UIImagePickerController()
        picker.delegate = self
        picker.sourceType = sourceType
        present(picker, animated: true)
    }
    
    @IBAction func cameraButtonClicked(_ sender: Any) {
        // Show options for the source picker only if the camera is available.
        guard UIImagePickerController.isSourceTypeAvailable(.camera) else {
            presentPhotoPicker(sourceType: .photoLibrary)
            return
        }
        self.presentPhotoPicker(sourceType: .camera)
    }
    
    @IBAction func galleryButtonClicked(_ sender: Any) {
        self.presentPhotoPicker(sourceType: .photoLibrary)
    }
    
    
}

@available(iOS 11.0, *)
extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    // MARK: - Handling Image Picker Selection
    
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String: Any]) {
        picker.dismiss(animated: true)
        
        // We always expect `imagePickerController(:didFinishPickingMediaWithInfo:)` to supply the original image.
        let image = info[UIImagePickerControllerOriginalImage] as! UIImage
        imageView.image = image
        updateclassification(for: image)
    }
}

import ImageIO

extension CGImagePropertyOrientation {
    /**
     Converts a `UIImageOrientation` to a corresponding
     `CGImagePropertyOrientation`. The cases for each
     orientation are represented by different raw values.
     
     - Tag: ConvertOrientation
     */
    init(_ orientation: UIImageOrientation) {
        switch orientation {
        case .up: self = .up
        case .upMirrored: self = .upMirrored
        case .down: self = .down
        case .downMirrored: self = .downMirrored
        case .left: self = .left
        case .leftMirrored: self = .leftMirrored
        case .right: self = .right
        case .rightMirrored: self = .rightMirrored
        }
    }
}

– How to make an iOS App
ktrkathir

How to find top visible viewcontroller on Swift


extension UIViewController {
/// Top most ViewController
func topMostViewController() -> UIViewController {
        
        if self.presentedViewController == nil {
            return self
        }
        
        if let navigation = self.presentedViewController as? UINavigationController {
            return (navigation.visibleViewController?.topMostViewController())!
        }
        /*
         if let tab = self.presentedViewController as? UITabBarController {
         if let selectedTab = tab.selectedViewController {
         return selectedTab.topMostViewController()
         }
         return tab.topMostViewController()
         }
         */
        return (self.presentedViewController?.topMostViewController())!
    }
}
extension UIApplication {
    
/// Top most ViewController
    func topMostViewController() -> UIViewController? {
        return self.keyWindow?.rootViewController?.topMostViewController()
    }
    
/// Top visible viewcontroller
    var topMostVisibleViewController : UIViewController? {
        
        if UIApplication.shared.keyWindow?.rootViewController is UINavigationController {
            return (UIApplication.shared.keyWindow?.rootViewController as! UINavigationController).visibleViewController
        }
        return nil
    }
}

Method:1

    if let visibleViewController = UIApplication.shared.topMostVisibleViewController {
// Do here
}

Method:2

  let topController = UIApplication.shared.topMostViewController()
                
                if topController is ViewController {
                    // Do here
                }

– How to make an iOS App
ktrkathir

Drag Delegate and Drop Delegate on iOS 11.0+


For understanding purpose:

struct LevelDetail {
  var unOrdered: [Int]
  var ordered : [Int]
}

Setuping Collectionview

class OrderNumberGameViewController: UIViewController {
  
  @IBOutlet weak var numbersCollectionView: UICollectionView!
  private var levelDetail: LevelDetail?

  override func viewDidLoad() {
   super.viewDidLoad()

   let limit = 50

   let orderedNumber = Array(1...limit)
   let unOrderedNumber = orderedNumber.shuffled() // Ref. Array Shuffled method in previous post

   levelDetail = LevelDetail(unOrdered: unOrderedNumber, ordered: orderedNumber)

   numbersCollectionView.dragDelegate = self
   numbersCollectionView.dropDelegate = self
   numbersCollectionView.dragInteractionEnabled = true
   numbersCollectionView.allowsMultipleSelection = true
  }
}

Implementing Drag and Drop Delegates

// MARK: - set up collectionview
extension OrderNumberGameViewController : UICollectionViewDragDelegate, UICollectionViewDropDelegate { ... }
// MARK: DragDelegate and Drop Delegate
extension OrderNumberGameViewController : UICollectionViewDragDelegate, UICollectionViewDropDelegate {

  func collectionView(_ collectionView: UICollectionView, canHandle session: UIDropSession) -> Bool {
    return true
  }

  // Single item drag
  func collectionView(_ collectionView: UICollectionView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {

    if let level = levelDetail {
      let item = level.unOrdered[indexPath.row]
      let itemProvider = NSItemProvider(object: "\(item)" as NSItemProviderWriting)

      let dragItem = UIDragItem(itemProvider: itemProvider)
      dragItem.localObject = item
      return [dragItem]
    }
    return []
}

// Multiple items drag
/* func collectionView(_ collectionView: UICollectionView, itemsForAddingTo session: UIDragSession, at indexPath: IndexPath, point: CGPoint) -> [UIDragItem] {
if let level = levelDetail {
let item = level.unOrdered[indexPath.row]
let itemProvider = NSItemProvider(object: "\(item)" as NSItemProviderWriting)

let dragItem = UIDragItem(itemProvider: itemProvider)
dragItem.localObject = item
return [dragItem]
}
return []
}
*/

func collectionView(_ collectionView: UICollectionView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UICollectionViewDropProposal {

   return UICollectionViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)

/* if session.localDragSession != nil {
if collectionView.hasActiveDrag {
return UICollectionViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
} else {
return UICollectionViewDropProposal(operation: .copy, intent: .insertAtDestinationIndexPath)
}
} else {
return UICollectionViewDropProposal(operation: .forbidden)
}
*/
}

func collectionView(_ collectionView: UICollectionView, performDropWith coordinator: UICollectionViewDropCoordinator) { // Droping performance

  let destinationIndexPath: IndexPath
  if let indexPath = coordinator.destinationIndexPath {
    destinationIndexPath = indexPath
  } else { // Get last index path of collection view.
    let section = collectionView.numberOfSections - 1
    let row = collectionView.numberOfItems(inSection: section)
    destinationIndexPath = IndexPath(row: row, section: section)
  }

  switch coordinator.proposal.operation {
  case .move: //Add the code to reorder items

/* collectionView.performBatchUpdates({
var indexPaths = [IndexPath]()
for (index, item) in coordinator.items.enumerated() {
//Destination index path for each item is calculated separately using the destinationIndexPath fetched from the coordinator
let indexPath = IndexPath(row: destinationIndexPath.row + index, section: destinationIndexPath.section)

if levelDetail != nil {
self.levelDetail?.unOrdered.insert(item.dragItem.localObject as! Int, at: indexPath.row)
}
indexPaths.append(indexPath)
}
collectionView.insertItems(at: indexPaths)
})
*/

  let items = coordinator.items
  if items.count == 1, let item = items.first, let sourceIndexPath = item.sourceIndexPath {
  var dIndexPath = destinationIndexPath
  if dIndexPath.row >= collectionView.numberOfItems(inSection: 0) {
  dIndexPath.row = collectionView.numberOfItems(inSection: 0) - 1
 }

 collectionView.performBatchUpdates({

  if levelDetail != nil {
  self.levelDetail?.unOrdered.remove(at: sourceIndexPath.row)
  self.levelDetail?.unOrdered.insert(item.dragItem.localObject as! Int, at: dIndexPath.row)
  collectionView.deleteItems(at: [sourceIndexPath])
  collectionView.insertItems(at: [dIndexPath])
  }

 })
 
  coordinator.drop(item.dragItem, toItemAt: dIndexPath)
 }
 case .copy: //Add the code to copy items
 return
 default:
 return
 }
 }
}

– How to make an iOS App
ktrkathir