texto teclados teclado tamaño predictivo para palabras eliminar diccionario descargar cambiar autocorrector aumentar aparece iphone objective-c uiview nsdictionary nscopying

iphone - teclados - ¿Vista como clave del diccionario?



teclados para iphone 6 (7)

Quiero tener un NSDictionary que mapea de UIView s a otra cosa.

Sin embargo, como UIViews no implementa el protocolo NSCopying , no puedo usarlos directamente como claves de diccionario.


Aquí está el código real (basado en la respuesta de luvieere y otra sugerencia de Yar):

// create dictionary NSMutableDictionary* dict = [NSMutableDictionary new]; // set value UIView* view = [UILabel new]; dict[[NSValue valueWithNonretainedObject:view]] = @"foo"; // get value NSString* foo = dict[[NSValue valueWithNonretainedObject:view]];


Aunque esto no es realmente para lo que están destinados, usted podría crear una interfaz funcional similar a un diccionario utilizando Referencias Asociativas :

static char associate_key; void setValueForUIView(UIView * view, id val){ objc_setAssociatedObject(view, &associate_key, val, OBJC_ASSOCIATION_RETAIN); } id valueForUIView(UIView * view){ return objc_getAssociatedObject(view, &associate_key); }

Incluso podrías envolver esto en una clase ThingWhatActsLikeADictionaryButWithKeysThatArentCopyable *; en ese caso, es posible que desee conservar las vistas que utiliza como claves.

Algo como esto (sin probar):

#import "ThingWhatActsLikeADictionaryButWithKeysThatArentCopyable.h" #import <objc/runtime.h> static char associate_key; @implementation ThingWhatActsLikeADictionaryButWithKeysThatArentCopyable - (void)setObject: (id)obj forKey: (id)key { // Remove association and release key if obj is nil but something was // previously set if( !obj ){ if( [self objectForKey:key] ){ objc_setAssociatedObject(key, &associate_key, nil, OBJC_ASSOCIATION_RETAIN); [key release]; } return; } [key retain]; // retain/release for obj is handled by associated objects functions objc_setAssociatedObject(key, &associate_key, obj, OBJC_ASSOCIATION_RETAIN); } - (id)objectForKey: (id)key { return objc_getAssociatedObject(key, &associate_key); } @end

* El nombre puede necesitar algún trabajo.


En lugar de almacenar un puntero a la vista y arriesgar el problema de la basura, simplemente asigne una etiqueta a UIView y almacene el valor de la etiqueta en el diccionario. Mucho más seguro.


Estoy usando una solución simple bajo ARC proporcionada por Objective-C ++.

MyClass.mm:

#import <map> @implementation MyClass { std::map<UIView* __weak, UIColor* __strong> viewMap; } - (void) someMethod { viewMap[self.someView] = [UIColor redColor]; }

En este ejemplo, estoy obteniendo una verificación de tipos más fuerte al hacer que todos los valores tengan que ser un UIColor* que es todo lo que necesitaba para esto. Pero también puede usar id como el tipo de valor si desea permitir cualquier objeto como el valor, ej: std::map<UIView* __weak, id __strong> viewMap; Del mismo modo para las teclas: id __weak, id __strong> viewMap;

También puede variar los __strong y __weak según sea necesario. En mi caso, las vistas ya están retenidas por el controlador de vista en el que uso esto, por lo que no vi la necesidad de apuntar con fuerza.


Puede usar un NSValue sosteniendo el puntero a UIView y usar esto como clave. NSValues son copiables. pero, si se destruye la vista, NSValue mantendrá un puntero no NSValue .


Siempre que no necesite soporte antes de iOS 6, NSMapTable (sugerido por nielsbot ) funciona bien porque puede proporcionar un enumerador sobre las claves de la colección. Eso es útil para el código común a todos los campos de texto, como configurar el delegado o sincronizar bidireccionalmente los valores de texto con una instancia de NSUserDefaults.

en viewDidLoad

self.userDefFromTextField = [NSMapTable weakToStrongObjectsMapTable]; [self.userDefFromTextField setObject:@"fooUserDefKey" forKey:self.textFieldFoo]; [self.userDefFromTextField setObject:@"barUserDefKey" forKey:self.textFieldBar]; // skipped for clarity: more text fields NSEnumerator *textFieldEnumerator = [self.userDefFromTextField keyEnumerator]; UITextField *textField; while (textField = [textFieldEnumerator nextObject]) { textField.delegate = self; }

A la vista, aparecerá:

NSEnumerator *keyEnumerator = [self.userDefFromTextField keyEnumerator]; UITextField *textField; while (textField = [keyEnumerator nextObject]) { textField.text = [self.userDefaults stringForKey:[self.textFields objectForKey:textField]]; }

en textField: shouldChangeCharactersInRange: replacementString:

NSString *resultingText = [textField.text stringByReplacingCharactersInRange:range withString:string]; if(resultingText.length == 0) return YES; NSString *preferenceKey = [self.textFields objectForKey:textField]; if(preferenceKey) [self.userDefaults setString:resultingText forKey:preferenceKey]; return YES;

Y ahora voy a llorar, porque implementé todo esto antes de darme cuenta de que mi aplicación orientada a iOS 5.1 no puede usarla. NSMapTable fue introducido en iOS 6.


una solución simple cuando solo desea UIView como clave de vez en cuando, lo uso para almacenar UILabel y UIColor

NSArray<UIView *> *views = @[viewA,viewB,viewC,viewD]; NSArray *values = @[valueA,valueB,valueC,valueD]; for(int i = 0;i < 4;i++) { UIView *key = views[i]; id value = values[i] //do something } id value = values[[views indexOfObject:key]]