Development Tip

objc_setAssociatedObject ()는 무엇이며 어떤 경우에 사용해야합니까?

yourdevel 2020. 11. 14. 11:10
반응형

objc_setAssociatedObject ()는 무엇이며 어떤 경우에 사용해야합니까?


내가 맡은 프로젝트에서 원저자가 사용 objc_setAssociatedObject()하기로 결정했고 그것이 무엇을하는지 또는 왜 사용하기로 결정했는지 100 % 명확하지 않습니다.

나는 그것을 찾아보기로 결정했고, 불행히도 문서는 그 목적에 대해 그다지 설명 적이 지 않습니다.

objc_setAssociatedObject
주어진 키 및 연결 정책을 사용하여 주어진 개체에 대한 관련 값을 설정합니다.
void objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy policy)
매개 변수 연결에
object
대한 소스 개체입니다.
key
연결의 키입니다.
value
개체의 키 키와 연결할 값입니다. 기존 연결을 지우려면 nil을 전달하십시오.
policy
연결 정책입니다. 가능한 값은 "연관 객체 동작"을 참조하십시오.

그렇다면이 함수는 정확히 무엇을하고 어떤 경우에 사용해야합니까?


답변을 읽은 후 편집

그렇다면 다음 코드의 요점은 무엇입니까?

Device *device = [self.list objectAtIndex:[indexPath row]];
DeviceViewController *next = [[DeviceViewController alloc] initWithController:self.controller
                                                                            device:device
                                                                               item:self.rootVC.selectedItem];  
    objc_setAssociatedObject(device, &kDeviceControllerKey, next, OBJC_ASSOCIATION_RETAIN);

장치가 이미 인스턴스 변수 인 경우 장치를 뷰 컨트롤러와 연결하는 데 어떤 의미가 있습니까?


Objective-C Runtime Reference 의 참조 문서에서 :

Objective-C 런타임 함수 objc_setAssociatedObject를 사용하여 한 개체와 다른 개체를 연결합니다. 이 함수는 소스 개체, 키, 값 및 연결 정책 상수의 네 가지 매개 변수를 사용합니다. 열쇠는 void 포인터입니다.

  • 각 연결의 키는 고유해야합니다. 일반적인 패턴은 정적 변수를 사용하는 것입니다.
  • 이 정책은 연결된 개체가 할당,
    유지 또는 복사되는지 여부와
    연결이 원자 적으로 또는
    비원 자적으로 만들어 지는지를 지정합니다 . 이 패턴은 선언 된 속성
    의 속성과 유사
    합니다 ( "속성
    선언 속성"참조). 상수를 사용하여 관계에 대한 정책을 지정합니다 (
    objc_AssociationPolicy 및
    Associative Object Behaviors 참조).

배열과 문자열 간의 연결 설정

static char overviewKey;



NSArray *array =

    [[NSArray alloc] initWithObjects:@"One", @"Two", @"Three", nil];

// For the purposes of illustration, use initWithFormat: to ensure

// the string can be deallocated

NSString *overview =

    [[NSString alloc] initWithFormat:@"%@", @"First three numbers"];



objc_setAssociatedObject (

    array,

    &overviewKey,

    overview,

    OBJC_ASSOCIATION_RETAIN

);



[overview release];

// (1) overview valid

[array release];

// (2) overview invalid

At point 1, the string overview is still valid because the OBJC_ASSOCIATION_RETAIN policy specifies that the array retains the associated object. When the array is deallocated, however (at point 2), overview is released and so in this case also deallocated. If you try to, for example, log the value of overview, you generate a runtime exception.


objc_setAssociatedObject adds a key value store to each Objective-C object. It lets you store additional state for the object, not reflected in its instance variables.

It's really convenient when you want to store things belonging to an object outside of the main implementation. One of the main use cases is in categories where you cannot add instance variables. Here you use objc_setAssociatedObject to attach your additional variables to the self object.

When using the right association policy your objects will be released when the main object is deallocated.


Here is a list of use cases for object associations:

one: To add instance variables to categories. In general this technique is advised against, but here is an example of a legitimate use. Let's say you want to simulate additional instance variables for objects you cannot modify (we are talking about modifying the object itself, ie without subclassing). Let's say setting a title on a UIImage.

// UIImage-Title.h:
@interface UIImage(Title)
@property(nonatomic, copy) NSString *title;
@end 

// UIImage-Title.m:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>

static char titleKey;

@implementation UIImage(Title)
- (NSString *)title
{
    return objc_getAssociatedObject(self, &titleKey);
}

- (void)setTitle:(NSString *)title
{
    objc_setAssociatedObject(self, &titleKey, title, OBJC_ASSOCIATION_COPY);
}
@end

Also, here is a pretty complex (but awesome) way of using associated objects with categories.. it basically allows you to pass in a block instead of a selector to a UIControl.


two: Dynamically adding state information to an object not covered by its instance variables in conjunction with KVO.

The idea is that your object gains state information only during runtime (ie dynamically). So the idea is that although you can store this state info in an instance variable, the fact that you're attaching this info into a an object instantiated at runtime and dynamically associating it with the other object, you are highlighting the fact that this is a dynamic state of the object.

One excellent example that illustrates this is this library, in which associative objects are used with KVO notifications. Here is an excerpt of the code (note: this KVO notification isn't necessary to run make the code in that library work.. rather it's put there by the author for convenience, basically any object that registers to this will be notified via KVO that changes have happened to it):

static char BOOLRevealing;

- (BOOL)isRevealing
{
    return [(NSNumber*)objc_getAssociatedObject(self, &BOOLRevealing) boolValue];
} 

- (void)_setRevealing:(BOOL)revealing
{
    [self willChangeValueForKey:@"isRevealing"];
    objc_setAssociatedObject(self, &BOOLRevealing, 
       [NSNumber numberWithBool:revealing], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    [self didChangeValueForKey:@"isRevealing"];
}

bonus: take a look at this discussion/explanation of associated objects by Mattt Thompson, author of the seminal AFNetworking library


To answer your revised question:

What is the point in associating the device with the view controller if it's already an instance variable?

There are several reasons why you might want to do this.

  • the Device class doesn't have a controller instance variable, or property and you can't change it or subclass it e.g. you don't have the source code.
  • you want two controllers associated with the device object and you can't change the device class or subclass it.

Personally, I think it is very rare to need to use low level Objective-C runtime functions. This looks like a code smell to me.

참고URL : https://stackoverflow.com/questions/5909412/what-is-objc-setassociatedobject-and-in-what-cases-should-it-be-used

반응형