Как добавить userInfo в UIAlertView? - PullRequest
16 голосов
/ 12 марта 2011

Я хотел бы знать, как добавить объект userInfo или любой NSDictionary в UIAlertView?

Спасибо.

Ответы [ 5 ]

31 голосов
/ 12 марта 2011

Вы можете попробовать создать подкласс UIAlertView для добавления поля или сохранить ссылку в своем классе делегата. Но самый общий способ прикрепить любой объект к любому другому объекту - это использовать objc_setAssociatedObject.

Для этого вам нужно #import <objc/runtime.h>, и вам нужен произвольный void *, который используется в качестве ключа (обычная уловка - объявить static char fooKey; в вашем файле .m и использовать его адрес). Затем вы можете прикрепить объект так:

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, перечислены здесь .

15 голосов
/ 25 апреля 2012

Я написал (хорошо проверенную) категорию для 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: Переименуйте методы по своему усмотрению, но если вы решите сохранить имя, обязательно добавьте префикс,Это категория по корневому объекту, люди.Какой-то класс где-то использует это имя метода, и вы не хотите вмешиваться!Моя статическая библиотека, которую я включаю в каждый проект, использует имена методов associativeCCObjectForKey: и setAssociativeCCObject:forKey:.

. Надеюсь, это поможет всем, кто хочет иметь простую userInfo -подобную функцию для каждого объекта.Пожалуйста!: -)

11 голосов
/ 24 января 2012

Если вы используете> 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];
4 голосов
/ 09 августа 2011

Это работает для меня, если я дам ему буквальную строку c, такую ​​как «ключ», вместо создания статического символа

Вместо этого, принимая во внимание то, что говорит Аноми, вы могли бы вместо этогосделать это:

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

Это работает для всего, что позволяет вам использовать произвольный void * (наблюдение, эта функция и т. д.) и не требует дополнительных уловок статических переменных.Кроме того, (const void *) 0x314 ВСЕГДА 0x314, независимо от того, что делает компилятор.

Кроме того, Аноми, вы только что сохранили мне МНОГО работы в приложении, над которым я сейчас работаю.Спасибо!

1 голос
/ 20 января 2014

Я придумала более простое решение, которое может соответствовать некоторым обстоятельствам. Поскольку вы получаете контекст 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». Надеюсь, это поможет.

...