سؤال

I'm new to Objective-C and ARC, and have been searching and reading for hours without finding an answer. The code does what I want it to do, but I want to know that it doesn't rely on favorable conditions. Here's a simplified version of my code:

+(void)foo {
    Class *classes = (__unsafe_unretained Class *)malloc(sizeof(Class) * someValue);

    // Perform work without complicated memory management

    free(classes);
}

I can't do much about the structure I'm allocating. It's filled by objc_getClassList. Unfortunately, Apple doesn't seem to have updated their documentation to explain how to do this under ARC. The typecast above is partly conceived by looking at examples, but it still makes me nervous.

One of my concerns is that if I would have allocated space for a "regular" object, then dealloc would have been called when the variable goes out of scope, which would have happened after free is called. But I don't think that's exactly what's going on here.

  • Does Class behave differently from other kinds of Objective-C data types? Should I expect something else from it?
  • What kind of pointer is classes? I guess it references an array of unknown size (a non-object pointer), but ARC still cares about it since the code won't compile without that cast. It looks like a strong pointer, but I don't know what it would be a strong pointer to.
  • Are there strong pointers to the objects in the array at all, or are the objects themselves strong pointers? If not, does ARC still work, or should I revert to some MRC conventions?
  • Will there be an automated call to dealloc? When, and how can the compiler ensure that that happens?
  • Is it better practice to set classes to NULL, and only then do the call to free? Or should I iterate over the array and do something about every object, such as setting them to nil?
هل كانت مفيدة؟

المحلول

you are allocating an array of struct pointers (Class == pointer to a struct), which will be filled with pointers to the Classes registered to the runtime. This pointers will not be released/dealloced etc. as long as your application runs. You are not allocating any-classes, you are allocating space to hold pointers to this classes. Your code is totaly fine, and __unsafe_unretained is exactly what you want. It tells ARC you are holding a pointer to an Object you are not owning, and so prevent it from trying to release it at the end of the scope of your variable.

نصائح أخرى

Does Class behave differently from other kinds of Objective-C data types? Should I expect something else from it?

Class is a type that can hold a pointer to any class object, just like how id is a type that can hold a pointer to any object, and how NSString * is a type that can hold a pointer to any object that is an instance of NSString (or subtype thereof). Class objects are (one kind of) objects, and work in basically the same ways that other objects do. The type Class can be used just like other object-pointer types.

What kind of pointer is classes? I guess it references an array of unknown size (a non-object pointer), but ARC still cares about it since the code won't compile without that cast. It looks like a strong pointer, but I don't know what it would be a strong pointer to.

classes is a pointer to Class, i.e. a pointer to a pointer to a class object. You are using it here to point to the first member of an array of Class, which is correct. classes is not an object pointer, but it is a pointer to an object pointer; that's why ARC cares. It's just like if you cast the result of malloc to id * or NSString **. When you don't specify a qualifier on Class, it is implicitly __unsafe_unretained. So classes is already a pointer to an unretained object pointer.

Are there strong pointers to the objects in the array at all, or are the objects themselves strong pointers? If not, does ARC still work, or should I revert to some MRC conventions?

Will there be an automated call to dealloc? When, and how can the compiler ensure that that happens?

Class holds pointers to class objects. Class objects are basically singletons; they are not reference-counted. They generally live for the duration of the program, except perhaps if the class is unloaded. It's not necessary to maintain an explicit strong reference to the class object; the class will stay around.

Is it better practice to set classes to NULL, and only then do the call to free? Or should I iterate over the array and do something about every object, such as setting them to nil?

You obviously shouldn't set classes to NULL before calling free(); that way, calling free(classes); won't do anything. Since the elements of this array are __unsafe_unretained, there is no point to setting them to anything before freeing the memory; it will not make a difference.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top