How to retrieve data from NSUserDefaults?

702 Views Asked by At

currently, I try make an music playlist application. I try to save and retrieve playlist data from NSUserDefaults. I have no problem when saving the data but I got an error when retrieving data.

I got:

Terminating app due to uncaught exception 'MPMediaItemCollectionInitException', reason: '-init is not supported, use -initWithItems:

I'm following the answer from Play iPod playlist retrieved from a saved persistentid list but I try to write it in swift.

here is my save function:

func savePlaylist(var mediaItemCollection: MPMediaItemCollection){

    var items: NSArray = mediaItemCollection.items

    var listToSave: NSMutableArray = NSMutableArray()

    for song in items{

        var persistentId: AnyObject! = song.valueForProperty(MPMediaItemPropertyPersistentID)

        listToSave.addObject(persistentId)

    }

    var data: NSData = NSKeyedArchiver.archivedDataWithRootObject(listToSave)

    NSUserDefaults.standardUserDefaults().setObject(data, forKey: "songsList")
    NSUserDefaults.standardUserDefaults().synchronize()

}

and here is my retrieve function:

func setupMusic(){

    if NSUserDefaults.standardUserDefaults().objectForKey("songsList") != nil{

        var theList: NSMutableArray = NSMutableArray()

        var data: NSData = (NSUserDefaults.standardUserDefaults().objectForKey("songsList") as? NSData)!

        var decodedData: NSArray  = (NSKeyedUnarchiver.unarchiveObjectWithData(data) as? NSArray)!

        theList.addObjectsFromArray(decodedData as [AnyObject])

        var allTheSongs: NSMutableArray = NSMutableArray()

        for var i = 0; i < theList.count; i++ {

            var songQuery = MPMediaQuery.songsQuery()

            var songs: NSArray = songQuery.items

            allTheSongs.addObject(songs)

        }

        var currentQueue: MPMediaItemCollection = MPMediaItemCollection()

        myMusicPlayer?.setQueueWithItemCollection(currentQueue)


    }else{
        println("fail!!!!!!!!!!!!")
    }

}

How can I fix it?

2

There are 2 best solutions below

2
On BEST ANSWER

Here is the issue var currentQueue: MPMediaItemCollection = MPMediaItemCollection()

You must init with items

As per the documentation by apple.

init(items:) Designated Initializer

Initializes a media item collection with an array of media items. Declaration

Swift

init!(items items: [AnyObject]!) Parameters items

The array of items you are assigning to the media item collection.

You have to init with items like

var currentQueue: MPMediaItemCollection = MPMediaItemCollection(items:itemsArray)
1
On

I am giving you a very simple way to any kind of object and retrieve from NSUserDefault . You don't need to use explicitly archive and unarchive . Just create a category of NSUserDefaults as follow

#import <Foundation/Foundation.h>
@interface NSUserDefaults (AKSNSUserDefaults)
- (void)saveCustomObject:(id<NSCoding>)object
                     key:(NSString *)key;
- (id<NSCoding>)loadCustomObjectWithKey:(NSString *)key;
@end  

@implementation NSUserDefaults (AKSNSUserDefaults)

- (void)saveCustomObject:(id<NSCoding>)object
                     key:(NSString *)key {
    NSData *encodedObject = [NSKeyedArchiver archivedDataWithRootObject:object];
    [self setObject:encodedObject forKey:key];
    [self synchronize];

}

- (id)loadCustomObjectWithKey:(NSString *)key {
    NSData *encodedObject = [self objectForKey:key];
    id object = [NSKeyedUnarchiver unarchiveObjectWithData:encodedObject];
    return object;
}

@end

and than your NSUserDefaults is ready to store any object . but one thing is need to use NSCoder in your object model .

for example :

#import <Foundation/Foundation.h>

@interface AKSClassA : NSObject<NSCoding>
// declared some property 
@property (nonatomic,assign) NSInteger userID;
@property (nonatomic,strong) NSString *userName;
@end
#import "AKSClassA.h"
@implementation AKSClassA
@synthesize userID;
@synthesize userName;
-(id)initWithCoder:(NSCoder *)aDecoder{
    if (self = [super init]) {

        self. userID = [aDecoder decodeIntegerForKey:@"userID"];
        self. userName = [aDecoder decodeObjectForKey:@"userName"];

   }
    return self;
}
-(void)encodeWithCoder:(NSCoder *)aCoder{
    [aCoder encodeInteger:userID  forKey:@"userID"];
    [aCoder encodeObject:userName forKey:@"userName"];
}
@end
// in some class if you are using classA object member to store and retrieve with value  example below 
// to save data in NSUserDefaults 
  AKSClassA *obj =[array1 objectAtIndex:index];
  [[NSUserDefaults standardUserDefaults] saveCustomObject:button key:@"userData"];

// to retrieve data 
 AKSClassA *obj1 = (AKSClassA*)[[NSUserDefaults standardUserDefaults]loadCustomObjectWithKey:@"userData"];

    [titleLabel  setText:obj1.userName];