Skip to content
  • Home
  • Code
  • iOS & Swift
  • Combine
  • RxSwift
  • SwiftUI
  • Flutter & Dart
  • Tutorials
  • Art
  • Blog
Fx Studio
  • Home
  • Code
  • iOS & Swift
  • Combine
  • RxSwift
  • SwiftUI
  • Flutter & Dart
  • Tutorials
  • Art
  • Blog
Written by chuotfx on March 9, 2020

Combine vs. UIKit – Logic

Combine

Contents

  • Chuẩn bị
  • 1. Cập nhật dữ liệu
  • 2. Xử lý dữ liệu nhận được
  • 3. Kiểm tra điều kiện
  • Tạm kết

Chào bạn đến với Fx Studio,

Chúng ta lại tiếp tục với series dài của Combine và phần Combine vs. UIKit. Phần này sẽ là việc xử lý logic của các thành phần trong ViewController. Áp dụng các Operators vào cho việc xử lý.

Bắt đầu thôi!

Chuẩn bị

  • Xcode 11.0
  • Swift 5.1
  • iOS 13.0

Project code demo thì sử dụng lại project trong bài Combine vs. UIKit – Navigation. Chúng ta sẽ cài đặt thêm các function để xử lý các tính tăng mới.

1. Cập nhật dữ liệu

Chúng ta reset lại function gotoSettingsVC từ HomeViewController nha.

  @objc func gotoSettingsVC() {
    // vc
    let settingsVC = SettingsViewController()

   // push
    self.navigationController?.pushViewController(settingsVC, animated: true)
  }

Chúng ta sẽ cài đặt việc update title của màn hình Settings, mỗi lần nhập dữ liệu. Trước tiên cần phải tạo nơi lưu trữ các subscriptions trong Settings trước.

  • Thêm property này vào trong class SettingsViewController
var subscriptions = Set<AnyCancellable>()
  • Update lại function viewDidLoad
    • Tiến hành subscribe biến count
    • Sử dụng map để biến đổi dữ liệu nhận được từ Int thành String
    • assig dữ liệu nhận được trực tiếp lên thuộc tính title của ViewController
 override func viewDidLoad() {
    super.viewDidLoad()
    
    // update UI
    // title
    $count
      .map { "\($0)" }
      .assign(to: \.title, on: self)
      .store(in: &subscriptions)
    
    // textfield
    countTexyField.text = "\(count)"
    
  }

Bạn build project và test lại. Title sẽ được liên tục update dựa theo giá trị của count.

2. Xử lý dữ liệu nhận được

Tuy nhiên, chúng ta mới hoàn thành một nữa công việc. Còn việc lấy sự kiện từ UITextField để cật nhật lại dữ liệu cho biến count

Giải quyết bài toán này chúng ta sẽ tạo ra 1 Publisher cho UITextField để nhận các sự kiện phát ra từ nó. Tạo một file mới có tên là UITextField.Publisher.swift

import Foundation
import UIKit
import Combine

extension UITextField {
  var publisher: AnyPublisher<String?, Never> {
    NotificationCenter.default
      .publisher(for: UITextField.textDidChangeNotification, object: self)
      .compactMap { $0.object as? UITextField? }
      .map { $0?.text }
      .eraseToAnyPublisher()
  }
}
  • Viết extension cho UITextField.
  • Khai báo thêm 1 compute property là publisher với Output là String và Failure là Never
  • Sử dụng publisher của  NotificationCenter.default nhằm bắt sự kiện notification textDidChangeNotification
  • compactMap để xác định đúng TextField sau khi ép kiểu, tránh các trường hợp nil
  • map để biến dữ liệu nhận được thành String
  • eraseToAnyPublisher để xoá dấu vết để lại

Bây giờ chúng ta sang phần chính. Thêm đoạn code sau vào function viewDidLoad của SettingsViewController.

countTexyField.publisher
      .sink { value in
        guard let value = value, let temp = Int(value) else {
          return
        }
        
        self.count = temp
        
    }.store(in: &subscriptions)

Giải thích:

  • Subscribe thuộc tính publisher của UITextField chúng ta vừa mới tạo ra.
  • sink để subscription nó
  • Thực hiện việc biến đổi String? thành Int và gán dữ liệu cho count
  • Lưu trữ lại subscription

Tiến hành build ứng dụng và test hoạt động đã đúng yêu cầu hay chưa.

Tiện tay update lại function gotoSettingsVC ở HomeViewController. Khi các dữ liệu đã ổn định rồi và bạn không cần lo lắng gì tới biến count .

  @objc func gotoSettingsVC() {
    // vc
    let settingsVC = SettingsViewController()

    settingsVC.$count
      .sink { value in
        self.countPublisher.value = value
    }.store(in: &subscriptions)
    
    // push
    self.navigationController?.pushViewController(settingsVC, animated: true)
  }

3. Kiểm tra điều kiện

Chuyển sang phần mà chắc nhiều bạn sẽ quan tâm. Nếu trường hợp TextField của chúng ta với dữ liệu nhập chưa đúng yêu cầu. Thì đi kèm với đó là các UI Control liên quan sẽ không hoạt động. Nhằm loại bỏ đi 1 cơ số bugs có thể phát sinh do việc handle điều kiện trong ứng dụng.

Quay về ví dụ của chúng ta, nếu như dữ liệu của TextField chúng ta à số và không âm. Thì Button DONE mới hoạt động được. Ta tiến hành cài đặt như sau:

Mở file SettingsViewController và thêm thuộc tính sau:

 var validated : AnyPublisher<Bool, Never> {
    return Publishers.Map(upstream: $count) { $0 >= 0 }.eraseToAnyPublisher()
  }

Nó giúp việc luôn kiểm tra trên stream count. Và só sánh điều kiện >= 0 để quyết định trả về trạng thái kích hoạt cho Button DONE. Tiếp tục, thêm đoạn code sau vào function viewDidLoad:

    validated
      .assign(to: \.isEnabled, on: doneButton)
      .store(in: &subscriptions)

Vì vadidated có Output là Bool. Và nó luôn cập nhật theo giá trị của luồng count. Vì vậy, chúng ta có thể assign trực tiếp tới thuộc tính isEnabled của doneButton.

Build và test kiểm tra lại sự hoạt động của ViewController. Ngoài ra, để thêm hiệu ứng đẹp cho ứng dụng, thì bạn có thể tuỳ chỉnh giao diện của nút DONE theo isEnabled. Và bạn có thể áp dụng thêm một số toán tử như combineLatest để kiểm tra một lúc nhiều TextField.

 

OKAY. Tới đây, mình xin kết thúc bài viết này và bạn có thể download code demo tại đây.

Tạm kết

  • Sử dụng các Operator để biến đổi dữ liệu phù hợp với các UI Control
  • Extension để thêm các Publisher cho UI Control
  • Kiểm tra kết hợp nhiều điều kiện theo Combine code
  • Điều kiển các UI Control dựa theo các điều kiện

Cảm ơn bạn đã đọc bài viết này!

 

FacebookTweetPinYummlyLinkedInPrintEmailShares14

Related Posts:

  • RxCocoa Basic – Extend UIKit
    RxCocoa Basic – Extend UIKit
  • Tích hợp UIViewController (UIKit) vào SwiftUI Project - SwiftUI Notes #14
    Tích hợp UIViewController (UIKit) vào SwiftUI Project -…
  • RxSwift vs. UIKit - Hello ViewController
    RxSwift vs. UIKit - Hello ViewController
  • RxSwift vs. UIKit – Tạo Model với Custom Observable
    RxSwift vs. UIKit – Tạo Model với Custom Observable
Tags: combine
Written by chuotfx

Hãy ngồi xuống, uống miếng bánh và ăn miếng trà. Chúng ta cùng nhau đàm đạo về đời, về code nhóe!

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Donate – Buy me a coffee!

Fan page

Fx Studio

Tags

Actor Advanced Swift api AppDistribution Asynchronous autolayout basic ios tutorial blog callback ci/cd closure collectionview combine concurrency CoreData Core Location crashlytics darkmode dart dart basic dart tour Declarative decoding delegate deploy fabric fastlane firebase flavor flutter GCD iOS mapview MVVM optional protocol rxswift Swift Swift 5.5 SwiftUI SwiftUI Notes tableview testing TravisCI unittest

Recent Posts

  • Raw String trong 10 phút
  • Dispatch Semaphore trong 10 phút
  • Tổng kết năm 2022
  • KeyPath trong 10 phút – Swift
  • Make color App Flutter
  • Ứng dụng Flutter đầu tiên
  • Cài đặt Flutter SDK & Hello world
  • Coding Conventions – người hùng hay kẻ tội đồ?
  • Giới thiệu về Flutter
  • Tìm hiểu về ngôn ngữ lập trình Dart

You may also like:

  • Tích hợp SwiftUI vào UIKit Project - SwiftUI Notes #13
    Tích hợp SwiftUI vào UIKit Project - SwiftUI Notes #13
  • RxSwift vs. UIKit - Fetching Data from API
    RxSwift vs. UIKit - Fetching Data from API
  • RxSwift vs. UIKit - Hello ViewController
    RxSwift vs. UIKit - Hello ViewController
  • RxSwift vs. UIKit – Working with Cache Data
    RxSwift vs. UIKit – Working with Cache Data
  • Tích hợp UIViewController (UIKit) vào SwiftUI Project -…
    Tích hợp UIViewController (UIKit) vào SwiftUI Project - SwiftUI Notes #14

Archives

  • February 2023 (1)
  • January 2023 (2)
  • November 2022 (2)
  • October 2022 (1)
  • September 2022 (5)
  • August 2022 (6)
  • July 2022 (7)
  • June 2022 (8)
  • May 2022 (5)
  • April 2022 (1)
  • March 2022 (3)
  • February 2022 (5)
  • January 2022 (4)
  • December 2021 (6)
  • November 2021 (8)
  • October 2021 (8)
  • September 2021 (8)
  • August 2021 (8)
  • July 2021 (9)
  • June 2021 (8)
  • May 2021 (7)
  • April 2021 (11)
  • March 2021 (12)
  • February 2021 (3)
  • January 2021 (3)
  • December 2020 (3)
  • November 2020 (9)
  • October 2020 (7)
  • September 2020 (17)
  • August 2020 (1)
  • July 2020 (3)
  • June 2020 (1)
  • May 2020 (2)
  • April 2020 (3)
  • March 2020 (20)
  • February 2020 (5)
  • January 2020 (2)
  • December 2019 (12)
  • November 2019 (12)
  • October 2019 (19)
  • September 2019 (17)
  • August 2019 (10)

About me

Education, Mini Game, Digital Art & Life of coders
Contacts:
contacts@fxstudio.dev

Fx Studio

  • Home
  • About me
  • Contact us
  • Mail
  • Privacy Policy
  • Donate
  • Sitemap

Categories

  • Art (1)
  • Blog (22)
  • Code (4)
  • Combine (22)
  • Flutter & Dart (24)
  • iOS & Swift (86)
  • RxSwift (37)
  • SwiftUI (76)
  • Tutorials (70)

Newsletter

Stay up to date with our latest news and posts.
Loading

    Copyright © 2023 Fx Studio - All rights reserved.

    Share this ArticleLike this article? Email it to a friend!

    Email sent!