请原谅:我是初学者。我正在看另一个问题/答案,并遇到了这段代码:
SpinningView *spinner = [[SpinningView alloc] initWithFrame:CGRectMake(0.0, 0.0, 20.0, 20.0)]
//现在让我们来看看SpinningView的-initWithFrame:方法的实现
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
self.backgroundColor = [UIColor clearColor];
}
return self;
}
我相信,在代码的第二部分中,self指向发送消息的实例,导致遇到“self”,即[SpinningView alloc]的结果。 (或者不产生实例?)
所以,当你在第4行代码上调用self = [super initWithFrame:frame]时,你是不是要重新分配与“spinner”相关联的指针值?即,你是不是放弃了你在第一行分配的内存?或者编译器有人知道只是复制内存值而不是更改指针值?或者......什么??
谢谢!
答案 0 :(得分:1)
这是obj-c对象的-init
方法的标准习惯用法。这个想法是,从+alloc
分配的内容无关紧要,只有从-init
返回的内容才重要。现在,-init
通常只使用self
中已分配的对象。但它不是必须的。可以自由地释放该对象并创建一个新对象。经典的例子是当你分配/初始化NSString*
时,实际上并没有找回NSString*
的实例,你会得到一个具体的子类。这是因为NSString*
是“类群集”。因此,当您调用+alloc
时,您将返回NSString*
,但是当您调用-init
时,它会释放该对象并重新分配其子类之一的对象,初始化该新对象,然后交给它回到你身边。
另一个例子是如果你有一个试图记忆自己的类。假设您有一个使用数字初始化的不可变类。您可以更改-init
以重新使用该类的现有实例。这是一个例子(注意:不是线程安全的):
static NSDictionary *numberCache;
@interface MyNumber : NSObject
@property (readonly) int number;
- (id)initWithInt:(int)i;
@end
@implementation MyNumber
+ (void)initialize {
if (self == [MyNumber class]) {
numberCache = [[NSDictionary alloc] init];
}
}
- (id)initWithInt:(int)i {
// find ourself in the numberCache
NSValue *val = [numberCache objectForKey:@(i)];
if (val) {
// yep, we exist. Release the just-allocated object
[self release];
// and retain the memoized object and stuff it back in self
self = [[val nonretainedObjectValue] retain];
} else if ((self = [super init])) {
// nope, doesn't exist yet. Initialize ourself
_number = i;
// and stuff us into the cache
val = [NSValue valueWithNonretainedObject:self];
[numberCache setObject:val forKey:@(i)];
}
return self;
}
- (void)dealloc {
// remove us from the cache
[numberCache removeObjectForKey:@(_number)];
[super dealloc];
}
@end
答案 1 :(得分:0)
@KevinBallard涵盖了大部分要点。我们需要self =
的原因是因为init
无法保证返回调用它的同一对象(它可能返回不同的对象或nil
)。我将回答您的问题并扩展内存管理方面:
我相信,在代码的第二部分,自我指向 发送消息导致“自我”存在的实例 遇到了,即[SpinningView alloc]的结果。
是
所以,当你在第4行调用self = [super initWithFrame:frame]时 代码,你不是重新分配与之关联的指针值 “微调”?
是。目前还不是spinner
(spinner
不存在)。您正在方法中重新分配指针变量self
。
是的,你是不是放弃了你在第一次分配的内存 线?或者编译器只知道复制内存值 而不是改变指针值?或者......什么??
是。在MRC下,您只是重新分配指针,除了更改指针值之外,编译器不会执行任何操作。在ARC下,它更复杂,但在一天结束时,编译器在这种情况下就像在MRC下一样,即只重新指定指针。
如果你考虑一下,它并不是真的“放弃”记忆。按照惯例,您会看到init
方法取得(“使用”)已经保留的对象的所有权(通常是对alloc
的调用的返回结果),并返回保留的对象。但这两者不一定是同一个对象。因此,当您调用init
方法时,其self
已被保留,init
方法拥有该方法,但随后调用[super init...]
,调用超类{{1} init
上的方法,以便现在获取self
拥有self
所有权的所有权。作为回报,该超类的init
会向您返回一个保留的实例,您将其分配给init
。你并没有“放弃”self
,因为你把它交给了超类的self
方法,后者又负责管理它的内存(如果它想要返回别的东西就释放它)。