在 Objective-C 中保留计数和工厂方法
Posted
技术标签:
【中文标题】在 Objective-C 中保留计数和工厂方法【英文标题】:Retain count and factory methods in Objective-C 【发布时间】:2011-09-30 11:58:15 【问题描述】:我之前一直在这个论坛上寻找创建工厂函数以从 nib 构造自定义视图的最佳方法(here 是我以前的帖子)
我现在使用以下代码:
+ (LoadingV *)loadingViewCopyFromNib
LoadingV *view = nil;
NSArray* nibViews = [[NSBundle mainBundle] loadNibNamed:@"LoadingV" owner:self options:nil];
view = (LoadingV*)[nibViews objectAtIndex: 0];
// Setting up properties
CGRect frm = view.progress.frame;
frm.size.width *=1.5;
frm.size.height *=1.5;
view.progress.frame = frm;
view.waitLbl.text = NSLocalizedString(@"Please wait", @"");
return view; <------- warning is here
// In .h file
...
LoadingView* loadV;
@property (nonatomic, retain) LoadingView* loadV;
// in .m file
@synthesize loadV;
...
self.loadV = [LoadingV loadingViewCopyFromNib];
当我构建和分析时,我收到以下有关工厂功能的警告:
/LPAPP/Classes/LoadingV.m:34:5 返回 +0 保留计数的对象 到预期 +1(拥有)保留计数的调用者
为什么会这样?我知道在函数中分配的局部变量不会超出其范围,除非它们被保留和自动释放。但在我的情况下,我没有创建一个新对象,只是返回一个对现有对象的引用。那么为什么我会收到警告呢?像这样进行是否安全:)
干杯 自动对焦
【问题讨论】:
显然分析器会在返回保留对象的前缀(init、copy 等)中计算“加载”。 我认为你是对的!将更改 API 名称并删除 Copy。过去的实现有所不同,然后在不注意命名约定的情况下对其进行了修改。欢呼 您使用的是哪个版本的 XCode?.. clang/llvm 3.0 (ios 5 beta) 将为 ARC/ARC 转换内置不同的命名约定处理,也许它有点小问题 我没有使用 XCode 4,因为我在安装它时遇到了糟糕的体验。我回到带有 SDK 4.3.3 的 XCode 3.2.5(或 4.3.1 不确定:p) 我刚刚测试了更改函数名称并删除 Copy 并且一切正常。不再警告!伙计们干杯 【参考方案1】:虽然迈克是对的,但警告的原因完全不同。 您的方法名称包括“copy”,它被解释为返回 +1 保留计数(类似于 alloc、init)。请记住,一旦您过渡到 ARC,这可能会导致问题!
【讨论】:
这是不正确的,只有 'copy' 或 'mutableCopy' 的 前缀 它被解释为 +1 保留计数。 是的,苹果比其他人更喜欢记录一些“功能”......分析器的工作方式似乎有点不同......【参考方案2】:当涉及到像NSArray
这样的集合类时,objectAtIndex:
和其他类似访问器返回的引用不能保证在父容器被释放时保持有效。换句话说,objectAtIndex:
不会返回自动释放的对象。
这意味着一旦它来自的数组被释放,你返回的指针可能最终会变得无效。
要解决此问题,请在您的退货声明中使用retain
+autorelease
:
return [[view retain] autorelease];
更新:
我无法在我的 Xcode 版本中重现此警告。但也许马丁是正确的,您正在使用的 GCC/clang 版本错误地解释了“副本”。最新的 Xcode 和 gcc/clang 编译器不会出现此警告,并且规则是只有 prefix 的“copy”或“mutableCopy”被解释为返回 +1 保留对象。
【讨论】:
是的,你可能是对的,当然分析器是错误的——返回的对象在下一次自动发布之前是“好的”,除非改变 Objective-C 以识别 nibViews 已经通过超出范围。 分析仪没有错。是的,今天的实现细节使得对象将保持有效,但分析器只处理代码违反的对象所有权规则。如果将来某些底层实现发生变化,您的原始代码可能会停止工作。 实现在未来总是会改变,在不改变上述任何代码的情况下打破这一点。但当然,这样的更改会破坏很多应用程序(并不是说 Apple 会通过他们的更改破坏很多应用程序)。 顺便说一下,静态分析器到底在抱怨哪一行?我无法重现此分析器警告。 我认为从 objectAtIndex 返回的对象将保持活动状态,直到下一次自动释放,因为它是对已经在自动释放数组(nibViews)中的对象的引用。调用 self.loadV =... 甚至可以让它活得更久。这就是为什么我不确定警告并想问的原因。我将更改函数的名称并删除 Copy,因为我认为 Daniel R Hicks 有一个观点以上是关于在 Objective-C 中保留计数和工厂方法的主要内容,如果未能解决你的问题,请参考以下文章
有人能告诉我在objective-c中保留和释放到底做了啥吗?