[RESOLU] Code logique dans une class

Hello à tous,

Petite question de newbie: le code logique dans une class n’est exécuté qu’à l’instanciation de celle-ci?

En faite, je suis en train de séparer le code logique de mes VC, du coup j’instancie une class qui regroupe des fonctions et elle me retourne toujours la même chose, c’est normal?

Je suis passé à coté de quelque chose? Ma logique est à coté de la plaque?

class CurrentTrack {
    
    private static var s_instance:CurrentTrack? = nil
    public static var shared:CurrentTrack {
        if s_instance == nil {
            s_instance = CurrentTrack()
        }
        return s_instance!
    }
    
    let player = Player.shared
    
    private init() {
        downloadJSON {
        }
    }
    
    var track = String()
    var artist = String()
    var broadcastId = String()
    var cover = String()
    var date = String()
    var time = String()
    var shareLink = String()
    var onair = String()

    private func downloadJSON(completed: @escaping () -> ()) {
        
        let currentStation = player.getName()
        let url = URL(string: "http://www.xxxxxxxxxxx.fr/ajax/current")
        
        URLSession.shared.dataTask(with: url!) { (data, response, error) in
            if error == nil {
                do {
                    let Tracks = try JSONDecoder().decode(Song.self, from: data!)
                    
                    DispatchQueue.main.async {
                        completed()
                        switch currentStation {
                        case "xxxxxxxxxxxxxxxxx":
                            self.track = Tracks.current.track
                            self.artist = Tracks.current.artist
                            self.broadcastId = String(Tracks.current.broadcastId)
                            self.cover = Tracks.current.cover
                            self.date = Tracks.current.date
                            self.time = Tracks.current.time
                            self.shareLink = Tracks.current.shareLink
                        case "xxxxxxxxxxxxxxxxxx":
                            self.track = Tracks.xxx.track
                            self.artist = Tracks.xxx.artist
                            self.broadcastId = String(Tracks.xxx.broadcastId)
                            self.cover = Tracks.xxx.cover
                            self.date = Tracks.xxx.date
                            self.time = Tracks.xxx.time
                            self.shareLink = Tracks.xxx.sharleLink
                        case "xxxxxxxxxxxxxx":
                            self.track = Tracks.xxx.track
                            self.artist = Tracks.xxx.artist
                            self.broadcastId = String(Tracks.xxx.broadcastId)
                            self.cover = Tracks.xxx.cover
                            self.date = Tracks.xxx.date
                            self.time = Tracks.xxx.time
                            self.shareLink = Tracks.xxx.sharleLink
                        case "xxxxxxxxxxxxxxx":
                            self.track = Tracks.onsp.track
                            self.artist = Tracks.onsp.artist
                            self.broadcastId = String(Tracks.onsp.broadcastId)
                            self.cover = Tracks.onsp.cover
                            self.date = Tracks.onsp.date
                            self.time = Tracks.onsp.time
                            self.shareLink = Tracks.onsp.sharleLink
                        default:
                            self.track = Tracks.current.track
                            self.artist = Tracks.current.artist
                            self.broadcastId = String(Tracks.current.broadcastId)
                            self.cover = Tracks.current.cover
                            self.date = Tracks.current.date
                            self.time = Tracks.current.time
                            self.shareLink = Tracks.current.shareLink
                        }
                        self.onair = currentStation
                        
                    }
                } catch {
                    print("JSON Error: \(error)")
                }
            }
        }.resume()
    }
    
}

Dans mon VC, j’utilise une boucle qui va chercher les infos toutes les 3 secondes.

let getCurrentTrack = CurrentTrack.shared   

 override func viewDidLoad() {
        super.viewDidLoad()
       //...
        Timer.scheduledTimer(timeInterval: 3.0, target: self, selector: #selector(getCurrentTrackFromClass), userInfo: nil, repeats: true)
    }

    @objc func getCurrentTrackFromClass() {
        print("Current track : (\(getCurrentTrack.date) - \(getCurrentTrack.time)) \(getCurrentTrack.artist) - \(getCurrentTrack.track) (\(getCurrentTrack.onair))")
    }

Du coup, les valeurs de getCurrentTrack ne changent jamais après le premier appel.

Si je ne suis pas sur la bonne voie, n’hésitez pas a me le dire :man_shrugging:t2:

Merci pour votre aide! :pray:t2:

private static var s_instance:CurrentTrack? = nil
public static var shared:CurrentTrack {
    if s_instance == nil {
        s_instance = CurrentTrack()
    }
    return s_instance!
}

dans ce code tu créer un objet CurrentTrack avec les propriété actuelle de celui ci sous le nom s_instance. par contre par la suite tu modifie les propriétés des self, self.track etc… mais pas les propriété de s_instance qui lui est un objet avec ses propriétés de départ je ferais un Guard au debut de ton switch pour vérifier que s_instance est different de Nil et je modifierais ses propriétés dans le switch. s_instance.track = Tracks.current.track. Je suis pas sur de ce que je te dit car je te répond a froid sans test mais dans ma logique a moi ça fonctionnerais

Hello @nicopicks,

merci pour ta réponse, j’ai suivi le cours sur les singletons de @mbritto pour avoir accès a cette class où que je sois dans mon app et autant de fois que je le souhaite avec les mêmes variables.
J’ai appliqué ce principe à d’autres class de mon app, ça fonctionne comme je le souhaite.

J’ai peur de ne pas comprendre ce que tu me dis pour le coup :frowning:

En gros ce que je voulais dire c’est que tu utilise getCurrentTrack qui va chercher les info contenu dans shared qui retourne l’objet CurrentTrack contenu dans la variable s_instance qui lui n’est jamais modifier une fois créer et qui restera le même même si les valeur de tas classe objet change par la suite.

import Foundation

class CurrentTrack {

private static var s_instance:CurrentTrack? = nil
public static var shared:CurrentTrack {
    if s_instance == nil {
        s_instance = CurrentTrack()
    }
    return s_instance!
}

let player = Player.shared

private init() {
    downloadJSON {
    }
}

var track = String()
var artist = String()
var broadcastId = String()
var cover = String()
var date = String()
var time = String()
var shareLink = String()
var onair = String()

private func downloadJSON(completed: @escaping () -> ()) {
    
    let currentStation = player.getName()
    let url = URL(string: "http://www.xxxxxxxxxxx.fr/ajax/current")
    
    URLSession.shared.dataTask(with: url!) { (data, response, error) in
        if error == nil {
            do {
                let Tracks = try JSONDecoder().decode(Song.self, from: data!)
                
                DispatchQueue.main.async {
                    completed()
                    guard (CurrentTrack.s_instance != nil) else {return}
                    switch currentStation {
                        
                    case "xxxxxxxxxxxxxxxxx":
                        CurrentTrack.s_instance.track = Tracks.current.track
                        CurrentTrack.s_instance.track = Tracks.current.artist
                        CurrentTrack.s_instance.track = String(Tracks.current.broadcastId)
                        CurrentTrack.s_instance.track = Tracks.current.cover
                        CurrentTrack.s_instance.track = Tracks.current.date
                        CurrentTrack.s_instance.track = Tracks.current.time
                        CurrentTrack.s_instance.track = Tracks.current.shareLink

                       ETC........

Dans ce code on prend les mofidification des infos de la musique en cour sur la variable static que tu appelle plus tard dans ton VC

ahhh oui d’acc, j’ai compris, mais alors a ce moment je peux aussi supprimer ce bloc?:

private static var s_instance:CurrentTrack? = nil
public static var shared:CurrentTrack {
    if s_instance == nil {
        s_instance = CurrentTrack()
    }
    return s_instance!
}

J’ai essayé ton code @nicopicks , ça ne fonctionne pas :pensive:

J’ai ajouté guard (CurrentTrack.s_instance != nil) else {return}

et j’ai remplacé tous les self par CurrentTrack.s_instance?

ça me retourne toujours le même titre.

Salut, désoler j’ai pas trop eu le temps de resuivre ton post jusqu’à maintenant. Voila le code que tu dois avoir:

import Foundation

class CurrentTrack {

private static var s_instance:CurrentTrack? = nil
public static var shared:CurrentTrack {
    if s_instance == nil {
        s_instance = CurrentTrack()
    }
    return s_instance!
}

var track = String()
var artist = String()
var broadcastId = String()
var cover = String()
var date = String()
var time = String()
var shareLink = String()
var onair = String()
let player = Player.shared

private init() {
    downloadJSON {
    }
}



private func downloadJSON(completed: @escaping () -> ()) {
    
    let currentStation = player.getName()
    let url = URL(string: "http://www.xxxxxxxxxxx.fr/ajax/current")
    
    URLSession.shared.dataTask(with: url!) { (data, response, error) in
        if error == nil {
            do {
                let Tracks = try JSONDecoder().decode(Song.self, from: data!)
                
                DispatchQueue.main.async {
                    completed()
                    guard (CurrentTrack.s_instance != nil) else {return}
                    switch currentStation {
                        
                    case "xxxxxxxxxxxxxxxxx":
                        CurrentTrack.s_instance.track = Tracks.current.track
                        CurrentTrack.s_instance.artist = Tracks.current.artist
                        CurrentTrack.s_instance?.broadcastId = String(Tracks.current.broadcastId)
                        CurrentTrack.s_instance.cover = Tracks.current.cover
                        CurrentTrack.s_instance.date = Tracks.current.date
                        CurrentTrack.s_instance.time = Tracks.current.time
                        CurrentTrack.s_instance?.shareLink = Tracks.current.shareLink
                    case "xxxxxxxxxxxxxxxxxx":
                        CurrentTrack.s_instance.track = Tracks.xxx.track
                        CurrentTrack.s_instance.artist = Tracks.xxx.artist
                        CurrentTrack.s_instance?.broadcastId = String(Tracks.xxx.broadcastId)
                        CurrentTrack.s_instance.cover = Tracks.xxx.cover
                        CurrentTrack.s_instance.date = Tracks.xxx.date
                        CurrentTrack.s_instance.time = Tracks.xxx.time
                        CurrentTrack.s_instance?.shareLink = Tracks.xxx.sharleLink
                    case "xxxxxxxxxxxxxx":
                        CurrentTrack.s_instance.track = Tracks.xxx.track
                        CurrentTrack.s_instance.artist = Tracks.xxx.artist
                        CurrentTrack.s_instance?.broadcastId = String(Tracks.xxx.broadcastId)
                        CurrentTrack.s_instance.cover = Tracks.xxx.cover
                        CurrentTrack.s_instance.date = Tracks.xxx.date
                        CurrentTrack.s_instance.time = Tracks.xxx.time
                        CurrentTrack.s_instance?.shareLink = Tracks.xxx.sharleLink
                    case "xxxxxxxxxxxxxxx":
                        CurrentTrack.s_instance.track = Tracks.onsp.track
                        CurrentTrack.s_instance.artist = Tracks.onsp.artist
                        CurrentTrack.s_instance?.broadcastId = String(Tracks.onsp.broadcastId)
                        CurrentTrack.s_instance.cover = Tracks.onsp.cover
                        CurrentTrack.s_instance.date = Tracks.onsp.date
                        CurrentTrack.s_instance.time = Tracks.onsp.time
                        CurrentTrack.s_instance?.shareLink = Tracks.onsp.sharleLink
                    default:
                        CurrentTrack.s_instance.track = Tracks.current.track
                        CurrentTrack.s_instance.artist = Tracks.current.artist
                        CurrentTrack.s_instance?.broadcastId = String(Tracks.current.broadcastId)
                        CurrentTrack.s_instance.cover = Tracks.current.cover
                        CurrentTrack.s_instance.date = Tracks.current.date
                        CurrentTrack.s_instance.time = Tracks.current.time
                        CurrentTrack.s_instance?.shareLink = Tracks.current.shareLink
                    }
                    CurrentTrack.s_instance.onair = currentStation
                    
                }
            } catch {
                print("JSON Error: \(error)")
            }
        }
        }.resume()
}

}

La logique du code est plutôt simple tu crée ton objet statique s_instance et ensuite on le modifie quand on appelle la fonction download JSON

En gros la fonction de recharge toute les 3 seconde ne sert à rien si tu appelle pas le téléchargement et le traitement du fichier JSON. une fois que tu passe dans cette fonction tu modifie ton objet statique avec les nouvelles valeurs des caractéristiques musicales actuelle par exemple tu peut appeler le download à chaque fois que tu demande l’accès à s_instance:

import Foundation

class CurrentTrack {

private static var s_instance:CurrentTrack? = nil
public static var shared:CurrentTrack {
    if s_instance == nil {
        s_instance = CurrentTrack()
    }
    s_instance?.refresh()
    return s_instance!
}

var track = String()
var artist = String()
var broadcastId = String()
var cover = String()
var date = String()
var time = String()
var shareLink = String()
var onair = String()
let player = Player.shared

private init() {
    downloadJSON {
    }
}



private func downloadJSON(completed: @escaping () -> ()) {
    
    let currentStation = player.getName()
    let url = URL(string: "http://www.xxxxxxxxxxx.fr/ajax/current")
    
    URLSession.shared.dataTask(with: url!) { (data, response, error) in
        if error == nil {
            do {
                let Tracks = try JSONDecoder().decode(Song.self, from: data!)
                
                DispatchQueue.main.async {
                    completed()
                    guard (CurrentTrack.s_instance != nil) else {return}
                    switch currentStation {
                        
                    case "xxxxxxxxxxxxxxxxx":
                        CurrentTrack.s_instance.track = Tracks.current.track
                        CurrentTrack.s_instance.artist = Tracks.current.artist
                        CurrentTrack.s_instance?.broadcastId = String(Tracks.current.broadcastId)
                        CurrentTrack.s_instance.cover = Tracks.current.cover
                        CurrentTrack.s_instance.date = Tracks.current.date
                        CurrentTrack.s_instance.time = Tracks.current.time
                        CurrentTrack.s_instance?.shareLink = Tracks.current.shareLink
                    case "xxxxxxxxxxxxxxxxxx":
                        CurrentTrack.s_instance.track = Tracks.xxx.track
                        CurrentTrack.s_instance.artist = Tracks.xxx.artist
                        CurrentTrack.s_instance?.broadcastId = String(Tracks.xxx.broadcastId)
                        CurrentTrack.s_instance.cover = Tracks.xxx.cover
                        CurrentTrack.s_instance.date = Tracks.xxx.date
                        CurrentTrack.s_instance.time = Tracks.xxx.time
                        CurrentTrack.s_instance?.shareLink = Tracks.xxx.sharleLink
                    case "xxxxxxxxxxxxxx":
                        CurrentTrack.s_instance.track = Tracks.xxx.track
                        CurrentTrack.s_instance.artist = Tracks.xxx.artist
                        CurrentTrack.s_instance?.broadcastId = String(Tracks.xxx.broadcastId)
                        CurrentTrack.s_instance.cover = Tracks.xxx.cover
                        CurrentTrack.s_instance.date = Tracks.xxx.date
                        CurrentTrack.s_instance.time = Tracks.xxx.time
                        CurrentTrack.s_instance?.shareLink = Tracks.xxx.sharleLink
                    case "xxxxxxxxxxxxxxx":
                        CurrentTrack.s_instance.track = Tracks.onsp.track
                        CurrentTrack.s_instance.artist = Tracks.onsp.artist
                        CurrentTrack.s_instance?.broadcastId = String(Tracks.onsp.broadcastId)
                        CurrentTrack.s_instance.cover = Tracks.onsp.cover
                        CurrentTrack.s_instance.date = Tracks.onsp.date
                        CurrentTrack.s_instance.time = Tracks.onsp.time
                        CurrentTrack.s_instance?.shareLink = Tracks.onsp.sharleLink
                    default:
                        CurrentTrack.s_instance.track = Tracks.current.track
                        CurrentTrack.s_instance.artist = Tracks.current.artist
                        CurrentTrack.s_instance?.broadcastId = String(Tracks.current.broadcastId)
                        CurrentTrack.s_instance.cover = Tracks.current.cover
                        CurrentTrack.s_instance.date = Tracks.current.date
                        CurrentTrack.s_instance.time = Tracks.current.time
                        CurrentTrack.s_instance?.shareLink = Tracks.current.shareLink
                    }
                    CurrentTrack.s_instance.onair = currentStation
                    
                }
            } catch {
                print("JSON Error: \(error)")
            }
        }
        }.resume()
}

private func refresh() {
    downloadJSON {
    }
}

}

Dans le code j’ai simplement créer la fonction refresh qui se charge de lancer la fonction DownloadJSON qui modifiera l’objet CurrentTrack stocker dans la variable static s_instance retourner par la variable static public shared. La fonction refresh est appeler a chaque fois que tu fais appelle a ta propriété calculé shared test ça et dis moi =)

j’ai essayé de ton code, ca ne fonctionne toujours pas :pensive:
Je reçois toujours le même titre

Voila mes appels dans mon VC :

class PlayerViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, AVRoutePickerViewDelegate, MPPlayableContentDataSource, MPPlayableContentDelegate {
let getCurrentTrack = CurrentTrack.shared
...

override func viewDidLoad() {
    super.viewDidLoad()
    getCurrentTrackFromClass()
    Timer.scheduledTimer(timeInterval: 3.0, target: self, selector: #selector(getCurrentTrackFromClass), userInfo: nil, repeats: true)
}

@objc func getCurrentTrackFromClass() {
    print("Current track : (\(getCurrentTrack.date) - \(getCurrentTrack.time)) \(getCurrentTrack.artist) - \(getCurrentTrack.track) (\(getCurrentTrack.onair))")
}

Je met ça au cas où je fais quelque chose que je ne fais pas correctement.

:pensive:

    @objc func getCurrentTrackFromClass() {
        print("Current track : (\(CurrentTrack.shared.date) - \(CurrentTrack.shared.time)) \(CurrentTrack.shared.artist) - \(CurrentTrack.shared.track) (\(CurrentTrack.shared.onair))")
}

Ce code devrait mieux fonctionner car:

let getCurrentTrack = CurrentTrack.shared 

est instancé une seule fois et ne suis donc pas l’évolution de CurrentTrack.shared mais copie sont état au moment ou tu l’appelle pour la première fois pour palier au problème tu pourrais le modifier en variable et non constante puis écrire

getCurrentTrack = CurrentTrack.shared

dans tas fonction « getCurrentTrackFromClass() »

comme ça toutes les 3 secondes prendrais l’état de CurrentTrack.shared qui lui est bien mis à jours

En espérant t’avoir aidé :crossed_fingers:

1 « J'aime »

Ca fonctionne! :wink:

Merci 1000 fois!