Delegate aus Asynchronem completionHandler?

  • Delegate aus Asynchronem completionHandler?

    Hallo nochmals,
    ich versuche aus dem completionhandler einer CloudKit Abfrage ein delegate zu senden.
    Leider erfolglos.
    Wenn ich das Delegate nicht im completionhandler der asynchronen Abfrage sende wird es ausgeführt.

    Kann ich kein delegate aus einer asynchronen Methode heraus feuern?
  • Wieso verwendest du nicht callbacks wie es überall in Cocoa üblich ist?
    Aus deinem Nickname schließe ich daraus, dass du im .NET Umfeld tätig, so wie ich.
    Delegates und asynchrone Abfragen laufen in .NET ein wenig anders. Vor allem letzteres ist imho in .NET eleganter.
  • Vielleicht nochmal etwas genauer.
    Ich habe eine Klasse CloudKitManager() in der ich meine CloudKit Logik verarbeite.

    Um hier ein alert zu versenden habe ich ein delegate aufgesetzt:

    Quellcode

    1. protocol AlertPresenterDelegate: class{
    2. func presentAlert(sender:CloudKitManager, title:String, message:String)
    3. }



    In meiner CloudKitManager Klasse habe ich eine Variable

    Quellcode

    1. weak var delegate:AlertPresenterDelegate?
    und die Methode die CloudKit subscriptions abonniert um bei Änderungen PushNachrichten zu empfangen:

    Quellcode

    1. /**
    2. **Subscribes to CloudKit Record changes**
    3. - parameter recordType: - String: *Name of the Record as String (equal to a table name)*
    4. - parameter predikateKey: - String: *Name of the Key for subscription (equal to column name)*
    5. - parameter predicate: - String: *Predicate to filter subscriptions (equal to cell value)*
    6. - parameter subscriptionOptions: - CKSubscriptionOptions: *Options when the subscription shoulc fire*
    7. - parameter pushalertBody: - String: *The Push Notification Message*
    8. - remark:
    9. Subscribes to changes of records in CloudKit Services.
    10. In this app all subscriptions should be filtered by predikateKey: id and predicate equal to the userId the app are subscribed to.
    11. */
    12. func subscribeToCloudKitChanges(recordType:String, predicateKey:String, predicate:String, subscriptionOption:CKSubscriptionOptions, pushalertBody:String) {
    13. let predicate = NSPredicate(format: "\(predicateKey) = %@", predicate)
    14. let subscription = CKSubscription(recordType: recordType, predicate: predicate, options: subscriptionOption)
    15. let notificationInfo = CKNotificationInfo()
    16. notificationInfo.alertBody = pushalertBody
    17. notificationInfo.shouldBadge = false
    18. notificationInfo.soundName = UILocalNotificationDefaultSoundName
    19. subscription.notificationInfo = notificationInfo
    20. publicDB!.saveSubscription(subscription, completionHandler: ({returnRecord, error in
    21. if let err = error {
    22. print(err.localizedDescription)
    23. let title:String = eLocalization.Alert_CloudKit_Subscription_Error_Title.rawValue.localized
    24. let message:String = err.localizedDescription
    25. self.delegate?.presentAlert(self, title: title, message: message)
    26. }
    27. else { dispatch_async(dispatch_get_main_queue()) {
    28. print("CloudKit subscription success")
    29. let title:String = eLocalization.Alert_CloudKit_Subscription_Success_Header.rawValue.localized
    30. let message:String = eLocalization.Alert_CloudKit_Subscription_Success_Message.rawValue.localized + " \(predicate)"
    31. self.delegate?.presentAlert(self, title: title, message: message)
    32. }
    33. }
    34. }))
    35. }
    Alles anzeigen

    in meinem View Controller nutze ich die CloudKitManager Klasse in der ich auch mein Delegate Protocol implementiere

    Quellcode

    1. class SubscribeAsObserverVC:UIViewController, AlertPresenterDelegate{
    2. var ckmngr = CloudKitManager()
    3. override func viewDidLoad() {
    4. super.viewDidLoad()
    5. ckmngr.delegate = self
    6. }
    7. func presentAlert(sender: CloudKitManager, title: String, message: String) {
    8. let alert = UIAlertController(title: title, message: message, preferredStyle: .Alert)
    9. alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: { (UIAlertAction) -> Void in }))
    10. presentViewController(alert, animated: true, completion: nil)
    11. }
    12. }
    Alles anzeigen
    wo ist der Fehler?
  • macmoonshine schrieb:

    Hast du getestet, ob self.delegate? auch nicht nil ist? Eine weitere Fehlermöglichkeit könnte sein, dass der Completion-Handler nicht im Main-Thread läuft.
    Von letzterem gehe ich fast aus... Dann passiert halt gerne mal nichts. Eventuell hilft es ja dementsprechend, den Aufruf des Delegates im mainThread auszuführen... Bspw. mit dispatch_sync.
  • Danke nochmals für die Hinweise.
    Die haben mich auf die richtige Fährte geführt.
    Das Problem bestand darin, dass ich das Delegate = self an der falschen Stelle gesetzt habe.

    In meinem Thread habe ich ein CloudKitManager Instanz gehabt.
    Hier habe ich dieser Instanz auch das Delegate zugewiesen.
    Aber dummer Weise habe ich in einer TableViewCell nochmal eine Instanz erzeugt und dort natürlich nicht das Delegate installiert.

    Auf jetzt übergebe ich einfach die CloudKitManager Instanz während ich die TableViewCells konfiguriere.

    Es war also immer das Delegate nil.

    :thumbsup: