[vlc-commits] [Git][videolan/vlc][master] 2 commits: macosx: Prevent retaining of self in views that use async thumbnail fetching

Steve Lhomme (@robUx4) gitlab at videolan.org
Sat Mar 22 10:33:53 UTC 2025



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
fda55ba7 by Claudio Cambra at 2025-03-22T10:19:01+00:00
macosx: Prevent retaining of self in views that use async thumbnail fetching

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
145428b3 by Claudio Cambra at 2025-03-22T10:19:01+00:00
macosx: Set represented play queue item before handling presentation

Fixes a number of issues with thumbnailing and with crashes on view
deletion

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -


11 changed files:

- modules/gui/macosx/library/VLCLibraryCarouselViewItemView.m
- modules/gui/macosx/library/VLCLibraryCollectionViewItem.m
- modules/gui/macosx/library/VLCLibraryCollectionViewMediaItemListSupplementaryDetailView.m
- modules/gui/macosx/library/VLCLibraryCollectionViewMediaItemSupplementaryDetailView.m
- modules/gui/macosx/library/VLCLibraryHeroView.m
- modules/gui/macosx/library/VLCLibraryTableCellView.m
- modules/gui/macosx/library/audio-library/VLCLibraryAlbumTableCellView.m
- modules/gui/macosx/library/media-source/VLCMediaSourceCollectionViewItem.m
- modules/gui/macosx/panels/VLCInformationWindowController.m
- modules/gui/macosx/playqueue/VLCPlayQueueTableCellView.m
- modules/gui/macosx/windows/video/VLCMainVideoViewAudioMediaDecorativeView.m


Changes:

=====================================
modules/gui/macosx/library/VLCLibraryCarouselViewItemView.m
=====================================
@@ -114,11 +114,12 @@
 
     const id<VLCMediaLibraryItemProtocol> actualItem = self.representedItem.item;
 
+    __weak typeof(self) weakSelf = self;
     [VLCLibraryImageCache thumbnailForLibraryItem:actualItem withCompletion:^(NSImage * const thumbnail) {
-        if (self.representedItem.item != actualItem) {
+        if (!weakSelf || weakSelf.representedItem.item != actualItem) {
             return;
         }
-        self.imageView.image = thumbnail;
+        weakSelf.imageView.image = thumbnail;
     }];
 
     self.titleTextField.stringValue = actualItem.displayString;


=====================================
modules/gui/macosx/library/VLCLibraryCollectionViewItem.m
=====================================
@@ -219,12 +219,13 @@ const CGFloat VLCLibraryCollectionViewItemMaximumDisplayedProgress = 0.95;
     self.mediaTitleTextField.stringValue = actualItem.displayString;
     self.secondaryInfoTextField.stringValue = actualItem.primaryDetailString;
 
+    __weak typeof(self) weakSelf = self;
     [VLCLibraryImageCache thumbnailForLibraryItem:actualItem
                                    withCompletion:^(NSImage * const thumbnail) {
-        if (self.representedItem.item != actualItem) {
+        if (!weakSelf || weakSelf.representedItem.item != actualItem) {
             return;
         }
-        self.mediaImageView.image = thumbnail;
+        weakSelf.mediaImageView.image = thumbnail;
     }];
 
     if ([actualItem isKindOfClass:VLCMediaLibraryMediaItem.class]) {


=====================================
modules/gui/macosx/library/VLCLibraryCollectionViewMediaItemListSupplementaryDetailView.m
=====================================
@@ -147,19 +147,17 @@ NSCollectionViewSupplementaryElementKind const VLCLibraryCollectionViewMediaItem
             secondaryActionableDetail ? NSColor.secondaryLabelColor : NSColor.tertiaryLabelColor;
     }
 
+    __weak typeof(self) weakSelf = self; // Prevent retain cycle
     [VLCLibraryImageCache thumbnailForLibraryItem:item withCompletion:^(NSImage * const thumbnail) {
-        if (self.representedItem.item != item) {
+        if (!weakSelf || weakSelf.representedItem.item != item) {
             return;
         }
-        self.artworkImageView.image = thumbnail;
+        weakSelf.artworkImageView.image = thumbnail;
     }];
 
-    __weak typeof(self) weakSelf = self; // Prevent retain cycle
     [_tracksDataSource setRepresentedItem:item withCompletion:^{
-        __strong typeof(self) strongSelf = weakSelf;
-
-        if (strongSelf) {
-            [strongSelf.tableView reloadData];
+        if (weakSelf) {
+            [weakSelf.tableView reloadData];
         }
     }];
 }


=====================================
modules/gui/macosx/library/VLCLibraryCollectionViewMediaItemSupplementaryDetailView.m
=====================================
@@ -186,11 +186,13 @@ NSCollectionViewSupplementaryElementKind const VLCLibraryCollectionViewMediaItem
     self.mediaItemActorsTitleTextField.hidden = self.mediaItemActorsTextField.hidden;
     self.mediaItemActorsTextField.stringValue = actors;
 
+    __weak typeof(self) weakSelf = self;
     [VLCLibraryImageCache thumbnailForLibraryItem:actualItem withCompletion:^(NSImage * const thumbnail) {
-        if (self.representedItem.item != actualItem) {
+        if (!weakSelf || weakSelf.representedItem.item != actualItem) {
             return;
         }
-        self->_mediaItemArtworkImageView.image = thumbnail;
+        VLCLibraryCollectionViewMediaItemSupplementaryDetailView * const strongSelf = weakSelf;
+        strongSelf->_mediaItemArtworkImageView.image = thumbnail;
     }];
 }
 


=====================================
modules/gui/macosx/library/VLCLibraryHeroView.m
=====================================
@@ -65,11 +65,13 @@
     const id<VLCMediaLibraryItemProtocol> actualItem = self.representedItem.item;
     self.titleTextField.stringValue = actualItem.displayString;
     self.detailTextField.stringValue = actualItem.primaryDetailString;
+
+    __weak typeof(self) weakSelf = self;
     [VLCLibraryImageCache thumbnailForLibraryItem:actualItem withCompletion:^(NSImage * const image) {
-        if (self.representedItem.item != actualItem) {
+        if (!weakSelf || weakSelf.representedItem.item != actualItem) {
             return;
         }
-        self.largeImageView.image = image;
+        weakSelf.largeImageView.image = image;
     }];
 }
 


=====================================
modules/gui/macosx/library/VLCLibraryTableCellView.m
=====================================
@@ -81,11 +81,12 @@ NSString * const VLCLibraryTableCellViewIdentifier = @"VLCLibraryTableCellViewId
     self.playInstantlyButton.action = @selector(playMediaItemInstantly:);
     self.playInstantlyButton.target = self;
 
+    __weak typeof(self) weakSelf = self;
     [VLCLibraryImageCache thumbnailForLibraryItem:actualItem withCompletion:^(NSImage * const thumbnail) {
-        if (self.representedItem.item != actualItem) {
+        if (!weakSelf || weakSelf.representedItem.item != actualItem) {
             return;
         }
-        self.representedImageView.image = thumbnail;
+        weakSelf.representedImageView.image = thumbnail;
     }];
 
     if(actualItem.primaryDetailString.length > 0) {
@@ -107,11 +108,13 @@ NSString * const VLCLibraryTableCellViewIdentifier = @"VLCLibraryTableCellViewId
     self.singlePrimaryTitleTextField.hidden = NO;
     self.singlePrimaryTitleTextField.stringValue = _representedInputItem.name;
 
+    __weak typeof(self) weakSelf = self;
     [VLCLibraryImageCache thumbnailForInputItem:self->_representedInputItem withCompletion:^(NSImage * const thumbnail) {
-        if (representedInputItem != self->_representedInputItem) {
+        VLCLibraryTableCellView * const strongSelf = weakSelf;
+        if (!strongSelf || representedInputItem != strongSelf->_representedInputItem) {
             return;
         }
-        self->_representedImageView.image = thumbnail;
+        strongSelf->_representedImageView.image = thumbnail;
     }];
 
     self.trackingView.viewToHide = self.playInstantlyButton;


=====================================
modules/gui/macosx/library/audio-library/VLCLibraryAlbumTableCellView.m
=====================================
@@ -327,14 +327,14 @@ const CGFloat VLCLibraryAlbumTableCellViewDefaultHeight = 168.;
         self.genreNameTextButton.contentTintColor = secondaryActionableDetail ? NSColor.secondaryLabelColor : NSColor.tertiaryLabelColor;
     }
 
+    __weak typeof(self) weakSelf = self;
     [VLCLibraryImageCache thumbnailForLibraryItem:album withCompletion:^(NSImage * const thumbnail) {
-        if (self.representedItem.item != album) {
+        if (!weakSelf || weakSelf.representedItem.item != album) {
             return;
         }
-        self.representedImageView.image = thumbnail;
+        weakSelf.representedImageView.image = thumbnail;
     }];
 
-    __weak typeof(self) weakSelf = self; // Prevent retain cycle
     [_tracksDataSource setRepresentedItem:album withCompletion:^{
         __strong typeof(self) strongSelf = weakSelf;
 


=====================================
modules/gui/macosx/library/media-source/VLCMediaSourceCollectionViewItem.m
=====================================
@@ -138,12 +138,14 @@ NSString *VLCMediaSourceCellIdentifier = @"VLCLibraryCellIdentifier";
     VLCInputItem * const inputItem = _representedInputItem;
     _mediaTitleTextField.stringValue = inputItem.name;
 
+    __weak typeof(self) weakSelf = self;
     [VLCLibraryImageCache thumbnailForInputItem:inputItem
                                  withCompletion:^(NSImage * const thumbnail) {
-        if (self->_representedInputItem != inputItem) {
+        VLCMediaSourceCollectionViewItem * const strongSelf = weakSelf;
+        if (!strongSelf || strongSelf->_representedInputItem != inputItem) {
             return;
         }
-        self->_mediaImageView.image = thumbnail;
+        strongSelf->_mediaImageView.image = thumbnail;
     }];
 
 


=====================================
modules/gui/macosx/panels/VLCInformationWindowController.m
=====================================
@@ -308,6 +308,7 @@ _##field##TextField.delegate = self
 
     NSMutableSet * const artworkMrlSet = NSMutableSet.set;
 
+    __weak typeof(self) weakSelf = self;
     const dispatch_queue_t queue = dispatch_queue_create("vlc_infowindow_libraryitemimg_queue", 0);
     dispatch_async(queue, ^{
         NSMutableArray<NSImage *> * const artworkImages = NSMutableArray.array;
@@ -329,7 +330,7 @@ _##field##TextField.delegate = self
                     dispatch_group_enter(group);
                     [VLCLibraryImageCache thumbnailForLibraryItem:mediaItem
                                                    withCompletion:^(NSImage * const image) {
-                        if (nonMutableInputItems != self.representedInputItems) {
+                        if (!weakSelf || nonMutableInputItems != weakSelf.representedInputItems) {
                             dispatch_group_leave(group);
                             return;
                         }
@@ -380,6 +381,7 @@ _##field##TextField.delegate = self
     NSParameterAssert(representedInputItems.count > 0);
     _representedInputItems = representedInputItems;
 
+    __weak typeof(self) weakSelf = self;
     const dispatch_queue_t queue = dispatch_queue_create("vlc_infowindow_inputitemimg_queue", 0);
     dispatch_async(queue, ^{
         NSMutableArray<NSImage *> * const artworkImages = NSMutableArray.array;
@@ -390,7 +392,7 @@ _##field##TextField.delegate = self
                 dispatch_group_enter(group);
                 [VLCLibraryImageCache thumbnailForInputItem:item
                                              withCompletion:^(NSImage * const image) {
-                    if (representedInputItems != self.representedInputItems) {
+                    if (!weakSelf || representedInputItems != weakSelf.representedInputItems) {
                         dispatch_group_leave(group);
                         return;
                     }


=====================================
modules/gui/macosx/playqueue/VLCPlayQueueTableCellView.m
=====================================
@@ -78,12 +78,15 @@
 
 - (void)setRepresentedPlayQueueItem:(VLCPlayQueueItem *)item
 {
+    _representedPlayQueueItem = item;
+
+    __weak typeof(self) weakSelf = self;
     [VLCLibraryImageCache thumbnailForPlayQueueItem:item withCompletion:^(NSImage * const thumbnail) {
-        if (item != self.representedPlayQueueItem) {
+        if (!weakSelf || item != weakSelf.representedPlayQueueItem) {
             return;
         }
-        self.audioArtworkImageView.image = thumbnail;
-        self.mediaImageView.image = thumbnail;
+        weakSelf.audioArtworkImageView.image = thumbnail;
+        weakSelf.mediaImageView.image = thumbnail;
     }];
 
     const BOOL validArtistString = item.artistName && item.artistName.length > 0;
@@ -119,8 +122,6 @@
     }
 
     self.durationTextField.stringValue = [NSString stringWithTimeFromTicks:item.duration];
-
-    _representedPlayQueueItem = item;
 }
 
 @end


=====================================
modules/gui/macosx/windows/video/VLCMainVideoViewAudioMediaDecorativeView.m
=====================================
@@ -62,12 +62,13 @@
         VLCMain.sharedInstance.playQueueController.playerController;
     VLCInputItem * const currentInputItem = controller.currentMedia;
     if (controller.currentMedia) {
+        __weak typeof(self) weakSelf = self;
         [VLCLibraryImageCache thumbnailForInputItem:currentInputItem
                                      withCompletion:^(NSImage * const thumbnail) {
             if (currentInputItem != controller.currentMedia) {
                 return;
             }
-            [self setCoverArt:thumbnail];
+            [weakSelf setCoverArt:thumbnail];
         }];
     }
 }



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/61cbeec966d2220929d80f3df9d3b444f9593cf8...145428b3125a00014b05054ba64aaba09d9b5780

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/61cbeec966d2220929d80f3df9d3b444f9593cf8...145428b3125a00014b05054ba64aaba09d9b5780
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list