Logique Singleton

Hello à tous,

J’ai une difficulté avec la notion de Singleton. J’ai bien compris le but, mais pas exactement la manière de faire… :confused:

Voici mon code:

import UIKit
import AVFoundation
import AVKit

class Player {
    
    private static var s_instance:Player? = nil
    public static var shared:Player {
        if s_instance == nil {
            s_instance = Player()
        }
        return s_instance!
    }
    
    private static var name = String()
    static let radio = AVPlayer()
    private static let urlabc = AVURLAsset(url: URL(string: "http://xxxxxxxxxxxxxabc.m3u")!)
    private static let urldef = AVURLAsset(url: URL(string: "http://xxxxxxxxxxxxxdef.m3u")!)
    private static let urlghi = AVURLAsset(url: URL(string: "http://xxxxxxxxxxxxxghi.m3u")!)

    
    func play(radio:String, bitrate:Int) {
        var url:AVURLAsset
            switch radio {
            case "abc":
                Player.name = "abc"
                url = Player.urlabc
            case "def":
                Player.name = "def"
                url = Player.urldef
            case "ghi":
                Player.name = "ghi"
                url = Player.urlghi
            default:
                Player.name = "abc"
                url = Player.urlabc
        }
        let playerItem = AVPlayerItem(asset: url)
        Player.radio.replaceCurrentItem(with: playerItem)
        Player.radio.rate = 1.0
        Player.radio.play()
    }
    
    func getName() -> String {
        return Player.name
    }
}

dans tous mes ViewController’s, je fais:
let player = Player.shared
au lieu de
let player = Player()
Comme indiqué dans les videos.
Mais je ne récupère pas le bon nom quand je fais
let onair = player.getName()

Je pense que mon problème viens de mon Singleton, mais je ne vois pas comment m’y prendre. si qqn peut m’aiguiller, ça serait vraiment apprécié :blush:

Hello @didier,

Ceci devrait fonctionner ;::


private var name = String() // on retire le mot clé static

case « abc »:
shared.name = « abc » // ou self.name = « abc »
url = Player.urlabc
case « def »:
shared.name = « def »
url = Player.urldef
case « ghi »:
shared.name = « ghi »
url = Player.urlghi
default:
shared.name = « abc »
url = Player.urlabc
}

Hello @Samir

Merci pour ta réponse!:blush:

Ton code fonctionne, que j’ajoute ‘self’ ou pas d’ailleurs (shared.name ne fonctionne pas), il faut juste que j’enlève le mot clé static.

En revanche, à l’appel de
let player = Player.shared

print(player.getName())

ça renvoie tout le temps ‘abc’

ben c’est normal que cela retourne toujours abc, c’est ta valeur par défaut dans ton switch…
dans ton exemple, tu n’appelles jamais ta fonction play avec le paramètre radio rempli avec une chaine donc il est toujours égal à défaut donc à ‘abc’…

Euh si si je l’appelle bien, désolé, je n’ai pas précisé

J’appelle player.play(radio: “def”, bitrate: 128)

Salut @didier,
Si je comprends bien, tu fais :

let player = Player.shared
player.play(radio: “def”, bitrate: 128)
print(player.getName())

Et il t’affiche “abc”, c’est bien ça ?

Exact! :smiley: @iMrMaximus
Une idée?

Pas encore mais j’y travaille :wink:

Hum… c’est bizarre, je viens de mettre ta class dans l’un de mes projets, le code de mon message précédent et Xcode m’affiche “def” :thinking:

Et, au fait, pourquoi toutes tes variables de ta class sont définies en tant que singleton ?

Alor en fait je n’avais pas vu mais ton erreur vien de ta fonction :slight_smile:

func getName() → String {
return Player.name
}

il faudrait plutot faire :

func getName() → String {
return self.name
}

En fait l’idée du Singleton c’est d’avoir une seule et meme instance d’une classe utilisable partout dans l’app a n’importe quel moment. Du coup a part la variable qui stock l’instance de ta classe tu n’a pas besoin de mettre toute tes variables en static.

Je ne suis pas sûr que l’erreur vienne de la fonction getName() parce qu’en reprenant son code, je n’ai pas d’erreur, la fonction me retourne la bonne valeur.

Cependant, je suis de ton avis sur le sujet du singleton :slight_smile:

bon, je viens de passer une heure sur mon soucis :disappointed_relieved:

J’ai enlevé tous les static comme vous l’avez soulignés.

En ce qui concerne le fait que mon code m’affiche toujours “abc” au lieu de “def” vient du fait que je passais par une variable :

dans un de mes VC, j’ai fait :

let player = Player.shared
let onair = player.getName() //ou même = Player.shared.getName() peu importe

du coup onair avait toujours comme valeur “abc”…

le but était de faire un peu plus bas dans le code une comparaison avec onair:

...
if onair == "abc" {
...
}
...
if onair == "def" {
...
}
...

résultat, j’ai solutionné mon soucis a force de faire des print() de partout… :love_you_gesture:

au lieu de if onair == "abc", je fais if player.getName() == "abc"

Si il y a une explication, je suis preneur, parce que là, je comprend pas trop… :exploding_head:

Merci a vous en tout cas!!!

C’est à dire ?
Peux-tu nous passer tout le code de cette partie (tout le code possédant un lien avec Player ?

J’ai presque honte de vous dire pourquoi ça ne fonctionnait pas en fin de compte. :sweat_smile:

Mes variables étaient en dehors de la class en faite :face_with_hand_over_mouth:

import UIKit

let player:Player = Player.shared
let onair:String = Player.shared.getName()
let BITRATE:Int = UserDefaults.standard.integer(forKey: "BITRATE")

class RadioChoiceMenuViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {

du coup, j’ai fait ça:

import UIKit

class RadioChoiceMenuViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
    let player:Player = Player.shared
    let onair:String = Player.shared.getName()
    let BITRATE:Int = UserDefaults.standard.integer(forKey: "BITRATE") 

ça fonctionne bien mieux :see_no_evil:

Merci a vous, vraiment!

Attention à l’utilisation de variables intermédiaires:

let onair:String = Player.shared.getName()

Les String en Swift sont des struct, l’allocation créé une copie. Si ton Player change de name, onair gardera elle sa valeur originale.

Oui, je crois que c’est en parti ce qui m’est arrivé, du coup, pas de variable dans mon code?
Il vaut mieux que j’interroge ma class Player.shared?

Je pense que c’est mieux, et c’est d’autant plus facile que c’est un singleton.

L’autre solution serait d’avoir une variable qui contient ton instance de Player, si ce n’était pas un singleton.