Hallo zusammen,
eine meiner Apps erzeugte einen unerwarteten Crash nachdem ich mit Xcode 13.4 eine neue Version veröffentlichte ... und ich bin auf der Suche nach einer Erklärung:
An einer Stelle rufe ich - noch mit Objective-C - einen MFMailComposeViewController auf, welcher eine Datei vom iCloud-Drive anhängen soll. Daher benötige ich einen Block für's koordinierte Lesen, der eigentlich so aussehen sollte:
Alles anzeigen
Leider führte das früher zu einer Compiler-Warning
Alles anzeigen
Das Ganze lief jahrelang. Nun crashte die App hier und ich stellte fest, dass der ursprüngliche - mir auch korrekt erscheinende - Code keine Warnung mehr erzeugt. Eigentlich konnte es auch m. E. keinen Retain-Cycle geben, da der MailCompose-VC auch nur so lange leben kann, wie der aufrufende VC. Oder was verstehe ich falsch?
Um die Verwirrung komplett zu machen, besteht das gleiche Problem - die ursprüngliche Warnung und nun der Crash - auch bei Blöcken eines UIAlertControllers mit einem Text-Feld. Dort reicht self jedoch nicht, aber der (meines Wissens unsichere) Weg über
Ich bin maximal verwirrt und befürchte die nächste Falle in Zukunft, auch wenn die App jetzt läuft.
Wie geht ihr mit der obigen Compiler-Meldung um, wenn ihr in einem Block eine Referenz auf das aufrufende Objekt benötigt (bei mir MailCompose- bzw. TextField-Delegate? Und wieso sollte ich "__unsafe_unretained" verwenden, wenn gerade dort doch die Gefahr eines "in die Walachei"-zeigenden Pointers besteht?
Für jede Erklärung dankbar, Mattes
eine meiner Apps erzeugte einen unerwarteten Crash nachdem ich mit Xcode 13.4 eine neue Version veröffentlichte ... und ich bin auf der Suche nach einer Erklärung:
An einer Stelle rufe ich - noch mit Objective-C - einen MFMailComposeViewController auf, welcher eine Datei vom iCloud-Drive anhängen soll. Daher benötige ich einen Block für's koordinierte Lesen, der eigentlich so aussehen sollte:
Quellcode
- if ([MFMailComposeViewController canSendMail])
- {
- [...]
- NSFileCoordinator *coordinator = [NSFileCoordinator new];
- [coordinator coordinateReadingItemAtURL:mailURL options:NSFileCoordinatorReadingWithoutChanges error:nil byAccessor:^(NSURL *url)
- {
- MFMailComposeViewController *mailController = [[MFMailComposeViewController alloc] init];
- [mailController setMailComposeDelegate:self];
- [...]
- }];
- }
Capturing 'self' strongly in this block is likely to lead to a retain cycle
. Um dieses Problem zu vermeiden, nutzte ich eine schwache Referenz auf beim Zuweisen des Delegates:Quellcode
- if ([MFMailComposeViewController canSendMail])
- {
- [...]
- __weak typeof(self) weakSelf = self;
- NSFileCoordinator *coordinator = [NSFileCoordinator new];
- [coordinator coordinateReadingItemAtURL:mailURL options:NSFileCoordinatorReadingWithoutChanges error:nil byAccessor:^(NSURL *url)
- {
- MFMailComposeViewController *mailController = [[MFMailComposeViewController alloc] init];
- [mailController setMailComposeDelegate:weakSelf];
- [...]
- }];
- }
Um die Verwirrung komplett zu machen, besteht das gleiche Problem - die ursprüngliche Warnung und nun der Crash - auch bei Blöcken eines UIAlertControllers mit einem Text-Feld. Dort reicht self jedoch nicht, aber der (meines Wissens unsichere) Weg über
__unsafe_unretained
funktioniert.Ich bin maximal verwirrt und befürchte die nächste Falle in Zukunft, auch wenn die App jetzt läuft.
Wie geht ihr mit der obigen Compiler-Meldung um, wenn ihr in einem Block eine Referenz auf das aufrufende Objekt benötigt (bei mir MailCompose- bzw. TextField-Delegate? Und wieso sollte ich "__unsafe_unretained" verwenden, wenn gerade dort doch die Gefahr eines "in die Walachei"-zeigenden Pointers besteht?
Für jede Erklärung dankbar, Mattes
Diese Seite bleibt aus technischen Gründen unbedruckt.