Should I use NSUserDefaults or a plist to store data?

后端 未结 9 1384
北海茫月
北海茫月 2020-11-28 19:17

I will be storing a few strings (maybe 10-20). I am not sure if I should use NSUserDefaults to save them, or write them out to a plist. What is considered best practice? NSU

相关标签:
9条回答
  • 2020-11-28 19:51

    Using a plist is a good choice for storing your strings if the strings are not just user settings that can go in NSUserDefaults. As was mentioned, when using a plist you must store your plist in the Documents directory in order to write to it, because you can't write into your own app's resources. When I first learned this, I wasn't clear on where your own app's Bundle directory was vs. where the Documents directory was, so I thought I'd post example code here that first copies a plist called "Strings.plist" (that you already have in your own app's Bundle directory) to the Documents directory, and then writes to it and reads from it.

    // Make a path to the plist in the Documents directory
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *stringsPlistPathIndDoc = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"Strings.plist"];
    
    // Make a path to the plist in your app's Bundle directory
    NSString *stringsPlistPathInBundle = [[NSBundle mainBundle] pathForResource:@"Strings" ofType:@".plist"];
    
    NSFileManager *fileManager = [NSFileManager defaultManager];
    
    // Check first that you haven't already copied this plist to the Documents directory
    if (![fileManager fileExistsAtPath:stringsPlistPathIndDoc])
    {
        NSError *error;
    
        // Copy the plist from the Bundle directory to the Documents directory 
        [fileManager copyItemAtPath:stringsPlistPathInBundle toPath:stringsPlistPathIndDoc error:&error];
    }
    
    // Write your array out to the plist in the Documents directory
    NSMutableArray *stringsArray = [[NSMutableArray alloc] initWithObjects:@"string1", @"string2", @"string3", nil]; 
    [stringsArray writeToFile:stringsPlistPathIndDoc atomically:YES];
    
    // Later if you want to read it:
    stringsArray = [[NSMutableArray alloc] initWithContentsOfFile:stringsPlistPathIndDoc];
    
    0 讨论(0)
  • 2020-11-28 20:00

    iOS ultimately stores all NSUserDefaults data to a plist file. So it will not affect the performance if that is your concern. I personally prefer using NSUserDefaults for small data and plist for a relatively large set of data.

    Note: Never store any sensitive information in NSUserDefaults as anyone can see that data.

    0 讨论(0)
  • NSUserDefaults will store the user preferences into a file into the Library/Preferences folder. In theory it serves only to store some application/user properties.

    Plist file are usefull to manage a single file. If you need to manage more you should use the Coredata. There is no restriction about the size of the plist file. Otherwise you have to be careful with plist file because when you need to save or read it the entire contents of the file will be load into memory.

    0 讨论(0)
  • 2020-11-28 20:01

    It depends on what you want to store and why. NSUserDefaults is meant for storing user preferences. You can try to use it for other things, but you probably shouldn't.

    Otherwise, if your needs are simple a plist file is pretty straightforward. You can also use core data or come up with your own file format. In general, I use plist for simple tasks and then move to core data for anything more complex.

    0 讨论(0)
  • 2020-11-28 20:02

    I am assuming an array, but it will work with dictionaries too.

    Userdefaults, Core Data and Plists can all be read/write but if you use a plist you need to pay attention in what dir you put it. See the plist part down below.

    Core Data I think it's way too much overkill, it's just strings. It's supposed to be used when you want to persist more complex objects.

    NSUserDefaults:

    It's pretty fast and easy to do, though it's supposed to store only user settings. To write them to the userdefaults:

    NSArray *stringsArray = [[NSArray alloc] arrayWithObjects: string1, string2, string3, nil];
    [[NSUserDefaults standardUserDefaults] setObject:stringsArray forKey:@"MyStrings"];
    [[NSUserDefaults standardUserDefaults] synchronize];
    

    To read the from the userdefaults:

    NSArray *stringsArray = [[NSUserDefaults standardUserDefaults] objectForKey:@"MyStrings"];
    

    Plist:

    If your strings are going to be modified you will need to write and read a plist but you cant't write into your app's resources.

    1. To have a read/write plist first find the documents directory

      NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
      NSString *stringsPlistPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"Strings.plist"];
      
    2. Create the array (I am assuming the strings are string1, ...)

      NSArray *stringsArray = [[NSArray alloc] arrayWithObjects: string1, string2, string3, nil];
      
    3. Write it to file

      [stringsArray writeToFile:stringsPlistPath atomically:YES];
      

    To read the plist:

    1. Find the documents directory

      NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
      NSString *stringsPlistPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"Strings.plist"];
      
    2. Read it in:

      NSArray *stringsArray = [NSArray arrayWithContentsOfFile:stringsPlistPath];
      
    0 讨论(0)
  • 2020-11-28 20:03

    NSUSerDefaults is indeed quick to implement, but mostly as your application grows, you want to store more and more, I went directly for plist files.

    Mostly, people want to store a list of something, so here is my share on how to do this with NSDictionary. This does not require you to create a plist file first, it will be created at the first time saving something

    xcode 7 beta, Swift 2.0

    saving

    func SaveItemFavorites(items : Array<ItemFavorite>) -> Bool
    {
        let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray
        let docuDir = paths.firstObject as! String
        let path = docuDir.stringByAppendingPathComponent(ItemFavoritesFilePath)
        let filemanager = NSFileManager.defaultManager()
    
        let array = NSMutableArray()        
        
        for var i = 0 ; i < items.count ; i++
        {
            let dict = NSMutableDictionary()
            let ItemCode = items[i].ItemCode as NSString
            
            dict.setObject(ItemCode, forKey: "ItemCode")
            //add any aditional..
            array[i] = dict
        }
        
        let favoritesDictionary = NSDictionary(object: array, forKey: "favorites")
        //check if file exists
        if(!filemanager.fileExistsAtPath(path))
        {
            let created = filemanager.createFileAtPath(path, contents: nil, attributes: nil)
             if(created)
             {
                 let succeeded = favoritesDictionary.writeToFile(path, atomically: true)
                 return succeeded
             }
             return false
        }
        else
        {
            let succeeded = notificationDictionary.writeToFile(path, atomically: true)
            return succeeded
        }
    }
    

    Little note from the docs:

    NSDictionary.writeToFile(path:atomically:)

    This method recursively validates that all the contained objects are property list objects (instances of NSData, NSDate, NSNumber, NSString, NSArray, or NSDictionary) before writing out the file, and returns NO if all the objects are not property list objects, since the resultant file would not be a valid property list.

    So whatever you set at dict.SetObject() should be one of the above mentioned types.

    loading

    private let ItemFavoritesFilePath = "ItemFavorites.plist"
    
    func LoadItemFavorites() -> Array<ItemFavorite>
    {
        let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray
        let docuDir = paths.firstObject as! String
        let path = docuDir.stringByAppendingPathComponent(ItemFavoritesFilePath)
        let dict = NSDictionary(contentsOfFile: path)
        let dictitems : AnyObject? = dict?.objectForKey("favorites")
        
        var favoriteItemsList = Array<ItemFavorite>()
        
        if let arrayitems = dictitems as? NSArray
        {
            for var i = 0;i<arrayitems.count;i++
            {
                if let itemDict = arrayitems[i] as? NSDictionary
                {
                    let ItemCode = itemDict.objectForKey("ItemCode") as? String
                    //get any additional
                    
                    let ItemFavorite = ItemFavorite(item: ItemCode)
                    favoriteItemsList.append(ItemFavorite)
                }
            }
        }
        
        return favoriteItemsList
    }
    
    0 讨论(0)
提交回复
热议问题