فهرست منبع

library: fix KVC related pseudo-random crashes because we didn't remove the observers on dealloc, so observed objects tried to access nil observers

Felix Paul Kühne 11 سال پیش
والد
کامیت
e083c6c23b
2فایلهای تغییر یافته به همراه137 افزوده شده و 106 حذف شده
  1. 68 52
      Sources/VLCPlaylistCollectionViewCell.m
  2. 69 54
      Sources/VLCPlaylistTableViewCell.m

+ 68 - 52
Sources/VLCPlaylistCollectionViewCell.m

@@ -27,6 +27,11 @@
 
 @implementation VLCPlaylistCollectionViewCell
 
+- (void)dealloc
+{
+    [self _removeObserver];
+}
+
 - (void)awakeFromNib
 {
     if (SYSTEM_RUNS_IOS7_OR_LATER) {
@@ -87,66 +92,77 @@
     [self _updatedDisplayedInformationForKeyPath:keyPath];
 }
 
+- (void)_removeObserver
+{
+    if ([_mediaObject isKindOfClass:[MLLabel class]])
+        [_mediaObject removeObserver:self forKeyPath:@"name"];
+    else if ([_mediaObject isKindOfClass:[MLShow class]])
+        [_mediaObject removeObserver:self forKeyPath:@"episodes"];
+    else if ([_mediaObject isKindOfClass:[MLShowEpisode class]]) {
+        [_mediaObject removeObserver:self forKeyPath:@"name"];
+        [_mediaObject removeObserver:self forKeyPath:@"files"];
+        [_mediaObject removeObserver:self forKeyPath:@"artworkURL"];
+        [_mediaObject removeObserver:self forKeyPath:@"unread"];
+    } else if ([_mediaObject isKindOfClass:[MLAlbum class]]) {
+        [_mediaObject removeObserver:self forKeyPath:@"name"];
+        [_mediaObject removeObserver:self forKeyPath:@"tracks"];
+    } else if ([_mediaObject isKindOfClass:[MLFile class]]) {
+        [_mediaObject removeObserver:self forKeyPath:@"computedThumbnail"];
+        [_mediaObject removeObserver:self forKeyPath:@"lastPosition"];
+        [_mediaObject removeObserver:self forKeyPath:@"duration"];
+        [_mediaObject removeObserver:self forKeyPath:@"fileSizeInBytes"];
+        [_mediaObject removeObserver:self forKeyPath:@"title"];
+        [_mediaObject removeObserver:self forKeyPath:@"thumbnailTimeouted"];
+        [_mediaObject removeObserver:self forKeyPath:@"unread"];
+        [_mediaObject removeObserver:self forKeyPath:@"albumTrackNumber"];
+        [_mediaObject removeObserver:self forKeyPath:@"album"];
+        [_mediaObject removeObserver:self forKeyPath:@"artist"];
+        [_mediaObject removeObserver:self forKeyPath:@"genre"];
+        [(MLFile*)_mediaObject didHide];
+    }
+}
+
+- (void)_addObserver
+{
+    if ([_mediaObject isKindOfClass:[MLLabel class]])
+        [_mediaObject addObserver:self forKeyPath:@"name" options:0 context:nil];
+    else if ([_mediaObject isKindOfClass:[MLShow class]])
+        [_mediaObject addObserver:self forKeyPath:@"episodes" options:0 context:nil];
+    else if ([_mediaObject isKindOfClass:[MLShowEpisode class]]) {
+        [_mediaObject addObserver:self forKeyPath:@"name" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"files" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"artworkURL" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"unread" options:0 context:nil];
+    } else if ([_mediaObject isKindOfClass:[MLAlbum class]]) {
+        [_mediaObject addObserver:self forKeyPath:@"name" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"tracks" options:0 context:nil];
+    } else if ([_mediaObject isKindOfClass:[MLFile class]]) {
+        [_mediaObject addObserver:self forKeyPath:@"computedThumbnail" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"lastPosition" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"duration" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"fileSizeInBytes" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"title" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"thumbnailTimeouted" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"unread" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"albumTrackNumber" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"album" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"artist" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"genre" options:0 context:nil];
+        [(MLFile*)_mediaObject willDisplay];
+    }
+}
+
 - (void)setMediaObject:(MLFile *)mediaObject
 {
     if (_mediaObject != mediaObject) {
-        if ([_mediaObject isKindOfClass:[MLLabel class]]) {
-            [_mediaObject removeObserver:self forKeyPath:@"name"];
-        } else if ([_mediaObject isKindOfClass:[MLShow class]])
-            [_mediaObject removeObserver:self forKeyPath:@"episodes"];
-        else if ([_mediaObject isKindOfClass:[MLShowEpisode class]]) {
-            [_mediaObject removeObserver:self forKeyPath:@"name"];
-            [_mediaObject removeObserver:self forKeyPath:@"files"];
-            [_mediaObject removeObserver:self forKeyPath:@"artworkURL"];
-            [_mediaObject removeObserver:self forKeyPath:@"unread"];
-        } else if ([_mediaObject isKindOfClass:[MLAlbum class]]) {
-            [_mediaObject removeObserver:self forKeyPath:@"name"];
-            [_mediaObject removeObserver:self forKeyPath:@"tracks"];
-        } else if ([_mediaObject isKindOfClass:[MLFile class]]) {
-            [_mediaObject removeObserver:self forKeyPath:@"computedThumbnail"];
-            [_mediaObject removeObserver:self forKeyPath:@"lastPosition"];
-            [_mediaObject removeObserver:self forKeyPath:@"duration"];
-            [_mediaObject removeObserver:self forKeyPath:@"fileSizeInBytes"];
-            [_mediaObject removeObserver:self forKeyPath:@"title"];
-            [_mediaObject removeObserver:self forKeyPath:@"thumbnailTimeouted"];
-            [_mediaObject removeObserver:self forKeyPath:@"unread"];
-            [_mediaObject removeObserver:self forKeyPath:@"albumTrackNumber"];
-            [_mediaObject removeObserver:self forKeyPath:@"album"];
-            [_mediaObject removeObserver:self forKeyPath:@"artist"];
-            [_mediaObject removeObserver:self forKeyPath:@"genre"];
-            [(MLFile*)_mediaObject didHide];
-        }
+
+        [self _removeObserver];
 
         _mediaObject = mediaObject;
         // prevent the cell from recycling the current snap for random contents
         self.thumbnailView.image = nil;
 
-        if ([_mediaObject isKindOfClass:[MLLabel class]]) {
-            [_mediaObject addObserver:self forKeyPath:@"name" options:0 context:nil];
-        } else if ([_mediaObject isKindOfClass:[MLShow class]])
-            [_mediaObject addObserver:self forKeyPath:@"episodes" options:0 context:nil];
-        else if ([_mediaObject isKindOfClass:[MLShowEpisode class]]) {
-            [_mediaObject addObserver:self forKeyPath:@"name" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"files" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"artworkURL" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"unread" options:0 context:nil];
-        } else if ([_mediaObject isKindOfClass:[MLAlbum class]]) {
-            [_mediaObject addObserver:self forKeyPath:@"name" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"tracks" options:0 context:nil];
-        } else if ([_mediaObject isKindOfClass:[MLFile class]]) {
-            [_mediaObject addObserver:self forKeyPath:@"computedThumbnail" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"lastPosition" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"duration" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"fileSizeInBytes" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"title" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"thumbnailTimeouted" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"unread" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"albumTrackNumber" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"album" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"artist" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"genre" options:0 context:nil];
-            [(MLFile*)_mediaObject willDisplay];
-        }
+        [self _addObserver];
     }
 
     [self _updatedDisplayedInformationForKeyPath:nil];

+ 69 - 54
Sources/VLCPlaylistTableViewCell.m

@@ -26,6 +26,11 @@
 
 @implementation VLCPlaylistTableViewCell
 
+- (void)dealloc
+{
+    [self _removeObserver];
+}
+
 + (VLCPlaylistTableViewCell *)cellWithReuseIdentifier:(NSString *)ident
 {
     NSArray *nibContentArray;
@@ -46,68 +51,78 @@
     [self _updatedDisplayedInformationForKeyPath:keyPath];
 }
 
+- (void)_removeObserver
+{
+    if ([_mediaObject isKindOfClass:[MLLabel class]]) {
+        [_mediaObject removeObserver:self forKeyPath:@"files"];
+        [_mediaObject removeObserver:self forKeyPath:@"name"];
+    } else if ([_mediaObject isKindOfClass:[MLShow class]])
+        [_mediaObject removeObserver:self forKeyPath:@"episodes"];
+    else if ([_mediaObject isKindOfClass:[MLShowEpisode class]]) {
+        [_mediaObject removeObserver:self forKeyPath:@"name"];
+        [_mediaObject removeObserver:self forKeyPath:@"files"];
+        [_mediaObject removeObserver:self forKeyPath:@"artworkURL"];
+        [_mediaObject removeObserver:self forKeyPath:@"unread"];
+    } else if ([_mediaObject isKindOfClass:[MLAlbum class]]) {
+        [_mediaObject removeObserver:self forKeyPath:@"name"];
+        [_mediaObject removeObserver:self forKeyPath:@"tracks"];
+    } else if ([_mediaObject isKindOfClass:[MLFile class]]) {
+        [_mediaObject removeObserver:self forKeyPath:@"computedThumbnail"];
+        [_mediaObject removeObserver:self forKeyPath:@"lastPosition"];
+        [_mediaObject removeObserver:self forKeyPath:@"duration"];
+        [_mediaObject removeObserver:self forKeyPath:@"fileSizeInBytes"];
+        [_mediaObject removeObserver:self forKeyPath:@"title"];
+        [_mediaObject removeObserver:self forKeyPath:@"thumbnailTimeouted"];
+        [_mediaObject removeObserver:self forKeyPath:@"unread"];
+        [_mediaObject removeObserver:self forKeyPath:@"albumTrackNumber"];
+        [_mediaObject removeObserver:self forKeyPath:@"album"];
+        [_mediaObject removeObserver:self forKeyPath:@"artist"];
+        [_mediaObject removeObserver:self forKeyPath:@"genre"];
+        [(MLFile*)_mediaObject didHide];
+    }
+}
+
+- (void)_addObserver
+{
+    if ([_mediaObject isKindOfClass:[MLLabel class]]) {
+        [_mediaObject addObserver:self forKeyPath:@"files" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"name" options:0 context:nil];
+    } else if ([_mediaObject isKindOfClass:[MLShow class]])
+        [_mediaObject addObserver:self forKeyPath:@"episodes" options:0 context:nil];
+    else if ([_mediaObject isKindOfClass:[MLShowEpisode class]]) {
+        [_mediaObject addObserver:self forKeyPath:@"name" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"files" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"artworkURL" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"unread" options:0 context:nil];
+    } else if ([_mediaObject isKindOfClass:[MLAlbum class]]) {
+        [_mediaObject addObserver:self forKeyPath:@"name" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"tracks" options:0 context:nil];
+    } else if ([_mediaObject isKindOfClass:[MLFile class]]) {
+        [_mediaObject addObserver:self forKeyPath:@"computedThumbnail" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"lastPosition" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"duration" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"fileSizeInBytes" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"title" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"thumbnailTimeouted" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"unread" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"albumTrackNumber" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"album" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"artist" options:0 context:nil];
+        [_mediaObject addObserver:self forKeyPath:@"genre" options:0 context:nil];
+        [(MLFile*)_mediaObject willDisplay];
+    }
+}
+
 - (void)setMediaObject:(MLFile *)mediaObject
 {
     if (_mediaObject != mediaObject) {
-        if ([_mediaObject isKindOfClass:[MLLabel class]]) {
-            [_mediaObject removeObserver:self forKeyPath:@"files"];
-            [_mediaObject removeObserver:self forKeyPath:@"name"];
-        } else if ([_mediaObject isKindOfClass:[MLShow class]])
-            [_mediaObject removeObserver:self forKeyPath:@"episodes"];
-        else if ([_mediaObject isKindOfClass:[MLShowEpisode class]]) {
-            [_mediaObject removeObserver:self forKeyPath:@"name"];
-            [_mediaObject removeObserver:self forKeyPath:@"files"];
-            [_mediaObject removeObserver:self forKeyPath:@"artworkURL"];
-            [_mediaObject removeObserver:self forKeyPath:@"unread"];
-        } else if ([_mediaObject isKindOfClass:[MLAlbum class]]) {
-            [_mediaObject removeObserver:self forKeyPath:@"name"];
-            [_mediaObject removeObserver:self forKeyPath:@"tracks"];
-        } else if ([_mediaObject isKindOfClass:[MLFile class]]) {
-            [_mediaObject removeObserver:self forKeyPath:@"computedThumbnail"];
-            [_mediaObject removeObserver:self forKeyPath:@"lastPosition"];
-            [_mediaObject removeObserver:self forKeyPath:@"duration"];
-            [_mediaObject removeObserver:self forKeyPath:@"fileSizeInBytes"];
-            [_mediaObject removeObserver:self forKeyPath:@"title"];
-            [_mediaObject removeObserver:self forKeyPath:@"thumbnailTimeouted"];
-            [_mediaObject removeObserver:self forKeyPath:@"unread"];
-            [_mediaObject removeObserver:self forKeyPath:@"albumTrackNumber"];
-            [_mediaObject removeObserver:self forKeyPath:@"album"];
-            [_mediaObject removeObserver:self forKeyPath:@"artist"];
-            [_mediaObject removeObserver:self forKeyPath:@"genre"];
-            [(MLFile*)_mediaObject didHide];
-        }
+        [self _removeObserver];
 
         _mediaObject = mediaObject;
         // prevent the cell from recycling the current snap for random contents
         self.thumbnailView.image = nil;
 
-        if ([_mediaObject isKindOfClass:[MLLabel class]]) {
-            [_mediaObject addObserver:self forKeyPath:@"files" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"name" options:0 context:nil];
-        } else if ([_mediaObject isKindOfClass:[MLShow class]])
-            [_mediaObject addObserver:self forKeyPath:@"episodes" options:0 context:nil];
-        else if ([_mediaObject isKindOfClass:[MLShowEpisode class]]) {
-            [_mediaObject addObserver:self forKeyPath:@"name" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"files" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"artworkURL" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"unread" options:0 context:nil];
-        } else if ([_mediaObject isKindOfClass:[MLAlbum class]]) {
-            [_mediaObject addObserver:self forKeyPath:@"name" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"tracks" options:0 context:nil];
-        } else if ([_mediaObject isKindOfClass:[MLFile class]]) {
-            [_mediaObject addObserver:self forKeyPath:@"computedThumbnail" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"lastPosition" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"duration" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"fileSizeInBytes" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"title" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"thumbnailTimeouted" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"unread" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"albumTrackNumber" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"album" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"artist" options:0 context:nil];
-            [_mediaObject addObserver:self forKeyPath:@"genre" options:0 context:nil];
-            [(MLFile*)_mediaObject willDisplay];
-        }
+        [self _addObserver];
     }
 
     [self _updatedDisplayedInformationForKeyPath:nil];