2017-04-22 2 views
0

J'ai créé une application qui est utilisée pour montrer aux utilisateurs les chansons country les plus récentes et les plus populaires. J'utilise les bases de données Firebase pour envoyer et recevoir les informations pour les chansons. C'est dans Xcode en utilisant Swift et UIKit.Comment enregistrer une matrice contenant des informations d'une classe créée à l'aide de UserDefaults

J'ai créé une classe appelée Song qui gère toutes les informations que je reçois de Firebase. Cette classe est ci-dessous.

import Foundation 
import UIKit 

class Song { 

//private var _imageURL: String! 
private var _videoURL: NSMutableURLRequest! 
private var _songTitle: String! 
private var _artistName: String! 
private var _cellNum: Int! 
private var _lastNum: Int! 
private var _spotifyLink: String! 
private var _itunesLink: String! 
private var _lyrics: String! 
private var _saved: Bool! 

// var imageURL: String{ 
//  return _imageURL 
// } 

var videoURL: NSMutableURLRequest{ 
    return _videoURL 
} 

var songTitle: String{ 
    return _songTitle 
} 

var artistName: String{ 
    return _artistName 
} 

var cellNum: Int{ 
    return _cellNum 
} 

var lastNum: Int{ 
    return _lastNum 
} 

var spotifyLink: String{ 
    return _spotifyLink 
} 

var itunesLink: String{ 
    return _itunesLink 
} 

var lyrics: String{ 
    return _lyrics 
} 

var saved: Bool{ 
    get{ 
     return _saved 
    } 
    set{ 
     _saved = newValue 
    } 
} 

init(videoURL: NSMutableURLRequest, songTitle: String, artistName: String, cellNum: Int, lastNum: Int, spotifyLink: String, itunesLink: String, lyrics: String, saved: Bool) { 

    //_imageURL = imageURL 
    _videoURL = videoURL 
    _songTitle = songTitle 
    _artistName = artistName 
    _cellNum = cellNum 
    _lastNum = lastNum 
    _spotifyLink = spotifyLink 
    _itunesLink = itunesLink 
    _lyrics = lyrics 
    _saved = saved 
} 
} 

Dans un de mes fichiers rapides, j'initialisés un nouveau tableau de la chanson de type pour contenir les informations dont l'utilisateur enregistre.

var savedSongs = [Song]() 

Il y a un bouton dans l'une des storyboards que si l'utilisateur clique dessus, il ajoute la chanson enregistrée au tableau et lorsque l'utilisateur va au story-board SavedVC, tous les éléments qui sont enregistrés dans le tableau sont montrés à l'utilisateur. La fonction permettant de cliquer sur le bouton est indiquée ci-dessous.

@IBAction func save(_ sender: Any) { 


    if(saveBtn.currentTitle == "Save"){ 

     song.saved = true 
     let p1 = song 
     savedSongs.append(p1) 
     //UserDefaults save here 
     saveBtn.setTitle("Unsave", for: .normal) 
    } 
    else if(saveBtn.currentTitle == "Unsave"){ 

     if(savedSongs.count != 0){ 
      //let items = (savedSongs.count) - 1 

      let title = song.songTitle 

      for save in 0...savedSongs.count-1{ 

       let removeSave = savedSongs[save] 
       let checkTitle = removeSave.songTitle 

       if(checkTitle == title){ 
        song.saved = false 
        savedSongs.remove(at: save) 
        //UserDefaults save here 
        saveBtn.setTitle("Save", for: .normal) 
        return 
       } 
      } 
     } 
    } 
} 

Alors évidemment, l'utilisateur a une option pour enregistrer, et après cela, il peut re-cliquez sur le bouton pour annuler l'enregistrement de la chanson. Dans le code, l'objet

song.(attribute) 

est envoyé et est la représentation de la cellule qui est sélectionnée qui contient les informations de la classe Song. Comme j'ai mon code en ce moment, tout fonctionne. Le problème est que lorsque je quitte l'application, ce qui est dans le tableau ne reste pas. J'ai essayé UserDefaults, mais je ne suis pas sûr de savoir comment le faire avec le tableau que j'ai. Je souhaite enregistrer la matrice aux valeurs par défaut de l'utilisateur chaque fois que le bouton est cliqué dans l'IBAction de sauvegarde ci-dessus.

+0

variables support privées pour obtenir des constantes sont ridicules à Swift. Utilisez simplement le mot clé 'let', par exemple 'let songTitle: String'. Et ne jamais déclarer des variables comme des optionnels implicites non enveloppés qui sont initialisés avec une méthode init (non optionnelle). – vadian

Répondre

0

Vous devez encoder et décoder les objets afin de les enregistrer dans UserDefaults.

class Song: NSObject, NSCoding { 
    let name: String 
    let url: String 

    init(name: String, url: String) { 
     self.name = name 
     self.url = url 
    } 

    required init(coder decoder: NSCoder) { 
     self.name = decoder.decodeObject(forKey: "name") as? String ?? "" 
     self.url = decoder.decodeInteger(forKey: "url") as? String ?? "" 
    } 

    func encode(with coder: NSCoder) { 
     coder.encode(name, forKey: "name") 
     coder.encode(age, forKey: "url") 
    } 
} 

Et puis pour récupérer et enregistrer:

class MyViewController: UIViewController { 
    override func viewDidLoad() { 
     super.viewDidLoad() 
     // SAVE TO DEFAULTS 
     let song = Song(name: "Song", url: "http://song.com") 
     var songs = [Song]() 
     songs.append(song) 
     let encodedData = NSKeyedArchiver.archivedData(withRootObject: songs) 
     UserDefaults.standard.set(encodedData, forKey: "songs") 

     // RETRIEVE FROM DEFAULTS 
     if let data = UserDefaults.standard.data(forKey: "songs"), 
      let mySongs = NSKeyedUnarchiver.unarchiveObject(with: data) as? [Song] { 
      mySongs.forEach({print($0.name, $0.url)}) 
     } else { 
      print("ERROR") 
     } 
    } 
} 
+0

Cela a fonctionné parfaitement pour moi! Merci beaucoup! –

+0

Le codeur code toujours les deux valeurs non facultatives. Pourquoi vérifiez-vous pour «néant»? Cela n'arrivera jamais. – vadian