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 February 8, 2022

UserDefaults trong 10 phút

iOS & Swift . Tutorials

Contents

  • Chuẩn bị
  • UserDefaults
  • Sử dụng
  • Synchronize
  • Lưu dữ liệu
  • Đọc dữ liệu
  • Default value
  • Custom Objects
    • Ghi dữ liệu
    • Đọc dữ liệu
  • register(defaults:)
  • Tạm kết

Chào mừng bạn đến với Fx Studio. Chúng ta sẽ cùng nhau tìm hiểu về chủ đề khá là cơ bản trong Swift & iOS. Đó là UserDefaults. Đây là cách đầu tiên mà bạn sẽ dùng lưu trữ dữ liệu trong ứng dụng iOS của bạn.

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

Bắt đầu thôi!

Chuẩn bị

UserDefaults là một trong những thành phần cơ bản đầu tiên có trong nền tảng iOS. Nên về mặt công cụ sử dụng, thì hầu như tất cả các phiên bản của Xcode & Swift đều hỗ trợ nó. Nên bạn sẽ an tâm về mặt này.

Về mặt kiến thức, UserDefaults là một trong những khái niệm cơ bản. Do đó, bạn chỉ cần biết ít nhiều về Swift là đủ rồi. Còn nếu bạn chưa biết về Swift thì có thể tham khảo link sau đây.

    • Basic Swift trong 10 phút

Nếu bạn hứng thú với iOS thì có thể tiếp tục series Lập trình iOS cho mọi người ngay sau khi đọc xong bài viết này.

UserDefaults

UserDefaults được sử dụng để lưu trữ các phần nhỏ dữ liệu tồn tại trong suốt quá trình ứng dụng hoạt động. Ngay cả khi ứng dụng bị bắt đi và bạn vẫn lấy được giá trị cuối cùng khi sử dụng lại ứng dụng. Việc sử dụng UserDefaults được xem là khá phổ biến trong giới lập trình iOS.

Kiểu dữ liệu được sử dụng cho việc lưu trữ sẽ là các kiểu dữ liệu cơ bản và đơn giản. Ví dụ như: String, Int, Float …. Ngoài ra, bạn vẫn có thể lưu trữ các kiểu dữ liệu custom (như: class, struct, dictionary, array …)

Mỗi dữ liệu khi lưu trữ sẽ bao gồm một cặp key và value. Trong đó:

  • key sẽ luôn là kiểu dữ liệu String
  • value sẽ là giá trị mà bạn muốn lưu trữ và nó có thể cấp nhập các kiểu dữ liệu cơ bản (như đã nói ở trên).

Nó sẽ lưu trữ các giá trị dữ liệu vào file *.plist trong bộ nhớ của ứng dụng trên thiết bị. Khi ứng dụng bạn khởi chạy, thì nó sẽ được khôi phục và tiếp tục sử dụng trong suốt quá trình ứng dụng hoạt động.

Tóm lại, bạn không cần quan tâm về cơ chế hay bản chất của nó.

Về mặt ý nghĩa, UserDefaults sẽ dùng lưu trữ các settings người dùng từ phía local. Và không có nhu cầu đồng bộ dữ liệu đó lên server hay các thiết bị khác. Ngoài ra, tính bảo mật của nó khá kém, nên bạn cũng cần phải chú ý khi muốn lưu trữ các loại dữ liệu nhạy cảm.

Sử dụng

Chúng ta sẽ đi vào cách sử dụng cơ bản nhất của UserDefaults trước nhóe.

  • Chúng ta cần sử dụng một đối tượng của UserDefaults, hoặc bạn có thể lấy ngay đối tượng mà hệ thông cung cấp.
let userdefault = UserDefaults.standard
  • Đọc một giá trị với một key cho trước
let userdefault = UserDefaults.standard
print(userdefault.string(forKey: "hello") ?? "n/a")
  • Lưu giá trị với một key
let userdefault = UserDefaults.standard
userdefault.set("Hello", forKey: "hello")

Nhìn qua, bạn cũng hình dung cách phương thức cần sử dụng để thực hiện 2 công việc cơ bản rồi đó. Chúng sẽ dùng:

  • set để lưu trữ dữ liệu với key
  • string, int … hoặc object để lấy giá trị mà bạn đã lưu với key cho trước

EZ Game!

Synchronize

Nếu bạn là một dev iOS lâu năm. Hoặc đôi lúc bạn vô tình bắt gặp phương thức synchronize() , thì bây giờ nó:

Không còn cần thiết nữa!

Trước đây, nó dùng để đồng bộ dữ liệu và để bạn có thể sử dụng lại dữ liệu lưu trữ mới mất. Khi bạn mở ứng dụng thì dữ liệu sẽ được khôi phục.

Tuy nhiên, Swift đã tiến hóa và bạn không cần dùng tới function này nữa. Dữ liệu của bạn luôn luôn được đảm bảo lưu trữ và phục hồi mới nhất.

Và nếu bạn vẫn còn sử dụng nó trong code của bạn, thì đôi khi đem lại tác dụng phụ không mong muốn. Đó là …

Làm chậm ứng dụng.

Lưu dữ liệu

Để lưu dữ liệu vào UserDefaults, bạn sẽ sử dụng phương thức set(_:forKey:) của chính đối tượng UserDefaults.

  • Kiểu dữ liệu lưu trự sẽ dựa vào giá trị mà bạn cung cấp
  • key sẽ là do bạn đặt và nó có kiểu là String

Bạn có thể tham khảo các ví dự sau:

//Int
defaults.set(22, forKey: "userAge")

//Bool
var darkModeEnabled = true
defaults.set(darkModeEnabled, forKey: "darkModeEnabled")

//Array
let fruits = ["Apple", "Banana", "Mango"]
defaults.set(fruits, forKey: "favoriteFruits")

//Dictionary
let toggleStates = ["WiFi": true, "Bluetooth": false, "Cellular": true]
defaults.set(toggleStates, forKey: "toggleStates")

//....

Cũng kha khá kiểu dữ liệu mà bạn có thể lưu trữ rồi đó.

Đọc dữ liệu

Công việc tiếp theo là bạn đọc lại các dữ liệu đã được lưu. Cần phải xác định 2 điều:

  • Kiểu dữ liệu mà bạn muốn đọc
  • key của dữ liệu mà bạn đã lưu trữ

Ta sẽ xem qua ví dụ đọc dữ liệu với các giá trị đã lưu ở ví dụ trên nhóe.

let userAge = defaults.integer(forKey: "userAge")

let darkModeEnabled = defaults.bool(forKey: "darkModeEnabled")

let favoriteFruits = defaults.array(forKey: "favoriteFruits”)

let toggleStates = defaults.dictionary(forKey: "toggleStates")

UserDefaults sẽ cung cấp cho bạn đầy đủ các kiểu dữ liệu cơ bản theo từng phương thức phù hợp. Một số kiểu sẽ có giá trị trả về là Optional, ví dụ như String, Array, Dictionary … 

Cuối cùng, nếu bạn không biết chính xác là kiểu gì, thì hãy sử dụng phương thức object(forKey) với kiểu AnyObject? trả về. Sau đó, bạn tiến hành ép kiểu cho phù hợp.

Default value

Điều gì sẽ xảy ra nếu không có dữ liệu liên kết với key?

Với phương thức get thì bạn sẽ nhận lại một giá trị mặc định, khi chúng không tồn tại hoặc không liên kết với key nào cả. Ví dụ như integer(forKey) sẽ trả về là 0 nhóe.

print(userdefault.integer(forKey: "total"))    //0

Với các kiểu dữ liệu như là String, Array, Dictionary … thì bạn sẽ nhận được phiên bản Optional của chúng. Và khi rơi vào trường hợp trên, thì chúng sẽ trả về là nil.

Điều này nó tạo ra sự không nhất quán trong logic code của bạn. Chắc chắn bạn sẽ gặp khá nhiều bugs cơ bản với chúng.

Không tồn tại hay không có giá trị

Để thống nhất, bạn nên sử dụng phương thức object(forKey) cho tất cả các giá trị mà bạn muốn lấy. Và nó sẽ trả về một Optional. Khi giá trị chưa liên kết với key thì bạn sẽ nhận được là nil. Công việc cuối cùng, bạn sẽ ép kiểu về kiểu mà bạn muốn sử dụng. Ví dụ nhóe!

let favoriteFruits = defaults.object(forKey: "favoriteFruits") as? [String] ?? [String]()

Trong quá trình ép kiểu, nếu chúng là nil thì bạn có thể cung cấp một giá trị mặc định ban đầu để sử dụng. Vừa giải quyết bài toán tồn tại và vừa giá trị mặc định. EZ Game!

Custom Objects

Độ khó logic code của bạn sẽ tăng thêm. Và việc lưu trữ các đối tượng với kiểu dữ liệu Custom, như là: class, struct ... là điều hiển nhiên. Nhất là khi bạn có quá nhiều thuộc tính (properties) cần phải lưu trữ.

Tất nhiên, bạn cần phải có kiểu dữ liệu phù hợp cho việc lưu trữ. Với các class hay struct thì cần phải tuân thủ Codable Protocol. Nó sẽ giúp dữ liệu của bạn có thể chuyển đổi định dạng một cách tự động và nhanh chóng. Xem ví dụ với struct User sau nhóe!

struct User: Codable {
    let name: String
    let age: Int
}

Ghi dữ liệu

Vì bạn đã khai báo kiểu dữ liệu của bạn tuân thủ với Codable Protocol rồi. Nên chúng ta sẽ chuyển đổi đối tượng đó thành Data. Sau đó, chúng ta sẽ lưu chúng vào UserDefaults dưới dạng một object với key xác định.

Ví dụ nhóe!

let userdefault = UserDefaults.standard
let user = User(name: "chuotfx", age: 22)

let encoder = JSONEncoder()
if let encodedUser = try? encoder.encode(user) {
    userdefault.set(encodedUser, forKey: "user")
}

Trong đó:

  • JSONEncoder để tiến hành mã hóa đối tượng thành Data
  • set(_:forKey) để tiến hành lưu trữ

Đọc dữ liệu

Công việc đọc dữ liệu, thì tiến hành ngược lại với công việc ghi.

  • Đọc dữ liệu với kiểu là Data từ UserDefaults
  • Tiến hành giải mã đối tượng với JSONDecoder

Xem tiếp ví dụ nhóe!

if let savedUserData = userdefault.object(forKey: "user") as? Data {
    let decoder = JSONDecoder()
    if let savedUser = try? decoder.decode(User.self, from: savedUserData) {
        print("Saved user: \(savedUser)")
    }
}

register(defaults:)

Sau khi bạn đã am hiểu hết cơ bản về UserDefaults rồi. Thì chúng ta tiến tới với cách tiếp cận đúng đắng hơn khi bạn sử dụng UserDefaults.

Phương thức này giúp bạn cung cấp các giá trị mặc định cho các key mà bạn muốn sử dụng. Nó giúp cho bạn tránh đi việc phải xác định:

  • Đối tượng lưu trữ có tồn tại hay không?
  • Chúng có giá trị mặc định hay không?

Xem ví dụ code nhóe!

let userDefaults = UserDefaults.standard
userDefaults.register(
    defaults: [
        "enabledSound": true,
        "enabledVibration": true
    ]
)

print(userDefaults.bool(forKey: "enabledSound")) // true

Trong đó:

  • Sử dụng phương thức register để tiến hành đăng ký các key & value ban đầu
  • Còn lại thì bạn sử dụng bình thường như trên

Code của bạn lúc này sẽ khá sạch đẹp nhóe!

Và khi bạn đã lưu trữ một dữ liệu với key có trong phần register trước đó rồi. Và bạn lặp lại nó trong phần register kìa, thì bạn cũng an tâm. Các giá trị trong phần register sẽ được bỏ qua, nếu chúng đã tồn lại trước rồi. Do đó, bạn có thể sử dụng register bao nhiêu lần cũng được. Xem ví dụ nữa nha.

let userDefaults = UserDefaults.standard

userDefaults.set(false, forKey: "enabledSound") // 1

userDefaults.register(
    defaults: [
        "enabledSound": true, // 2
        "enabledVibration": true
    ]
)

userDefaults.bool(forKey: "enabledSound") // false

Tạm kết

  • Tìm hiểu về UserDefautls và cách sử dụng cơ bản
  • Đọc & ghi các kiểu dữ liệu cơ bản
  • Đọc & ghi các đối tượng với kiểu dữ liệu Custom
  • Sử dụng register để thêm các dữ liệu mặc định đầu tiên khi sử dụng

 

Okay! Tới đây, mình xin kết thúc bài viết về UserDefaults. 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.

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

FacebookTweetPinYummlyLinkedInPrintEmailShares21

Related Posts:

  • Cơ bản về async/await trong 10 phút - Swift 5.5
    Cơ bản về async/await trong 10 phút - Swift 5.5
  • Cơ bản về Actor trong 10 phút - Swift 5.5
    Cơ bản về Actor trong 10 phút - Swift 5.5
  • Image View trong 10 phút - SwiftUI Notes #26
    Image View trong 10 phút - SwiftUI Notes #26
  • Keychain trong 10 phút - iOS
    Keychain trong 10 phút - iOS
Tags: basic ios tutorial, iOS, Swift
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:

  • Cơ bản về Actor trong 10 phút - Swift 5.5
    Cơ bản về Actor trong 10 phút - Swift 5.5
  • Quick trong 10 phút
    Quick trong 10 phút
  • Opaque Type trong 10 phút - Swift
    Opaque Type trong 10 phút - Swift
  • Convenience Initializer trong 10 phút
    Convenience Initializer trong 10 phút
  • File Manager trong 10 phút - Swift
    File Manager trong 10 phút - Swift

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!