简体   繁体   English

一些初学者Objective-C / iPhone问题

[英]Some beginner Objective-C/iPhone questions

I'm just starting out (reading up a lot for the past couple of days). 我刚开始(过去几天读了很多)。 Here's some questions that I have stacked up, hopefully someone can answer them. 这是我堆积的一些问题,希望有人可以回答。

1. the (self != nil) check in initializer code. 1. (self!= nil)检入初始化代码。 Why do it? 为什么这样? To prevent accidental access to some "run-only-once" code that's wrapped up in there? 为了防止意外访问包含在那里的一些“只运行一次”代码? Where from could this accidental access come from? 从哪里来的意外访问来自? Doing such checks suggest that I don't have control over what's going on. 做这样的检查表明我无法控制正在发生的事情。


- (id)init {
    self = [super init]
    if (self != nil) {
    // Code..
    }
    return self;
}

2. How is it that you don't have to free up anything that static methods return? 2.你怎么没有释放静态方法返回的任何东西? (or this is the idea I've got) (或者这是我的想法)

3. How is str = @"Hi there!" 3. str = @“你好!” different from 不同于

str = [[NSString alloc] initWithString:@"Hi there!"];

As I understand, you have to release str in aquired with second method, but not with first? 据我所知,你必须用第二种方法释放str,但不是先用? If so, when does the first one get released? 如果是这样,第一个什么时候发布? Which one is preferable (not minding the typing length)? 哪一个更好(不打算打字长度)?

4. What is autorelease, if iphone has no garbage collection? 4.什么是autorelease,如果iPhone没有垃圾收集? I've noticed something called "an autorelease pool" being created in main.m. 我注意到在main.m中创建了一个名为“自动释放池”的东西。 Is [myObject autorelease]; 是[myObject autorelease]; a way of adding myObject to the nearest wrapping "autorelease pool", which will release it? 一种将myObject添加到最近的包装“自动释放池”的方法,它将释放它? Basically, some magic to avoid releasing it yourself? 基本上,一些魔法,以避免自己释放它? Why use it? 为什么要用它?

Well, thats it for now. 好吧,现在就是这样。 Thanks for any answers! 谢谢你的回答!

  1. In Objective-C, it's possible to return an instance other than self from -init . 在Objective-C中,可以从-init返回除self之外的实例。 Classes do this, for example, to enforce a singleton instance, or in the case of class clusters. 例如,类执行此操作以强制执行单例实例,或者在类集群的情况下执行此操作。 NSNumber , for example, returns a subclass depending on the type of value passed to its initializer. 例如, NSNumber根据传递给其初始值设定项的值的类型返回子类。 So when you call [[NSNumber alloc] initWithLong:long_value] , NSNumber 's -initWithLong: initializer is called after NSNumber 's +alloc , but a subclass of NSNumber may be returned to the oringial caller. 因此,当您调用[[NSNumber alloc] initWithLong:long_value]NSNumber[[NSNumber alloc] initWithLong:long_value] -initWithLong:初始化程序在NSNumber+alloc之后调用,但NSNumber的子类可能会返回给oringial调用者。 Thus the pattern 因此模式

    self = [super init]; self = [super init];

    which reassigns self to the value of [super init] so that self points to the actual instance that [super init] returned. 它将self重新分配给[super init]的值,以便self指向[super init]返回的实际实例。 If +alloc or the super's init method fails, the result of [super init] may be nil . 如果+alloc或super的init方法失败, [super init]的结果可能nil To avoid, side effects in the case of a failed initialization, the pattern then becomes 为了避免在初始化失败的情况下产生副作用,模式就变成了

     - (id) init { if(self = [super init]) { // do initialization of instance variables etc. } return self; } 

    Note that you must return self (or nil or an other instance) from the init method. 请注意,您必须从init方法返回self (或nil或其他实例)。 You should assign self to [super init] and you may check for nil before doing more work. 应该将自己分配给[super init] ,你可以在做更多工作之前检查nil

  2. You may have to release the return value of a staic method. 您可能必须释放staic方法的返回值。 You should read the Cocoa memory management guide . 您应该阅读Cocoa内存管理指南 The rule is generally quite simple: If the method you call has "new", "alloc", or "copy" in its signature, the result belongs to the caller and the caller must call -release on that instance or there will be a memory leak. 规则通常很简单:如果您调用的方法在其签名中具有“new”,“alloc”或“copy”,则结果属于调用者,调用者必须在该实例上调用-release ,否则将会有内存泄漏。 Of course you should call -retain on anything else (ie not from an "alloc","new" or "copy" method) you want to keep a reference to and then call -release or -autorelease when you are done with that instance. 当然你应该在你要保留引用的任何其他东西(即不是来自“alloc”,“new”或“copy”方法)上调用-retain ,然后在完成该实例时调用-release-autorelease

  3. str = @"Hi there!" , assuming str was declared as NSString *str; ,假设str被声明为NSString *str; assigns the address of the string constant @"Hi there!" to the value of the 指定字符串的地址常量@"Hi there!" to the value of the @"Hi there!" to the value of the str variable. You do not need to retain or release string constants. @"Hi there!" to the value of the str variable. You do not need to retain or release string constants. @"Hi there!" to the value of the variable. You do not need to retain or release string constants. variable. You do not need to retain or release string constants. str = [[NSString alloc] initWithString:@"Hi there!"]; str = [[NSString alloc] initWithString:@“Hi there!”]; allocates a new string instance. The value of allocates a new string instance. The value of str will be the address of this instance. Each call of str allocates a new string instance. The value of will be the address of this instance. Each call of will be the address of this instance. Each call of str = [[NSString alloc] initWithString:@"Hi there!"]; will be the address of this instance. Each call of str = [[NSString alloc] initWithString:@“Hi there!”]; again will allocate a new instance. So after again will allocate a new instance. So after str2 = [[NSString alloc] initWithString:@"Hi there!"]; again will allocate a new instance. So after str2 = [[NSString alloc] initWithString之后:@“你好!”]; , str != str2 , while after str2 = @"Hi There!", str==str2 . , str!= str2 , while after str2 = @“Hi There!”之后, str==str2 See this answer as well. 也请参阅答案。

  4. -autorelease adds the receiver to the current NSAutoreleasPool . -autorelease将接收器添加到当前的NSAutoreleasPool When the pool is drained (usually at the end of the current run loop iteration, or when the pool is manually drained), the pool calls -release on all instances in the pool. 当池被耗尽时(通常在当前运行循环迭代结束时,或者当手动耗尽池时),池将在池中的所有实例上调用-release If this -release drops the retain count to 0, the object is deallocated (and -dealloc called) just as with any other -release . 如果此-release将保留计数-dealloc 0,则释放该对象(并且调用-dealloc ),就像使用任何其他 - -release Using an autorelease pool is generally frowned upon on the iPhone because it may cause you to accumulate many unused instances in the pool before it is drained at the end of the run loop iteration. 在iPhone上使用自动释放池通常不赞成,因为它可能会导致您在运行循环迭代结束之前将池中的许多未使用实例累积掉。 If you can use -release instead of -autorelease , you generally should. 如果你可以使用-release而不是-autorelease ,你通常应该。 Again, see the Cocoa memory management guide for more info. 再次,请参阅Cocoa内存管理指南以获取更多信息。

  1. There is a school of thought that in most cases, allocating the self pointer is something that the system should do, and not the programmer. 有一种观点认为,在大多数情况下,分配self指针是系统应该做的事情,而不是程序员。

Also, many people prefer to keep the main line of program flow as un-indented as possible. 此外,许多人更喜欢将程序流的主线保持为尽可能不缩进。 In which case the initialisation code could be re-written as: 在这种情况下,初始化代码可以重写为:

- (id)init {
    if (![super init]) {
        return nil; // There is a problem so bail early.
    }
    // Initialisation code here.
    return self
}

Will Shipley explains this much better than I do. Shipley会比我更好地解释这一点。

1: This check is to ensure that the super constructor returned a new object. 1:此检查是为了确保超级构造函数返回一个新对象。

2: Static methods don't refer to an instance 2:静态方法不引用实例

3: 3:

str = @"Hi there!"

This assigns the address of the constant string "Hi there!" 这将指定常量字符串“Hi there!”的地址。 to the pointer str 到指针str

str = [[NSString alloc] initWithString:@"Hi there!"];

This allocates a string and copies "Hi There!" 这会分配一个字符串并复制“Hi There!” to it. 它。 This means that a) str is modifiable and b) needs to be deallocated when you are done with it. 这意味着a)str是可修改的,b)完成后需要解除分配。

calling 调用

self = [super init];

May return nil if the superclass cannot initialize itself for some reason or other, including memory being unavailable, or certain prerequisites have not been met. 如果超类由于某种原因无法初始化自身,包括内存不可用或某些先决条件未得到满足,则可能返回nil。 If that is the case, you don't want to be trying to set variables of self, or set self as a delegate, or add self to an array, if self is nil. 如果是这种情况,您不希望尝试设置self变量,或者将self设置为委托,或者将self添加到数组(如果self为nil)。

The autorelease pool is something created upon every event the iPhone sends your application. 自动释放池是在iPhone发送应用程序的每个事件时创建的。 It is created before any code runs, and released after all your code is done, for each event. 它是在任何代码运行之前创建的,并在所有代码完成后为每个事件发布。 Any objects that you call autorelease on will be put into the current autorelease pool. 您调用autorelease on的任何对象都将被放入当前的自动释放池中。 Any objects in the autorelease pool will be released as many times as they were added, after your code completes. 在代码完成后,自动释放池中的任何对象将被添加多次。 In this way, you don't have to worry about who's responsible for releasing an object created by one method and returned to another method. 通过这种方式,您不必担心谁负责释放由一个方法创建的对象并返回到另一个方法。

You can create your own autorelease pools as necessary. 您可以根据需要创建自己的自动释放池。

str = [[NSString alloc] initWithString:@"Hi there!"];

This line creates a string that is not in an autorelease pool, so you have to release it manually. 此行创建一个不在自动释放池中的字符串,因此您必须手动释放它。 Simply writing 简单写作

@"Hi there!";

returns a string that you don't have to worry about releasing. 返回一个你不必担心释放的字符串。 Extending your previous example: 扩展您之前的示例:

str = [[[NSString alloc] initWithString:@"Hi there!"] autorelease];

would be another method of creating a string you don't need to worry about releasing. 将是另一种创建字符串的方法,您不必担心释放。

One difference between garbage collection and autorelease pools is that garbage collection works with circular references. 垃圾收集和自动释放池之间的一个区别是垃圾收集与循环引用一起使用。 Using autorelease pools, you don't want to have two objects that retain each other and hope that once nothing else refers to them, they will go out of existence; 使用自动释放池,你不希望有两个彼此保留的对象,并希望一旦没有别的东西引用它们,它们就会不再存在; they won't. 他们不会。

  1. If self is nil after the super initialisation then you're probably out of memory. 如果在超级初始化之后self 为零 ,那么你可能已经没有记忆了。 Your only reasonable course of action is to return nil and hope things get handled gracefully further up the stack. 你唯一合理的做法就是返回nil并希望在堆栈中进一步优雅地处理事情。

  2. Static methods aren't allowed allocate on the heap, therefore there's nothing to free. 静态方法不允许在堆上进行分配,因此没有什么可以免费的。

  3. In the first instance, the string is compiled into the data segment of your app and cannot be freed. 在第一个实例中,字符串被编译到应用程序的数据段中,无法释放。 In the second instance, you are allocating memory from the heap and copying your static string (from the data segment) into it. 在第二个实例中,您将从堆中分配内存并将静态字符串(从数据段)复制到其中。

  4. It's simple garbage collection. 这是简单的垃圾收集。 As to why to use it, the simple answer is don't. 至于为何使用它,简单的答案是不。 It's not recommended to use autorelease on the iPhone due to limited resources. 由于资源有限,不建议在iPhone上使用自动释放。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM