Cocoa Programming for Mac OS X 第四章(Memory Management)摘录

Cocoa Programming for Mac OS X 第四章(Memory Management)摘录,第1张

概述一 、打开和关闭垃圾搜集器 Let's say that there are two instances of Person and that each has a favoriteColor, a pointer to a color object. If two people have the same favoriteColor, the objects will have pointers

一 、打开和关闭垃圾搜集器

Let's say that there are two instances of Person and that each has a favoritecolor,a pointer to a color object. If two people have the same favoritecolorFigure 4.1).

figure 4.1. The Problem




We do not want this orphaned color to be taking up room in our program's memory. We want the memory deallocated,so that we can put new objects in that memory,but we must be sure that the color is not deallocated while any objects are pointing to it.

This is a relatively tricky problem. Apple has come up with two solutions:

The old solution uses retain counts: Every object has a retain count,which should represent the number of other objects that have pointers to it. If the color is the favorite of two people,the retain count of that color should be 2. When it goes to zero,the object is deallocated.

The new solution,introduced in 10.5,is a garbage collector, which babysits(保姆) the entire object graph,looking for objects that can't be reached from the variables that are in scope. The unreachable objects are automatically deallocated.

What are the Trade-offs? Retain counts are a bit cumbersome(笨重的;不方便的): You need to explicitly retain objects that you want to keep around and to explicity release them when you are no longer interested in them. The retain-count mechanism also creates a dastardly(卑怯的) problem: object A retains object B,and B retains A. They are an island of garbage that will never go away,because they are retaining each other. This is kNown as a retain cycle. Figure 4.2 is an example of a common retain cycle.

figure 4.2. An Island of Garbage


Why not always use the garbage collector? If you use the garbage collector,your application will not run on any version of Mac OS before 10.5. Also,the garbage collector requires some cpu time to scan through the objects,looking for garbage. This can sometimes result in poorer performance. In an application that does a lot of audio or vIDeo processing,the garbage collector can cause hiccups(打嗝声) in the processing while it is doing a scan.

Turning the Garbage Collector On and Off

In the Groups and files outline vIEw of Xcode,you will see a group called Targets. Every project has at least one target. The targetrepresents one build process and typically results in one product. So,for example,you might have a project with two targets: One builds an application,and the other builds the Spotlight importer for that application's data file.

Look at the lottery project. Double-click the lottery target to open the Inspector. Look at the Build@L_404_24@ panel. This is where you can set all the variables that control how the program is built.

In the search fIEld,type in Garbage. Many lines will disappear,and you will see Objective-C Garbage Collection. Here,you can choose whether you want the garbage collector enabled. If you choose UnsupportedFigure 4.3).

figure 4.3. Enabling/disabling the Garbage Collector

The other two choices will enable the garbage collector. You must recompile before the change takes effect. (The difference between Supported and required is interesting only if you are creating a framework or plug-in that will be used in another application.)


二 、 living with the Garbage Collector

Your application will have an instance of NSGarbageCollector if and only if it is using the garbage collector. Add a line near the end of lottery.m:

[pool drain];NSLog(@"GC = %@",[NSGarbageCollector defaultCollector]);return 0;

Build and run the tool. Are you using the garbage collector?

If you are using the garbage collector,it is important that you not keep references to objects that you don't care about. In themain function of lotterynow and array pointers to nil when you lose interest in them. Add those lines now:

}
// Done with 'now',now是一个局部变量
now = nil;
      
for (LotteryEntry *entryToPrint in array) {
        NSLog(@"%@",entryToPrint);
    }    
}  
// Done with 'array',array是一个局部变量
array = nil;
[pool drain];
NSLog(@"GC = %@",[NSGarbageCollector defaultCollector]);
return 0;}

Now the garbage collector will know that it can deallocate the NSCalendarDate that now pointed to and the NSMutableArray thatarray pointed to. (In reality,the program almost certainly exits before the garbage collector gets around to deallocating those objects.)


三、living with Retain Counts

Creating autoreleased Objects

You created a description method that looks like this:

- (Nsstring *)description
{
    Nsstring *result;
    result = [[Nsstring alloc] initWithFormat:@"%@ = %d and %d",
              [entryDate descriptionWithCalendarFormat:@"%b %d %Y"],monospace">              firstNumber,secondNumber];
    return result;
}

This code would work perfectly well but would result in an annoying memory leak. The alloc operation always yIElds an object with a retain count of 1; thus,the string being returned has a retain count of 1. Any object asking for the string would retain it. The string would then have a retain count of 2. When no longer interested in the string,the object would release it. The retain count would become 1. As you see,the string would never be deallocated.

Our next attempt might look something like this:

- (Nsstring *)description{ Nsstring *result; result = [[Nsstring alloc] initWithFormat:@"%@ = %d and %d",[entryDate descriptionWithCalendarFormat:@"%b %d %Y"],firstNumber,secondNumber]; [result release]; return result;}

This code would not work at all. When sent the message release

The problem,then,is that you need to return a string,but you do not want to retain it. This is a common problem throughout the frameworks,which leads us to how the NSautoreleasePool is used in a non-GC application.

Objects are added to the current autorelease pool when they are sent the message autorelease. When the autorelease pool is drained,it sends the message release to all objects in the pool.

In other words,when an object is autoreleased,it is marked to be sent release sometime in the future. In particular,in a Cocoa application,an autorelease pool is created before every event is handled and is drained after the event has been handled. Thus,unless the objects in the autorelease pools are being retained,they will be destroyed as soon as the event has been handled.

A correct solution,is

[result autorelease]; return result;}

Rules Concerning Release

Objects created by allocnew,monospace">copy,or mutablecopy have a retain count of 1 and are not in the autorelease pool.

If you get an object by any other method,assume that it has a retain count of 1 and is in the autorelease pool. If you do not wish it to be deallocated with the current autorelease pool,you must retain it.

Because you will frequently need objects that you are not retaining,many classes have class methods that return autoreleased objects. Nsstring,has stringWithFormat:. The simplest correct solution then would be

- (Nsstring *)description{ return [Nsstring stringWithFormat:@"%@ = %d and %d",secondNumber];}
Temporary Objects

Note that the autoreleased object won't be released until the event loop ends. This behavior makes it perfect for provIDing an intermediate result. For example,if you had an array of Nsstring objects,you Could create a string with all the elements in uppercase and concatenated together,like this:

- (Nsstring *)concatenatedAndAllCaps{ int i; Nsstring *sum = @""; Nsstring *upper; for (i=0; i < [myArray count]; i++) { upper = [[myArray objectAtIndex:i] uppercaseString]; sum = [Nsstring stringWithFormat:@"%@%@",sum,upper]; } return sum;}

With this method,if you have 13 strings in the array,26 autoreleased strings will be created: 13 by uppercaseString and 13 bystringWithFormat:; the initial constant string is a special case and doesn't count. One of the resulting strings is returned and may be retained by the object that asked for it. The other 25 strings are deallocated automatically at the end of the event loop. (Note that you would probably get better performance in this example by appending the uppercased string to anNSMutableString instead of creating a new string and adding it to the autorelease pool each time through the loop.)

总结

以上是内存溢出为你收集整理的Cocoa Programming for Mac OS X 第四章(Memory Management)摘录全部内容,希望文章能够帮你解决Cocoa Programming for Mac OS X 第四章(Memory Management)摘录所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1066480.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-26
下一篇 2022-05-26

发表评论

登录后才能评论

评论列表(0条)

保存