Giter Site home page Giter Site logo

devpolant / swiftycomponents Goto Github PK

View Code? Open in Web Editor NEW
3.0 1.0 1.0 120 KB

A collection of useful Swift extensions and code utilities

License: MIT License

Objective-C 0.26% Swift 99.69% Ruby 0.05%
ios swift xcode swift-extensions extensions code-utilities uikit view-model

swiftycomponents's Introduction

Components

Swift Xcode MIT

This repository will contain some useful iOS code utils and extensions.

Requirements:

  • iOS 9.0+
  • Xcode 9.0+
  • Swift 4.0+

UI Layer

1. Work with UITableView & UICollectionView - one possible approach, inspired by CocoaHeads:

You can move configuration logic for UITableViewCell or UICollectionViewCell from -cellForRowAtIndexPath: to separate types.

First, you need to create cell class and appropriate type that conforms to CellViewModel type:

public typealias AnyViewCell = UIView

public protocol CellViewModel: AnyCellViewModel {
    associatedtype Cell: AnyViewCell
    func setup(cell: Cell)
}

UserTableViewCell.swift

// MARK: - View Model

struct UserCellModel: CellViewModel {
    var user: User
    
    func setup(cell: UserTableViewCell) {
        cell.nameLabel.text = user.name
    }
}

// MARK: - Cell

final class UserTableViewCell: UITableViewCell {
    @IBOutlet weak var nameLabel: UILabel!
}

After that you need to register created model type:

tableView.register(nibModel: UserCellModel.self)

Then store your models in array (or your custom datasource type):

private var users: [AnyCellViewModel] = []

AnyCellViewModel is a base protocol of CellViewModel. It's needed only in order to fix compiler limitation as you can use protocols with associatedtype only as generic constraints and can't write something like this:

private var users: [CellViewModel] = [] // won't compile

UITableViewDataSource implementation is very easy, even if you have multiple cell types, because all logic are contained in our view models:

class ViewController: UIViewController {
    
    @IBOutlet weak var tableView: UITableView!
    
    private var users: [AnyCellViewModel] = []

    override func viewDidLoad() {
        super.viewDidLoad()
        users = User.testDataSource.map { UserCellModel(user: $0) }
        tableView.register(nibModel: UserCellModel.self)
    }
}

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return users.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        return tableView.dequeueReusableCell(withModel: tableModel(at: indexPath), for: indexPath)
    }
    
    private func tableModel(at indexPath: IndexPath) -> AnyCellViewModel {
        return users[indexPath.row]
    }
}

See implementation details in Sources folder.

2. Keyboard Handling

Conform your view controller to KeyboardInteracting protocol:

public typealias KeyboardInputView = UIView & UITextInput

public protocol KeyboardInteracting: class {
    var scrollView: UIScrollView! { get }
    var keyboardInputViews: [KeyboardInputView] { get }
    
    func handleKeyboardShow(userInfo: [AnyHashable: Any])
    func handleKeyboardHide()
}

extension KeyboardInteracting where Self: UIViewController {

    func handleKeyboardShow(userInfo: [AnyHashable: Any]) {
        /// ...
    }

    func handleKeyboardHide() {
        // ...
    }
}

KeyboardInteracting.swift

Register and unregister for keyboard notifications:

extension UIViewController {
    public func registerForKeyboardNotifications() {
        let center = NotificationCenter.default
        center.addObserver(self, selector: #selector(keyboardDidShow(notification:)), name: .UIKeyboardDidShow, object: nil)
        center.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: .UIKeyboardWillHide, object: nil)
    }
    
    public func unregisterForKeyboardNotifications() {
        let center = NotificationCenter.default
        center.removeObserver(self, name: .UIKeyboardDidShow, object: nil)
        center.removeObserver(self, name: .UIKeyboardWillHide, object: nil)
    }
    
    @objc private func keyboardDidShow(notification: Notification) {
        guard let userInfo = notification.userInfo else { return }
        (self as? KeyboardInteracting)?.handleKeyboardShow(userInfo: userInfo)
    }
    
    @objc private func keyboardWillHide(notification: Notification) {
        (self as? KeyboardInteracting)?.handleKeyboardHide()
    }
}

And handle UIViewController life cycle:

class ViewController: UIViewController, KeyboardInteracting {
    var scrollView: UIScrollView!
    
    var keyboardInputViews: [KeyboardInputView] {
        // return an array of your input views
        return [] 
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        registerForKeyboardNotifications()
    }
    
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        unregisterForKeyboardNotifications()
    }
    
    // ...
}

Extensions

1. Bundle

extension Bundle {
    public var bundleIdentifier: String {
        return object(forInfoDictionaryKey: kCFBundleIdentifierKey as String) as! String
    }
    
    /// Project bundle name
    public var bundleName: String {
        return object(forInfoDictionaryKey: kCFBundleNameKey as String) as! String
    }
    
    /// App name which displaying in Springboard
    public var displayName: String {
        let displayName = object(forInfoDictionaryKey: "CFBundleDisplayName") as? String
        return displayName ?? self.bundleName
    }
    
    public var buildVersion: String? {
        return object(forInfoDictionaryKey: kCFBundleVersionKey as String) as? String
    }
}

License

Repository is created under the MIT license. See LICENSE for details.

swiftycomponents's People

Contributors

devpolant avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar

Forkers

multinerd-forks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.