Array under ARC

来源:互联网 发布:java 读取cad文件 dwg 编辑:程序博客网 时间:2024/06/05 03:47

Array

I explained the ownership specifiers with ‘id’ or object type variables. In this section, I explain how we can use the specifiers with arrays.

The following source code shows how to use a static array of variables qualified with __strong.

id objs[10];

You can do the same with __weak, __autoreleasing, or __unsafe_unretained.

id __weak objs[10];

By the way, any variables qualified with __strong, __weak, or __autoreleasing other than __unsafe_unretained, are initialized with nil. This is also applied for static array. Any arrays of variables, which qualified with __strong, __weak, or __autoreleasing, are initialized with nil. Let’s see how to use them.

{
    id objs[2];
    objs[0] = [[NSObject alloc] init];
    objs[1] = [NSMutableArray array];
}

When the control flow leaves the scope of the array, all the variables that have strong references in the array disappear. The assigned objects are released automatically. It is identical to variables not in arrays.

What will happen with a dynamic array? Basically, you should use containers in the Foundation Framework such as NSMutableArray, NSMutableDictionary, or NSMutableSet. Then the stored objects will be properly managed. These containers are the better choice, but you can still use a dynamic C array with variables qualified with __strong. But you have to remember a few things. As usual, let’s see them with an example.

First, declare a pointer to a dynamic C array:

id __strong *array = nil;

As described previously, ‘id *’ type means ‘id __autoreleasing *’. So, in this case, you have to type __strong qualifier. Although ‘id’ type variables with a __strong ownership qualifier are initialized as nil, id pointer type variables qualified with __strong are not. So, you have to assign nil explicitly.

Or, you can declare it as follows, if you prefer class type instead of ‘id’.

NSObject * __strong *array = nil;

Next, allocate a memory block for the variables in the array with the calloc function.

array = (id __strong *)calloc(entries, sizeof(id));

In this source code, a memory block is allocated for the number of “entries” elements. Note that variables qualified with __strong have to be initialized with nil. The calloc function is used to fill with zero after allocation. Instead of the calloc function, you can use the malloc function to allocate and the memset function to fill with zero as follows.

array = (id __strong *)malloc(entries * sizeof(id));
memset(array, 0, entries * sizeof(id));

However, it is very dangerous to assign nil as follows.

array = (id __strong *)malloc(sizeof(id) * entries);
for (NSUInteger i = 0; i < entries; ++i)
    array[i] = nil;

In this source code, the memory area allocated by malloc isn’t initialized by zero. So, before each assignment, release methods are called on invalid addresses. Therefore simply using the calloc function is recommended. After that, you can do anything for the dynamic array that you can for the static array.

array[0] = [[NSObject alloc] init];

But after you finish using a dynamic array of variables qualified with __strong, you have to release all the entries yourself. This is very different from static array. Just disposing of the memory block with free function as in the following causes a memory leak because each entry will never be released.

free(array);

For static arrays, the compiler will insert code to release all the entries automatically when the variable scope is left. But for dynamic arrays, the compiler can’t detect their lifetimes. By setting all the entries to nil, you can remove all the strong references of the entries so that all the objects will be released. And then, you have to dispose of the memory block itself as well.

for (NSUInteger i = 0; i < entries; ++i)
    array[i] = nil;

free(array);

As opposed to the initialization, you can’t release objects with the memset function as it causes memory leak. It is just dangerous. You have to assign nil to all the entries manually to let the compiler detect it.

Likewise, copying any entries by memcpy or realloc the memory block is dangerous as well. By doing so the object might not be disposed of, or the same object might be disposed of more than once. So, using these functions is strictly prohibited.

Also, you can use dynamic arrays of variables qualified with __weak in the same manner as with __strong. It is better not to use with __autoreleasing, because that produces an unexpected state. Because any variables qualified with __unsafe_unretained are not in control of the compiler, you can use them just as you would C pointer type variables such as void*.

0 0
原创粉丝点击