gpt4 book ai didi

iOS 7.0 和 ARC : UITableView never deallocated after rows animation

转载 作者:技术小花猫 更新时间:2023-10-29 10:44:57 24 4
gpt4 key购买 nike

我有一个非常简单的 ARC 测试应用程序。其中一个 View Controller 包含 UITableView。在制作行动画(insertRowsAtIndexPathsdeleteRowsAtIndexPaths)之后,UITableView(和所有单元格)从未被释放。如果我使用 reloadData,它工作正常。在 iOS 6 上没有问题,只有 iOS 7.0。关于如何修复此内存泄漏的任何想法?

-(void)expand {

expanded = !expanded;

NSArray* paths = [NSArray arrayWithObjects:[NSIndexPath indexPathForRow:0 inSection:0], [NSIndexPath indexPathForRow:1 inSection:0],nil];

if (expanded) {
//[table_view reloadData];
[table_view insertRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationMiddle];
} else {
//[table_view reloadData];
[table_view deleteRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationMiddle];
}
}

-(int)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

return expanded ? 2 : 0;
}

table_view 是一种 TableView 类(UITableView 的子类):

@implementation TableView

static int totalTableView;

- (id)initWithFrame:(CGRect)frame style:(UITableViewStyle)style
{
if (self = [super initWithFrame:frame style:style]) {

totalTableView++;
NSLog(@"init tableView (%d)", totalTableView);
}
return self;
}

-(void)dealloc {

totalTableView--;
NSLog(@"dealloc tableView (%d)", totalTableView);
}

@end

最佳答案

好吧,如果你挖掘得更深一点(禁用 ARC,子类 tableview,重写 retain/release/dealloc 方法,然后在它们上面放置日志/断点),你会发现动画完成 block 中发生了一些不好的事情,这可能导致泄漏。
看起来 tableview 在 iOS 7 上插入/删除单元格后从完成 block 接收了太多保留,但在 iOS 6 上没有(在 iOS 6 上 UITableView 尚未使用 block 动画 - 你也可以在堆栈跟踪上检查它) .

所以我尝试以一种肮脏的方式从 UIView 接管 tableview 的动画完成 block 生命周期:方法调配。 这实际上解决了问题。
但它的功能更多,所以我仍在寻找更复杂的解决方案。

所以扩展 UIView:

@interface UIView (iOS7UITableViewLeak)
+ (void)fixed_animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion;
+ (void)swizzleStaticSelector:(SEL)selOrig withSelector:(SEL)selNew;
@end
#import <objc/runtime.h>

typedef void (^CompletionBlock)(BOOL finished);

@implementation UIView (iOS7UITableViewLeak)

+ (void)fixed_animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion {
__block CompletionBlock completionBlock = [completion copy];
[UIView fixed_animateWithDuration:duration delay:delay options:options animations:animations completion:^(BOOL finished) {
if (completionBlock) completionBlock(finished);
[completionBlock autorelease];
}];
}

+ (void)swizzleStaticSelector:(SEL)selOrig withSelector:(SEL)selNew {
Method origMethod = class_getClassMethod([self class], selOrig);
Method newMethod = class_getClassMethod([self class], selNew);
method_exchangeImplementations(origMethod, newMethod);
}

@end

如您所见,原始完成 block 并未直接传递给 animateWithDuration: 方法,而是从包装器 block 中正确释放(缺少此 block 会导致 TableView 泄漏)。我知道它看起来有点奇怪,但它解决了问题。

现在用您 App Delegate 的 didFinishLaunchingWithOptions 或任何您想要的新动画实现替换原来的动画实现:

[UIView swizzleStaticSelector:@selector(animateWithDuration:delay:options:animations:completion:) withSelector:@selector(fixed_animateWithDuration:delay:options:animations:completion:)];

之后,所有对 [UIView animateWithDuration:...] 的调用都会导致这个修改后的实现。

关于iOS 7.0 和 ARC : UITableView never deallocated after rows animation,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18919870/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com