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 1, 2021

Updating UI – SwiftUI Notes #3

SwiftUI

Contents

  • Chuẩn bị
  • 1. Display Data
  • 2. Action
  • 3. Updating UI
  • Tạm kết

Chào bạn đến với Fx Studio. Chúng ta lại tiếp tục hành trình với series SwiftUI Notes. Trong bài viết trước, chúng ta học cách tạo được giao diện. Và tiếp nối bài viết này, chúng ta lại học cách đưa dữ liệu lên giao diện và cập nhật lại dữ liệu. Chủ đề bài viết là Updating UI.

Bài này sẽ tiếp nối bài trước và bạn có thể đọc bài viết đó tại link sau:

    • Creating your UI

Nếu mọi thứ đã ổn rồi, thì …

Bắt đầu thôi!

Chuẩn bị

Về mặt cấu hình và phiên bản sử dụng thì như sau:

    • Xcode 12
    • Swift 5.3
    • SwiftUI 2.0
    • MacOS 10.15.x

Về demo bài viết thì chúng ta sử dụng tiếp project ở bài trước. Bạn có thể checkout code tại đây:

    • Toàn bộ repo: https://github.com/fx-studio/swiftui-notes
    • Project bài trước: https://github.com/fx-studio/swiftui-notes/tree/main/002-CreatingUI

Tuy nhiên, bạn làm việc SwiftUI thì sẽ không cần phải sử dụng lại nguyên một Project. Bạn chỉ cần copy code của mỗi View nào cần thiết mà thôi. Và bạn có thể sử dụng SwiftUI với Playground, tham khảo tại đây.

Và bạn có thể tham khảo lại code của ContentView sẽ sử dụng trong demo lần này như sau:

struct ContentView: View {
    var body: some View {
        VStack(alignment: .center) {
            Button(action: {
                print("^")
            }) {
                Image(systemName: "arrowtriangle.up.fill")
                    .resizable()
                    .frame(width: 50.0, height: 50.0)
                    .foregroundColor(.red)
            }
            .frame(width: 50.0, height: 50.0)
            Text("0")
                .font(.title)
                .fontWeight(.bold)
                .foregroundColor(Color.blue)
                .multilineTextAlignment(.center)
            Button(action: {
                print("v")
            }) {
                Image(systemName: "arrowtriangle.down.fill")
                    .resizable()
                    .frame(width: 50.0, height: 50.0)
            }
            .frame(width: 50.0, height: 50.0)
        }
        .frame(width: 50.0, height: 200.0)
            
    }
}

Giao diện của ContentView như hình dưới.

Updating UI - SwiftUI

1. Display Data

Mặc dù là SwiftUI có khác nhiều so với UIKit. Nhưng chúng nó đều phải có những nhiệm vụ chung cần phải được giải quyết. Các nhiệm vụ này lại thuộc về phạm trù bản chất của lập trình mobile rồi.

Bắt đầu, chính là nhiệm vụ hiển thị dữ liệu lên giao diện. Bạn cũng biết là không thể nào hard code hết tất cả. Chúng ta sẽ tạo biến lưu trữ dữ liệu. Và đưa giá trị đó lên view của SwiftUI.

Bắt đầu, bạn hãy khai báo thêm một thuộc tính cho ContentView như sau:

var number: Int = 10

Mục tiêu chính là đem giá trị của number vào Text. Tiếp theo, bạn chỉnh sửa lại một chút code cho Text của ContentView lại.

Text("\(number)")
                        .font(.title)
                        .fontWeight(.bold)
                        .foregroundColor(Color.blue)
                        .multilineTextAlignment(.center)

Bạn sẽ thấy biến number được gián vào String làm đối số ban đầu cho việc khởi tạo Text. Và chưa đây 1 phút, giao diện của bạn cập nhật lại. Nếu chờ lâu quá, bạn hãy bấm resume hoặc try again nha. EZ Game!

2. Action

Nhiệm vụ thứ 2 của View cần đảm nhận, đó là nhận sự kiện từ người dùng. Trong giao diện đơn giản trên, ta có 2 Button. Chúng nó sẽ nhận nhiệm vụ đón nhận sự kiện người dùng.  Cho dễ hình dung thì bạn xem lại code của Button.

Button(action: {
                        // code here
                    }) {
                        Image(systemName: "arrowtriangle.up.fill")
                            .resizable()
                            .frame(width: 50.0, height: 50.0)
                            .foregroundColor(.red)
                    }

Trong đó,

  • action là tham số với yêu cầu là 1 closure.
  • Mọi thứ bạn cần phải làm vào đó mà quẩy.
  • Bạn hãy thử tăng number lên 1 đơn vị.
Button(action: {
                        number += 1
                    }) {
                        Image(systemName: "arrowtriangle.up.fill")
                            .resizable()
                            .frame(width: 50.0, height: 50.0)
                            .foregroundColor(.red)
                    }

Và đời không như là mơ. Bây giờ, bạn sẽ nhận được báo lỗi từ Xcode như sau:

Left side of mutating operator isn’t mutable: ‘self’ is immutable.

Căng nhĩ!

3. Updating UI

Cuối cùng, ta sẽ giải quyết lỗi ở trên. Bạn cũng biết nguyên nhân chính là từ khai báo ban đầu của ContentView.

struct ContentView: View { }

Nó là struct chứ không phải là class. Do đó, việc thay đổi giá trị của thuộc tính là không thể được. Để khắc phục điều này thì SwiftUI đã cho ta 1 keyword. Nó là:

@State

Ta chỉnh sửa lại khai báo number như sau:

@State var number: Int = 10

Ta sẽ thêm từ khoá @State trước khi khai báo thuộc tính.

  • Điều này đồng nghĩa ta sẽ uỷ thác cho SwiftUI lưu trữ giá trị biến đó trong bộ nhớ, chừng nào View đó còn tồn tại thì giá trị còn tồn tại.
  • Khi State có sự thay đổi, SwiftUI sẽ tự động hiểu để cập nhật lại View tương ứng với trạng thái mới nhất của dữ liệu.

Về @State thì sẽ có một bài viết riêng về nó.

Và cũng chưa đây 1 phút thì SwiftUI đã cập nhật. Bạn hãy bấm vào Live Preview, sau đó nhấn vào Button để cảm nhận kết quả có sự thay đổi hay không nha. Ahihi!

Bạn tiếp tục cập nhật thêm cho Button giảm giá trị. Code cuối cùng sẽ trông như thế này.

struct ContentView: View {
    
    @State var number: Int = 10
    
    var body: some View {
        VStack(alignment: .center) {
                    Button(action: {
                        number += 1
                    }) {
                        Image(systemName: "arrowtriangle.up.fill")
                            .resizable()
                            .frame(width: 50.0, height: 50.0)
                            .foregroundColor(.red)
                    }
                    .frame(width: 50.0, height: 50.0)
                    Text("\(number)")
                        .font(.title)
                        .fontWeight(.bold)
                        .foregroundColor(Color.blue)
                        .multilineTextAlignment(.center)
                    Button(action: {
                        number -= 1
                    }) {
                        Image(systemName: "arrowtriangle.down.fill")
                            .resizable()
                            .frame(width: 50.0, height: 50.0)
                    }
                    .frame(width: 50.0, height: 50.0)
                }
                .frame(width: 50.0, height: 200.0)
    }
}

 

Tạm kết

Bạn sẽ nhận ra sự khác nhau cơ bản của giữa SwiftUI & UIKit trong vấn đề Updating UI.

  • Với UIKit, sau khi thay đổi giá trị của thuộc tính. Bạn phải cập nhật lại giá trị thuộc tính của View trong giao diện. Bạn cần 2 bước để thực hiện việc này.
  • Với SwiftUI, mọi thứ sẽ được tự động. Bạn chỉ cần thay đổi giá trị của thuộc tính. Và giao diện sẽ tự động render lại với giá trị mới đó. Bạn cần 1 bước thôi.

 

Okay! Tới đây, mình xin kết thúc bài viết này. Và nếu có gì thắc mắc hay góp ý cho mình thì bạn có thể để lại bình luận hoặc gởi email theo trang Contact.

  • Bạn có thể checkout code tại đây.
  • Bạn theo dõi tiếp bài viết tiếp theo tại đây!

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

FacebookTweetPinYummlyLinkedInPrintEmailShares26

Related Posts:

  • Basic Environment values - SwiftUI Notes #9
    Basic Environment values - SwiftUI Notes #9
  • Presenting an Alert - SwiftUI Notes #4
    Presenting an Alert - SwiftUI Notes #4
  • SwiftUI App Life Cycle - SwiftUI Notes #6
    SwiftUI App Life Cycle - SwiftUI Notes #6
  • Declarative app development - SwiftUI Notes #7
    Declarative app development - SwiftUI Notes #7
Tags: SwiftUI, SwiftUI Notes
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
  • Tích hợp UIViewController (UIKit) vào SwiftUI Project -…
    Tích hợp UIViewController (UIKit) vào SwiftUI Project - SwiftUI Notes #14
  • Basic Environment values - SwiftUI Notes #9
    Basic Environment values - SwiftUI Notes #9
  • Declaring View - SwiftUI Notes #8
    Declaring View - SwiftUI Notes #8
  • SwiftUI App Life Cycle - SwiftUI Notes #6
    SwiftUI App Life Cycle - SwiftUI Notes #6

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!