瀏覽代碼

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
 @implementation VLCPlaylistCollectionViewCell
 
 
+- (void)dealloc
+{
+    [self _removeObserver];
+}
+
 - (void)awakeFromNib
 - (void)awakeFromNib
 {
 {
     if (SYSTEM_RUNS_IOS7_OR_LATER) {
     if (SYSTEM_RUNS_IOS7_OR_LATER) {
@@ -87,66 +92,77 @@
     [self _updatedDisplayedInformationForKeyPath:keyPath];
     [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
 - (void)setMediaObject:(MLFile *)mediaObject
 {
 {
     if (_mediaObject != 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;
         _mediaObject = mediaObject;
         // prevent the cell from recycling the current snap for random contents
         // prevent the cell from recycling the current snap for random contents
         self.thumbnailView.image = nil;
         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];
     [self _updatedDisplayedInformationForKeyPath:nil];

+ 69 - 54
Sources/VLCPlaylistTableViewCell.m

@@ -26,6 +26,11 @@
 
 
 @implementation VLCPlaylistTableViewCell
 @implementation VLCPlaylistTableViewCell
 
 
+- (void)dealloc
+{
+    [self _removeObserver];
+}
+
 + (VLCPlaylistTableViewCell *)cellWithReuseIdentifier:(NSString *)ident
 + (VLCPlaylistTableViewCell *)cellWithReuseIdentifier:(NSString *)ident
 {
 {
     NSArray *nibContentArray;
     NSArray *nibContentArray;
@@ -46,68 +51,78 @@
     [self _updatedDisplayedInformationForKeyPath:keyPath];
     [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
 - (void)setMediaObject:(MLFile *)mediaObject
 {
 {
     if (_mediaObject != 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;
         _mediaObject = mediaObject;
         // prevent the cell from recycling the current snap for random contents
         // prevent the cell from recycling the current snap for random contents
         self.thumbnailView.image = nil;
         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];
     [self _updatedDisplayedInformationForKeyPath:nil];