Я хотел бы знать, как добавить объект userInfo или любой NSDictionary в UIAlertView?
Спасибо.
Я хотел бы знать, как добавить объект userInfo или любой NSDictionary в UIAlertView?
Спасибо.
Если вы находитесь нa > 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, чтобы добавить это поле, или сохранить ссылку в своем классе делегата. Но самым общим способом привязки любого объекта к любому другому объекту является использование 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, перечислены здесь.
Я написал (проверенную) категорию на 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
-подобную функцию на каждом объекте. Пожалуйста!: -)
Это работает для меня, если я дам ему буквальную строку c, такую как "ключ", вместо создания статического char
Вместо этого, принимая во внимание то, что говорит Аномия, вы могли бы сделать это:
objc_setAssociatedObject ( alert , (const void*)0x314 , notification , OBJC_ASSOCIATION_RETAIN ) ;
Это работает на все, что позволяет вам использовать произвольные void * (наблюдение, эту функцию и т.д.) и не требует дополнительных статических переменных трюков. Кроме того, (const void *) 0x314 ВСЕГДА 0x314, независимо от того, что делает компилятор.
Кроме того, Аномия, вы только что сэкономили мне много работы в приложении, над которым я сейчас работаю. Спасибо!
Я придумал более простое решение, которое может поместиться в некоторых обстоятельствах. Поскольку вы получаете контекст 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". Надеюсь, это поможет.