Frage von einem Anfänger: Was hat es mit dem sharedInstance aufsich ?

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • da wird nur eine Instance angelegt und die immer zurück gegeben
    das machen viele weil sie diese Instance dann als GLOBALE variable benutzen um da überall drauf zugreifen zu können
    (kannst auch mal nach Singleton suchen) ich hab das böse wort genannt und es geht los

    in 99% der Fälle wo es benutzt wird ist es eigentlich "unsauber" das so zu machen und es gibt in den Fällen wahrscheinlich mehrere und bessere Möglichkeiten das zu machen

    für tiefergehende Details musst du nur ein paar Beiträge warten dann geht hier nämlich die große Diskussion los ;)
    Ich weiß nicht immer wovon ich rede aber ich weiß das ich Recht habe. :saint:
  • JamesHook schrieb:

    Wie sieht das handling dazu aus ? Worin liegt der Unterschied zum aus einer Klasse ein Object erstellen klassisch im Controller?

    Beispiel aus der Praxis: Du hast ein Dokument-basiertes Programm unter OS X.

    NSApplication.sharedApplication() ist eine sharedInstance/ Singleton. Du hast in Deinem Programm immer nur eine Instanz Deines Programms. Das kann es nur einmal geben.

    Du hast mehrere Dokumente in Deinem Programm. Also hast Du auch mehere Instazen von NSDocumentController, die diese verschiedenen Dokumente managen.
    Das iPhone sagt: "Zum Antworten streichen". Wie? Echt Jetzt? Muß ich erst die Wohnung streichen!?
  • gandhi schrieb:

    torquato schrieb:

    Also hast Du auch mehere Instazen von NSDocumentController, die diese verschiedenen Dokumente managen.
    Na ja, das eben gerade nicht. Du hast eine Instanz von NSDocumentController, der sich um mehrere NSDocument-Instanzen kümmert.
    Ja, stimmt natürlich. Habe ich aus dem Gedächtnis mit den verschiedenen NSDocuments verwechselt. Dann halt die verschienenen Instanzen eines NSViewController, der für die GUI der verschiedenen Dokumente zuständig ist...
    Das iPhone sagt: "Zum Antworten streichen". Wie? Echt Jetzt? Muß ich erst die Wohnung streichen!?
  • JamesHook schrieb:

    Wie sieht das handling dazu aus ?
    Ein echtes Singleton ist ein bisschen knifflig, weil du dafür die freie Objekterzeugung sperren musst. Die Implementierung der Klassenmethode ist hingegen in der Regel einfach. Thread-Sicherheit kannst du über dispatch_once() erreichen. Gibt's als fertiges Makro in Xcode.

    JamesHook schrieb:

    Worin liegt der Unterschied zum aus einer Klasse ein Object erstellen klassisch im Controller?
    Das hat nichts mit klassisch, modern oder s zu tun. Das ist ein Entwurfsmuster. Bestimme Dinge gibt es eben nur einmal.
    „Meine Komplikation hatte eine Komplikation.“
  • Ich versuche mich jetzt auch gerade an einem Beispiel. Soweit ich es verstanden habe will man mit dem Singleton nur sicherstellen das man immer global auf die selbe instanz zugreifen kann und diese nur einmal vorhanden ist.

    Ich schreibe gerade einen Code für ein Bluetooth Modul, die Klasse Bluetooth_Manager handelt die ganze Communication. Und NRFManager die Bluetooth Communication diese besitzt Delegate Methoden.
    Bluetooth_Manager sollte es später nur einmal geben und ich will auf diese Instanz von verschiedenen Views zugreifen das ganze wäre hier also wenn ich es richtig verstanden habe mit Singleton zu lösen ?

    Quellcode

    1. class Bluetooth_Manager:NRFManager , NRFManagerDelegate {
    2. //privat properties
    3. private var Manager = NRFManager()
    4. private var handle = handleTyps.DFFI2()
    5. private var request = requestTyps.DFFI2()
    6. private var logData = LogData()
    7. //global properties
    8. enum ECMTyp {
    9. case DDFI2
    10. case DDFI3
    11. }
    12. init(){
    13. Manager = NRFManager(delegate: NRFManagerDelegate)
    14. Manager.autoConnect = false
    15. }
    16. func Typ(Ecm:ECMTyp){
    17. switch Ecm {
    18. case .DDFI2: break
    19. handle = handleTyps.DFFI2()
    20. request = requestTyps.DFFI2()
    21. logData.Typ(.DDFI2)
    22. case .DDFI3: break
    23. }
    24. }
    25. /*
    26. func request()
    27. { if Manager.connectionStatus == .Connected {
    28. var theData:[UInt8] = [0x01, 0x00, 0x42, 0x02, 0xFF, 0x02, 0x43, 0x03, 0xE8]
    29. let data = NSData(bytes: theData as [UInt8], length: 9)
    30. self.Manager.writeData(data)
    31. print("send")
    32. }
    33. }
    34. */
    35. // NRFManagerDelegate methods
    36. func nrfDidConnect(nrfManager:NRFManager)
    37. {
    38. print("Connected")
    39. }
    40. func nrfDidDisconnect(nrfManager:NRFManager)
    41. {
    42. print("Disconnected")
    43. }
    44. func nrfReceivedData(nrfManager:NRFManager, data: NSData?, string: String?) {
    45. // exist data ?
    46. guard let string = string else{
    47. print("file error")
    48. return}
    49. // String to Array of UInt8
    50. let binArray = [UInt8](string.utf8)
    51. // Check the frame of Stream
    52. if !handle.StreamCheckRoutine(binArray) {
    53. // <-- Neue Anfrage senden
    54. print("frame incomplet")
    55. return}
    56. switch handle.Response(binArray) {
    57. case .Runtime:
    58. logData.addSensorData([])
    59. case .Acknowledge: break
    60. case .Version: break
    61. case .Sucesss: break
    62. case .Repeat: break
    63. case .Error: break
    64. default: break
    65. }
    66. print(binArray)
    67. }
    68. func RSSI() -> String{
    69. return String(Manager.rssi)
    70. }
    71. }
    Alles anzeigen
  • JamesHook schrieb:

    Bluetooth_Manager sollte es später nur einmal geben und ich will auf diese Instanz von verschiedenen Views zugreifen das ganze wäre hier also wenn ich es richtig verstanden habe mit Singleton zu lösen ?
    Kann man so machen, muss man aber nicht. Singletons sind Pattern und Antipattern in einem. Singletons erzeugen meist sehr starke Abhängigkeiten im Code und ihre Verwendung verbreitet sich wie die Pest im Code, so dass am Ende sogar View- und Modellklassen davon befallen sind. Falls Homöopathie irgendwo einen Sinn ergibt, dann ist das beim Einsatz von Singletons. ;)

    Ich würde zuerst mal überlegen, ob es deinen Bluetooth-Manager tatsächlich nur einmal geben kann. Was ist, wenn beispielsweise deine App auf einem Gerät mit zwei oder mehr Bluetooth-Schnittstellen läuft? Wie viele andere Controller greifen auf den Bluetooth-Manager zu? Kann es Varianten (z. B. für WLAN, IR, Telepathie) von dem Manager geben?
    „Meine Komplikation hatte eine Komplikation.“
  • Hardwaremanager halte ich tatsächlich für ein gutes Beispiel für Singletons (mit einigen Bedenken, die schon Macmoonshine genannt hat). Bei mir ist das Singleton dann allerdings eine zentrale Instanz, die sich um Discovery, Erzeugung und den Verbindungsstatus der einzelnen verbundenen Geräte kümmert - nicht die einzelnen Geräte selbst. In deinem Code sieht es so aus, als ob das Singleton ein Gerät selbst repräsentiert. Das würde ich nicht machen, selbst wenn das Programm immer nur mit einem Gerät zur Zeit kommuniziert. Rein konzeptionell gibt es nicht nur ein Gerät auf der Welt.
    Multigrad - 360°-Produktfotografie für den Mac
  • Der Bluetooth Manger kann sich mit verschiede BTLE Geräten verbinden , jedes Gerät unterscheidet sich minimal oder komplett von den anderen. Die Telegramme und Funktionen der Module können unterschiedlich sein.
    Im Bluetooth modul kann die Einstellung vorgenommen werden was gerade angeschlossen ist. Dazu hab ich eine Struct angelegt mit den verschiedenen Geräten DFFI2 DFFI3 als Beispiel , da gibt es den RequestTyp und den HandleTyp und dann kommen noch zwei. Ein Tabbarview passt sich dem ausgewählten Gerät an.

    Daher dachte ich mir der Singleton wäre hier eine feine Sache. Gestern hatte ich gleich noch festgestellt das ich noch keine Lösung habe bzw ich nicht weiß wie ich das mit dem Delegate vom NRF Manager hinbekomme da NRF Manager erst in einer anderen Klasse benützt wird.

    Gruß
  • Ja da hast du recht

    Quellcode

    1. init(Ecm:ECMTyp){
    2. Manager = NRFManager(delegate:self)
    3. Manager.autoConnect = false
    4. switch Ecm {
    5. case .DDFI2:
    6. handle = handleTyps.DFFI2()
    7. request = requestTyps.DFFI2()
    8. logData.Typ(.DDFI2)
    9. case .DDFI3:
    10. break
    11. }
    12. }
    Alles anzeigen
    Dann stehe ich aber vor zwei Problemen, wie kann ich global dann auf zb die ankommenden Daten zugreifen ich habe meherer Views die sich daraus Daten holen könnten. Das zweite Problem wie funktioniert das mit den Delegats Methoden wenn ich eine Klasse mit Delegats in einer anderen Klasse brauche es scheitert schon an der Initialisierung ich bekomme die Meldung Zeile 2 used before super init call .
  • JamesHook schrieb:

    Dann stehe ich aber vor zwei Problemen, wie kann ich global dann auf zb die ankommenden Daten zugreifen ich habe meherer Views die sich daraus Daten holen könnten.
    Du kannst das Manager-Objekt auch zum nächsten Viewcontroller über Properties weiterreichen.

    JamesHook schrieb:

    Initialisierung ich bekomme die Meldung Zeile 2 used before super init call .
    Da fehlt ja auch der Aufruf des Initializers der Oberklasse. ;)
    „Meine Komplikation hatte eine Komplikation.“
  • JamesHook schrieb:

    es scheitert schon an der Initialisierung ich bekomme die Meldung Zeile 2 used before super init call .

    Bevor man self in Swift verwenden kann, _müssen_ alle properties initialisiert sein.

    1.) Alle properties der Klasse initialisieren
    2.) Die Superclass initialisieren
    3.) Jetzt darf man self verwenden.

    Viel schwerwiegender scheint mir allerdings die Frage zu sein, wieso Du eine Unterklasse erstellst, um dann die Oberklasse als eine Property zu verwenden. Wieso am Ende des Initializers nicht einfach: self.delegate = self?
    Das iPhone sagt: "Zum Antworten streichen". Wie? Echt Jetzt? Muß ich erst die Wohnung streichen!?
  • torquato schrieb:

    JamesHook schrieb:

    es scheitert schon an der Initialisierung ich bekomme die Meldung Zeile 2 used before super init call .
    Bevor man self in Swift verwenden kann, _müssen_ alle properties initialisiert sein.

    1.) Alle properties der Klasse initialisieren
    2.) Die Superclass initialisieren
    3.) Jetzt darf man self verwenden.

    Viel schwerwiegender scheint mir allerdings die Frage zu sein, wieso Du eine Unterklasse erstellst, um dann die Oberklasse als eine Property zu verwenden. Wieso am Ende des Initializers nicht einfach: self.delegate = self?
    Erst mal vielen Danke für eure Antworten, aber jetzt hab ich den Faden verloren.
    Die Unterklasse ist NRFManager auf die initialisieren dieser klasse greife ich mit super.init() und als erstes muss ich die Unterklasse initialiseren....

    Quellcode

    1. init(Ecm:ECMTyp){
    2. super.init(delegate: ???? )
    3. super.autoConnect = false
    4. switch Ecm {
    5. case .DDFI2:
    6. handle = handleTyps.DFFI2()
    7. request = requestTyps.DFFI2()
    8. logData.Typ(.DDFI2)
    9. case .DDFI3:
    10. break
    11. }
    12. }
    Alles anzeigen
    stimmt das soweit ?
  • Nein. Andersrum. Beispiel:

    C-Quellcode

    1. class A {
    2. var a: Int
    3. init(x: Int) {
    4. a = x
    5. }
    6. }
    7. class B: A {
    8. var b: Int
    9. init(y: Int) {
    10. b = y // 1.) alle Properties der eigenen Klasse initialisieren
    11. super.init(x: 2) // 2.) die superklasse initialisieren
    12. print(self.a, self.b) // 3.) jetzt kann man auf self und alle Properties zugreifen
    13. }
    14. }
    Alles anzeigen

    B ist die Subclass (Unterklasse), A ist die Superclass (Oberklasse).
    Das iPhone sagt: "Zum Antworten streichen". Wie? Echt Jetzt? Muß ich erst die Wohnung streichen!?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von torquato ()