更新时间:2022-12-06 11:58:08
你可以使用这个概念关联对象。使用函数 objc_setAssociatedObject()
和 objc_getAssociatedObject()
。您可以使用这些属性实质上添加一个新属性,在您的情况下,通过类别将 NSDictionary
保存到对象。
You can use the concept of associated objects. Using the functions objc_setAssociatedObject()
and objc_getAssociatedObject()
. You can use these properties to essentially add a new property, in your case to hold an NSDictionary
, to an object through a category.
以下是 UIAlertView
类别的示例。如果项目使用ARC,则应在没有 ARC
, -fno-objc-arc
标志的情况下编译这些文件。
Here is an example of a UIAlertView
category. These files should be compiled without ARC
, -fno-objc-arc
flag set if the project is using ARC.
UIAlertView + WithContext.h:
#import <UIKit/UIKit.h>
@interface UIAlertView (Context)
@property (nonatomic, copy) NSDictionary *userInfo;
@end
UIAlertView + WithContext.m:
#import "UIAlertView+WithContext.h"
// This enum is actually declared elseware
enum {
OBJC_ASSOCIATION_ASSIGN = 0,
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1,
OBJC_ASSOCIATION_COPY_NONATOMIC = 3,
OBJC_ASSOCIATION_RETAIN = 01401,
OBJC_ASSOCIATION_COPY = 01403
};
@implementation UIAlertView (Context)
static char ContextPrivateKey;
-(void)setUserInfo:(NSDictionary *)userInfo{
objc_setAssociatedObject(self, &ContextPrivateKey, userInfo, 3);
}
-(NSDictionary *)userInfo{
return objc_getAssociatedObject(self, &ContextPrivateKey);
}
@end
此类别很容易使用。
SomeViewController.m: a UIAlertViewDelegate
是否使用ARC。
SomeViewController.m: a UIAlertViewDelegate
using ARC or not.
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Title" message:@"Message" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
alert.userInfo = [NSDictionary dictionaryWithObject:@"Hello" forKey:@"Greeting"];// autorelease if MRC
[alert show]; // release if MRC
}
-(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex{
NSLog(@"userInfo:%@",alertView.userInfo);
}
当你按下alertview的OK按钮时,你会看到:
When you press the alertview's OK button you will see:
userInfo:{
Greeting = Hello;
}
几个笔记:
1)确保关联类型与属性声明匹配,以便事物按预期运行。
1) Make sure the association type matches the property declaration so things behave as expected.
2)你可能不应该使用属性/关联的userInfo
因为Apple可能决定将 userInfo
属性添加到 UIAlertView
将来。
2) You probably shouldn't use userInfo
for the property/association since Apple may well decide to add a userInfo
property to UIAlertView
in the future.
编辑 解决您对 [self autorelease]的担忧;
必须平衡隐含的 alloc
保留此行:委托:[[WantAlertViewContext alloc] initWithDelegate:self context:userInfo]
。您可以通过在最终 UIAlertView
委托方法中调用 [self autorelease];
来实现此平衡。
It is imperative that you balance your implicit alloc
retain from this line: delegate:[[WantAlertViewContext alloc] initWithDelegate:self context:userInfo]
. You achieve this balance by calling [self autorelease];
in the final UIAlertView
delegate method.
当然,这确实是错的。主要是因为在看这个时没有办法乍一看它看起来像内存管理错误。但有一种简单的方法可以避免您正在创建的受控泄漏API;让 WantAlertViewContext
的实例明确保留自己。例如:
Granted, this does feel wrong. Mostly because there is no way when looking at this that it doesn't at first blush look like memory mis-management. But there is one simple way to avoid this "controlled leak" API you are creating; Have the instance of WantAlertViewContext
explicitly retain itself. For example:
-(id)initWithDelegate:(id<WantAlertViewContextDelegate>)delegate context:(id)context{
self = [super init];
if (self) {
_delegate = delegate;
_context = [context retain];
}
return [self retain]; // Explicitly retain self
}
-(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex{
alertView.delegate = nil;
[self autorelease]; // Or just [self release]; doesn't make much difference at this point
}
现在你的班级有一些内在的和谐。我说一些,因为这仍然不完美。例如,如果实例永远不是警报视图委托,则永远不会释放它。它仍然只是一个半控制的内存泄漏。
Now your class has some internal harmony. I say some because this is still not perfect. For example, if an instance is never an alert-view delegate it will never be released. It is still just a "semi-controlled" memory leak.
无论如何,现在你的实例化调用看起来更合乎逻辑:
Anyway, now your instantiation call can look more logical:
delegate:[[[WantAlertViewContext alloc] initWithDelegate:self context:userInfo] autorelease];
我认为这种特殊的设计模式充满了危险。如果你最终使用它,请密切关注它。
I think that this particular design pattern is fraught with danger. If you do end up using it keep a close eye on it.