【问题标题】:How to add userInfo to a UIAlertView?如何将 userInfo 添加到 UIAlertView?
【发布时间】:2011-07-13 21:16:56
【问题描述】:

我想知道如何将 userInfo 对象或任何 NSDictionary 添加到 UIAlertView?

谢谢。

【问题讨论】:

    标签: iphone objective-c nsdictionary uialertview userinfo


    【解决方案1】:

    您可以尝试将 UIAlertView 子类化以添加字段,或者将引用存储在您的委托类中。但是将任何对象附加到任何其他对象的最通用方法是使用objc_setAssociatedObject

    为此,您必须#import <objc/runtime.h>,并且您需要一个任意的void * 作为密钥(通常的技巧是在您的.m 文件中声明一个static char fooKey; 并使用它的地址)。然后你可以像这样附加对象:

    objc_setAssociatedObject(alertView, &fooKey, myDictionary, OBJC_ASSOCIATION_RETAIN);
    

    在这种情况下,myDictionary 将在 alertView 的整个生命周期内保留,并在 alertView 被释放时释放。

    要稍后检索您的关联对象,请使用逻辑命名为 objc_getAssociatedObject

    NSDictionary *myDictionary = objc_getAssociatedObject(alertView, &fooKey);
    

    如果没有关联集,它返回nil。要打破关联,只需使用objc_setAssociatedObject 为同一个对象和键关联一个新值; nil 可用于在不关联新对象的情况下中断关联。

    列出了除 OBJC_ASSOCIATION_RETAIN 之外的关联类型的其他值here

    【讨论】:

    • 谢谢@Anomie!这是我的代码:-(void)setObject:(id)object { objc_setAssociatedObject(self, &fooKey, object, OBJC_ASSOCIATION_RETAIN); } -(id)object { return objc_getAssociatedObject(self, &fooKey); }
    • 这很酷。如果我给它一个诸如“key”之类的文字 c 字符串而不是创建一个静态字符,它对我有用,因为我正在做的全部重点是避免创建全局/类变量(userInfo 本来可以去的地方) 假设两个相同的 c 字符串文字将指向相同的内存位置是否安全?
    • @ZakyGerman:不完全安全。 C 标准(Objective-C 所基于)说“如果它们的元素具有适当的值,则 [字符串文字的字符数组] 是否不同是未指定的。”这意味着允许编译器使"key" 的所有实例指向相同的内存位置,或全部指向不同的位置,或两者兼而有之。
    【解决方案2】:

    我在NSObject 上编写了一个(经过充分测试的)类别,它使每个对象都能够轻松存储数据。

    只需将代码放在头文件和实现文件中,然后将其导入您的任何项目。或者把它放在一个静态库中。仅限 Mac OS X 10.6+ 和 iOS(版本?)。

    #import <Foundation/Foundation.h>
    #import <objc/runtime.h>
    
    @interface NSObject (CCFoundation)
    
    - (id)associativeObjectForKey: (NSString *)key;
    - (void)setAssociativeObject: (id)object forKey: (NSString *)key;
    
    @end
    
    #pragma mark -
    
    @implementation NSObject (CCFoundation)
    
    static char associativeObjectsKey;
    
    - (id)associativeObjectForKey: (NSString *)key {
        NSMutableDictionary *dict = objc_getAssociatedObject(self, &associativeObjectsKey);
        return [dict objectForKey: key];
    }
    
    - (void)setAssociativeObject: (id)object forKey: (NSString *)key {
        NSMutableDictionary *dict = objc_getAssociatedObject(self, &associativeObjectsKey);
        if (!dict) {
            dict = [[NSMutableDictionary alloc] init];
            objc_setAssociatedObject(self, &associativeObjectsKey, dict, OBJC_ASSOCIATION_RETAIN);
        } [dict setObject: object forKey: key];
    }
    
    @end
    

    简单地说,只要您需要,每个对象都会成为易于使用的字典(感谢NSMutableDictionary)。字典在对象被释放时被释放,字典的对象在字典被释放时被释放。 Apple 如何让这一切变得如此简单,真是令人惊讶。

    警告 1:上面的代码是启用了 ARC。它经过了良好的测试,并用于多种已发货的产品中。我还没有发现任何内存泄漏或性能问题。

    警告 2: 根据需要重命名方法,但如果选择保留名称,请确保添加前缀。这是根对象 people 上的一个类别。某处的某个类正在使用此方法名称,您不想干涉!我在每个项目中都包含的静态库使用方法名称 associativeCCObjectForKey:setAssociativeCCObject:forKey:

    我希望这可以帮助任何想要在每个对象上都拥有类似userInfo 的简单功能的人。不客气! :-)

    【讨论】:

    【解决方案3】:

    如果您使用的是 > iOS 4.0(用于块)并且您只想要一个或两个按钮,您可以使用我制作的这个类别:

    https://github.com/rsaunders100/UIAlertView-Blocks

    它绕过了添加用户信息的需要,因为您将点击处理功能直接放入警报中。例如

     #import UIAlertView+Blocks.h
    
     ...
    
     ...
    
     NSString* myUserInfo = @"example";
    
     [UIAlertView displayAlertWithTitle:@"Example Alert View With Blocks"
                                message:nil
                        leftButtonTitle:@"Ok"
                      leftButtonAction:^{
                                          NSLog(@"%@", myUserInfo);
                                        } 
                      rightButtonTitle:nil
                     rightButtonAction:nil];
    

    【讨论】:

    • 你是否从链接中下载了 UIAlertView+Blocks.h 并包含#import UIAlertView+Blocks.h这一行?
    • 是的,我已经添加了。我已经解决了创建新类而不是添加UIAlerView+Blocks.h 到项目的问题
    • 如何通过pod导入你的项目?
    【解决方案4】:

    如果我给它一个文字 c 字符串,例如“key”而不是创建一个静态字符,它对我有用

    相反,考虑到 Anomie 所说的,您可以改为这样做:

    objc_setAssociatedObject ( alert , (const void*)0x314 , notification , OBJC_ASSOCIATION_RETAIN ) ;
    

    这适用于任何允许您使用任意 void*(观察、此函数等)并且不需要额外的静态变量技巧的东西。此外,无论编译器做什么,(const void*)0x314 始终为 0x314。

    另外,Anomie,你刚刚在我正在开发的应用程序中为我节省了很多工作。谢谢!

    【讨论】:

      【解决方案5】:

      我想出了一个更简单的解决方案,可能适合某些情况。因为您在调用委托时获得了 NSAlertView 上下文,所以我使用对象的实际地址来创建一个标记 (NSString*),然后我使用该标记将自定义值存储在全局或对象特定的 NSDictionary 中。这是一个例子:

      +(NSString*)GetTag:(id)ObjectIn
      {
          return [NSString stringWithFormat:@"Tag-%i",(int)ObjectIn];
      }
      

      在委托中:

      -(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
      {
          NSString* MyID = [CommandManager GetTag:alertView];
          [CurrentActiveAlerts removeObjectForKey:MyID];
      }
      

      调用:

          UIAlertView *myAlert = [[UIAlertView alloc] initWithTitle:title_text
                                                                message:@""
                                                           delegate:self
                                                  cancelButtonTitle:nil
                                              otherButtonTitles:button_text ,nil];
      
          CurrentActiveAlerts[[CommandManager GetTag:myAlert]] = CommandToRun;  
          [myAlert show];
          [myAlert release];
      

      这些键最终看起来像“Tag-226811776”。希望这会有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多