Hãy lưu ý trường hợp này, khi ứng dụng của bạn đang chạy trong nền và bạn không thể truy cập các giá trị được lưu trữ của mình trong NSUserDefaults:
Đã có nhiều chủ đề và lỗi về điều này, nhưng nó lại xảy ra với tôi trong iOS 9. Tôi có một ứng dụng khởi chạy ở chế độ nền để đáp ứng các tác vụ NSURLSession và nội dung có sẵn. Có thể lặp lại, nếu tôi khởi động lại điện thoại của mình và đợi ứng dụng của mình khởi động trong nền, thì khi mở ứng dụng, tôi thấy rằng [[NSUserDefaults standardUserDefaults] dictionaryRepresentation] chứa tất cả các giá trị hệ thống, ví dụ: AppleITunesStoreItemKinds, v.v. nhưng không chứa bất kỳ giá trị nào tôi đã đặt. Nếu tôi buộc thoát và khởi chạy lại ứng dụng, tất cả các giá trị của tôi sẽ quay trở lại. Có cách nào để tránh nó lưu vào bộ nhớ đệm tiêu chuẩnUserDefaults "trống rỗng" từ trước khi điện thoại được mở khóa, hoặc ít nhất là để xác định khi nào chúng bị lỗi và sửa chúng mà không cần phải thoát khỏi ứng dụng?
Vấn đề ở đây là NSUserDefaults cuối cùng được hỗ trợ bởi một tệp trong vùng chứa ứng dụng của bạn và vùng chứa ứng dụng của bạn phải được bảo vệ dữ liệu. Nếu bạn không làm gì đặc biệt thì trên iOS 7 trở lên, vùng chứa của bạn sử dụng NSFileProtectionCompleteUntilFirstUserAuthentication, một giá trị được kế thừa bởi cửa hàng sao lưu NSUserDefaults và vì vậy bạn không thể truy cập nó trước lần mở khóa đầu tiên.
IMO cách tốt nhất để giải quyết vấn đề này là tránh NSUserDefaults cho những thứ mà bạn dựa vào trong các đường dẫn mã có thể thực thi ở chế độ nền. Thay vào đó, hãy lưu trữ các cài đặt đó trong tệp tùy chọn của riêng bạn, tệp có chức năng bảo vệ dữ liệu mà bạn có thể quản lý rõ ràng (trong trường hợp này có nghĩa là 'đặt thành NSFileProtectionNone').
Có hai vấn đề với NSUserDefaults trong ngữ cảnh bảo vệ dữ liệu:
Nó là một API trừu tượng hoàn toàn: sự hiện diện và vị trí của kho dự trữ của nó không được coi là một phần của API đó, vì vậy bạn không thể quản lý rõ ràng việc bảo vệ dữ liệu của nó.
Lưu ý Trên các phiên bản gần đây của OS X NSUserDefaults được quản lý bởi một daemon và những người cố gắng thao tác trực tiếp kho sao lưu của nó đã gặp phải sự cố. Thật dễ dàng để tưởng tượng điều tương tự sẽ đến với iOS vào một thời điểm nào đó.
Ngay cả khi có thể thay đổi bảo vệ dữ liệu, NSUserDefaults không có cơ chế để phân loại dữ liệu dựa trên ngữ cảnh mà bạn đang sử dụng nó; đó là một API 'tất cả hoặc không có gì'. Trong trường hợp của bạn, bạn không muốn xóa bảo vệ khỏi tất cả các cài đặt mặc định của người dùng, mà chỉ những cài đặt bạn cần truy cập trong nền trước khi mở khóa lần đầu.
Cuối cùng, nếu bất kỳ dữ liệu nào thực sự nhạy cảm, bạn nên đưa nó vào chuỗi khóa. Đáng chú ý, chuỗi khóa có khả năng thiết lập bảo vệ dữ liệu trên cơ sở từng mục.