Contents
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:
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.
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.
Cảm ơn bạn đã đọc bài viết này!
Related Posts:
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
Fan page
Tags
Recent Posts
- Charles Proxy – Phần 1 : Giới thiệu, cài đặt và cấu hình
- Complete Concurrency với Swift 6
- 300 Bài code thiếu nhi bằng Python – Ebook
- Builder Pattern trong 10 phút
- Observer Pattern trong 10 phút
- Memento Pattern trong 10 phút
- Strategy Pattern trong 10 phút
- Automatic Reference Counting (ARC) trong 10 phút
- Autoresizing Masks trong 10 phút
- Regular Expression (Regex) trong Swift
You may also like:
Archives
- September 2024 (1)
- July 2024 (1)
- June 2024 (1)
- May 2024 (4)
- April 2024 (2)
- March 2024 (5)
- January 2024 (4)
- 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)