Pytanie Jak dodać userInfo do UIAlertView?


Chciałbym wiedzieć, jak dodać obiekt UserInfo, lub dowolny NSDictionary, do UIAlertView?

Dziękuję Ci.


16
2018-03-12 00:31


pochodzenie




Odpowiedzi:


Jeśli jesteś na> iOS 4.0 (dla bloków) i chcesz tylko jeden lub dwa przyciski, możesz użyć tej kategorii, którą wykonałem:

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

Pomija potrzebę dodawania informacji o użytkowniku, ponieważ funkcja ręcznego klikania przechodzi bezpośrednio do alertu. na przykład

 #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];

11
2018-01-24 09:37



Katastrofa Xcode nierozpoznany selektor? - Lunayo
Pobrałeś UIAlertView + Blocks.h z linku i zawarłeś linię #import UIAlertView+Blocks.h? - Robert
Tak, dodałem. Rozwiązałem problem, tworząc nową klasę zamiast dodawać UIAlerView+Blocks.h do projektu - Lunayo
Jak zaimportować projekt za pomocą pod? - LKM


Możesz spróbować podklasy UIAlertView, aby dodać pole lub zapisać referencję w klasie delegatów. Ale najbardziej ogólnym sposobem dołączania dowolnego obiektu do dowolnego innego obiektu jest użycie objc_setAssociatedObject.

Aby to zrobić, musisz #import <objc/runtime.h>i potrzebujesz arbitra void * który jest używany jako klucz (zwykłą sztuczką jest deklarowanie a static char fooKey; w pliku .m i użyj jego adresu). Następnie możesz dołączyć obiekt w ten sposób:

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

W takim przypadku myDictionary zostanie zachowany na czas działania alertView i zostanie zwolniony po zwolnieniu alertViewView.

Aby później pobrać powiązany obiekt, użyj nazwy logicznej objc_getAssociatedObject.

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

Powraca nil jeśli nie było zestawu powiązań. Aby przerwać połączenie, po prostu użyj objc_setAssociatedObject powiązać nową wartość dla tego samego obiektu i klucza; nil może być użyty do zerwania powiązania bez kojarzenia nowego obiektu.

Inne wartości dla typu powiązania oprócz OBJC_ASSOCIATION_RETAIN są wymienione tutaj.


31
2018-03-12 01:13



Dziękuję @Anomie! To jest mój kod: -(void)setObject:(id)object { objc_setAssociatedObject(self, &fooKey, object, OBJC_ASSOCIATION_RETAIN); } -(id)object { return objc_getAssociatedObject(self, &fooKey); } - aLt
To fajnie. Działa to dla mnie, jeśli podam dosłowny łańcuch c, taki jak "klucz" zamiast tworzenia statycznego znaku, ponieważ cały punkt, który robię, to unikanie tworzenia zmiennych globalnych / klasowych (gdzie zamiast tego mógłby zostać użyty userInfo ) czy można bezpiecznie założyć, że dwa identyczne ciągi liter c wskażą tę samą lokalizację pamięci? - Zaky German
@ZakyGerman: Nie całkowicie bezpieczny. Standard C (na którym oparte jest Objective-C) mówi: "Nie jest określone, czy [tablice znaków dla literałów łańcuchowych] są odrębne pod warunkiem, że ich elementy mają odpowiednie wartości." Oznacza to, że kompilator może tworzyć wszystkie wystąpienia "key" wskazują tę samą lokalizację pamięci lub wszystkie w różnych lokalizacjach lub niektóre z nich. - Anomie


Napisałem kategorię (dobrze przetestowaną) NSObject dzięki czemu każdy obiekt ma możliwość łatwego przechowywania danych.

Wystarczy umieścić kod w nagłówku i pliku implementacji i zaimportować go do dowolnego projektu. Lub umieść go w statycznej bibliotece. Tylko Mac OS X 10.6+ i iOS (wersja?).

#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

Mówiąc wprost, każdy obiekt staje się łatwym w użyciu słownikiem (dzięki NSMutableDictionary) tak szybko, jak tego potrzebujesz. Słownik jest zwalniany, gdy obiekt jest, a obiekty słownika są zwalniane po zwolnieniu słownika. To niesamowite, jak Apple zrobił to tak prosto.

Ostrzeżenie 1: Powyższy kod jest Włączono ARC. Jest dobrze przetestowany i jest używany w kilku wysyłanych produktach. Nie widziałem jeszcze żadnych wycieków pamięci ani problemów z wydajnością.

Ostrzeżenie 2: Zmień nazwy metod według własnego uznania, ale jeśli chcesz zachować nazwę, dodaj przedrostek. To jest kategoria na obiekcie głównym, ludzie. Niektóre klasy używają tej nazwy metody i nie chcesz ingerować! Moja biblioteka statyczna, którą zawieram w każdym projekcie, używa nazw metod associativeCCObjectForKey: i setAssociativeCCObject:forKey:.

Mam nadzieję, że to pomoże każdemu, kto chce mieć prostą userInfojak w przypadku każdego obiektu. Nie ma za co! :-)


15
2018-04-25 15:45



+1 dla eleganckiego podejścia - Frank C.
Miły. Nazwałem moją kategorię arbitrarobjectonanynsobjectlol. Ach ... kolizje nazw obiektów ... stackoverflow.com/a/1021040/129202 - Jonny
Mam problem z dodaniem obiektu asocjacyjnego do NSDate obiekty w ten sposób i stworzył nowe pytanie SO o tym: stackoverflow.com/questions/30308082/... - vomako
Fajnie i może być wykorzystanych wiele miejsc, aby zapewnić rzeczy .. +1 - Sandeep Singh


Działa to dla mnie, jeśli podaję literalny łańcuch c, taki jak "klucz" zamiast tworzenia statycznego znaku

Zamiast tego, biorąc pod uwagę to, co mówi Anomie, możesz zamiast tego:

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

Działa to dla wszystkiego, co pozwala na użycie arbitralnej pustki * (obserwacja, ta funkcja, itp.) I nie wymaga żadnych dodatkowych sztuczek statycznych. Ponadto (const void *) 0x314 jest ZAWSZE 0x314, bez względu na to, co robi kompilator.

Poza tym Anomie zaoszczędziłaś MNIE dużo pracy w aplikacji, nad którą teraz pracuję. Dzięki!


4
2017-08-08 23:33





Wymyśliłem prostsze rozwiązanie, które może pasować w pewnych okolicznościach. Ponieważ otrzymujesz kontekst NSAlertView po wywołaniu delegata, używam rzeczywistego adresu obiektu do utworzenia znacznika (NSString *), który następnie wykorzystuję do przechowywania niestandardowych wartości w globalnym lub specyficznym dla obiektu NSDictionary. Oto przykład:

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

W Delegacie:

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

Powołanie:

    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];

Klucze będą wyglądały jak "Tag-226811776". Mam nadzieję że to pomoże.


1
2018-01-20 16:00