Iniciar sesión

Ver la versión completa : Ayuda XCode: NSTableView y NSFormatter



swapd0
03/06/2013, 11:40
Hola, a ver si me podeis echar una mano.

Tengo un NSTableView donde puedo añadir direcciones y modificarlas, los objetos que meto en la tabla son del tipo Address, todo funciona bien, pero yo quiero que estas aparezcan en hexadecimal.

Mediante codigo (no se como hacerlo desde el IB) hago esto para asignarle el AddressFormatter a la tabla, con esto me aparecen la direcciones en hexadecimal.


- (void)setFormatter{
NSTableColumn *col = [mTableViewtableColumnWithIdentifier:@"address"];
AddressFormatter *fmt = [[AddressFormatteralloc] init];
[[col dataCell] setFormatter:fmt];
}


El problema es que cuando edito una direccion y le doy al Enter me aparecen estos mensajes de error.


2013-06-03 10:35:29.323 Disassembler68k[371:903] -[Address copyWithZone:]: unrecognized selector sent to instance 0x100558670
2013-06-03 10:35:29.335 Disassembler68k[371:903] Exception detected while handling key input.
2013-06-03 10:35:29.339 Disassembler68k[371:903] -[Address copyWithZone:]: unrecognized selector sent to instance 0x100558670


¿Que estoy haciendo mal?

Clase Address y AddressFormatter
Cabecera:

@interface Address : NSObject{
@private
int address;
}


- (id)initWithAddress:(int)a;


@property int address;


@end


@interface AddressFormatter : NSFormatter


- (NSString *)stringForObjectValue:(id)obj;
- (BOOL)getObjectValue:(id *)obj forString:(NSString *)string errorDescription:(NSString **)error;


@end



Implementacion:

#import "Address.h"

@implementation Address


//@synthesize address;


-(id)init
{
self = [superinit];
if (self)
address = 0;
returnself;
}


-(id)initWithAddress:(int)a
{
[self init];
address = a;
returnself;
}


-(void)dealloc
{
[superdealloc];
}


@end




@implementation AddressFormatter


- (NSString *)stringForObjectValue:(id)obj
{
NSException *error;
NSString *strValue;

// parameter check
if ( obj != nil )
{
// identify the type of object to be formatted
if ([obj isKindOfClass:[NSNumberclass]])
{
// convert the data to a string
strValue = [NSString stringWithFormat:@"%x", [obj intValue]];
}
else
{
// raise an exception
error = [NSExceptionexceptionWithName:NSInvalidArgumentExce ption
reason:@"Unsupported datatype"
userInfo:nil];
[error raise];
}
}
else
{
// raise an exception
error = [NSExceptionexceptionWithName:NSInvalidArgumentExce ption
reason:@"Nil argument"
userInfo:nil];
[error raise];
}
// return the formatting results
return strValue;
}


- (BOOL)getObjectValue:(id *)obj forString:(NSString *)string errorDescription:(NSString **)error
{
BOOL ok = NO;

// parameter check
if ( string != nil )
{
unsignedint val;
NSScanner *scanner = [[NSScanner alloc] initWithString:string];
if ( [scanner scanHexInt: &val] )
{
*obj = [[Address alloc] initWithAddress: val]; // ------- creo que esto esta mal
ok = (*obj != nil);
}
}


return ok;
}


@end

^MiSaTo^
03/06/2013, 12:10
Ese error que te da es básicamente porque necesitas implementar el protocolo NSCopying. No he trabajado con los AddressFormatters pero lo que te dice es básicamente que te falta por implementar eso ;)
Por otro lado, cuando declaras property, deberías indicar si la quieres nonatomic o atomic y en tu caso te recomendaría usar NSInteger en vez de un int para que no tengas problemas de casteos y demás entre dispositivos.

También veo que te creas una variable privada int address... para qué si ya tienes la property?
No se si estás usando ARC o no, pero yo cambiaría el código a esto:


interface Address : NSObject
property (nonatomic, assing, readonly) NSInteger address;

- (id)initWithAddress:(NSInteger)address;

@end
interface AddressFormatter : NSFormatter


- (NSString *)stringForObjectValue:(id)obj;
- (BOOL)getObjectValue:(id *)obj forString:(NSString *)string errorDescription:(NSString **)error;


@end



y


#import "Address.h"

@implementation Address


- (id)initWithAddress:(NSInteger)address {
if (self = [super init]){
_address = address;
}
return self;
}

- (id)init {
return [self initWithAddress:0];
}

// si estás usando ARC debes borrar este método.
-(void)dealloc
{
[super dealloc];
}

@end



@implementation AddressFormatter


- (NSString *)stringForObjectValue:(id)obj
{
NSException *error;
NSString *strValue;

// parameter check
if ( obj != nil )
{
// identify the type of object to be formatted
if ([obj isKindOfClass:[NSNumberclass]])
{
// convert the data to a string
strValue = [NSString stringWithFormat:@"%x", [obj intValue]];
}
else
{
// raise an exception
error = [NSExceptionexceptionWithName:NSInvalidArgumentExce ption reason:@"Unsupported datatype" userInfo:nil];
[error raise];
}
}
else
{
// raise an exception
error = [NSExceptionexceptionWithName:NSInvalidArgumentExce ption reason:@"Nil argument" userInfo:nil];
[error raise];
}
// return the formatting results
return strValue;
}


EDIT: mirando la clase NSFormatter (https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSFormatter_Class/Reference/Reference.html) veo que tiene el protocolo NSCopying, por lo que tendrás que implementar el copyWithZone. Aquí (http://stackoverflow.com/questions/4089238/implementing-nscopying) y Aquí (http://stackoverflow.com/questions/11391835/myclassname-copywithzone-unrecognized-selector-sent-to-instance) tienes dos ejemplos de cómo hacerlo

swapd0
03/06/2013, 22:10
Es que estoy aprendiendo el ObjetiveC/Cocoa de forma un poco desordenada, hace eones que mire lo de las propiedades y tengo que refrescar como van.

En general yo programo todo en C++, solo quiero el Cocoa/Objetive-C para hacer el interface de las aplicaciones.

Gracias por los consejos, ahora lo pruebo.

swapd0
03/06/2013, 23:37
Ok, todo va pero hay dos cosas raras.



tengo que implementar el metodo longLongValue porque si no lo hago al actualizar la tabla (-(id)tableView: (NSTableView *)tableView objectValueForTableColumn: (NSTableColumn *)tableColumn row: (NSInteger)row) dice que no lo encuentra en Address
En la clase donde guardo las direcciones (NSMutableArray) solo meto objetos del tipo Address pero el AddressFormatter se encuentra objetos de tipo Address y NSNumber...


A ver si le doy un repaso y voy corrigiendo cosas. Esta claro que debo de darle otro repaso al Objetive-C porque yo pensaba que con las propiedades te ahorrabas tener que implementar los metodos set/get, no sabia que tambien te añadian la variable a la clase.

-----Actualizado-----

PD: como estoy usando Snow Leopard parece que el compilador soporta ARC pero despues da un error de linkador porque falta la libreria... a este paso voy a tener que actualizar el mac.

swapd0
07/06/2013, 00:45
Ahora el problema es con el NSTextView...

¿Por que $%$!@# el NSTextView me capa las lineas a 80 columnas independientemente del tamaño de la ventana? Yo meto un texto en un std:: ostream y despues se lo paso al NSTextView asi:



[mTextView setString: [NSString stringWithUTF8String: outputStream]];


Pero me salen las lineas asi:


l000001 lea l000002,a7 ; 00001000
jsr l000003 ; 00001006
l000385 jsr l000381 ; 0000100c
bra.s l000385 ; 00001012
ds.b 785 ; 00001014
dc.b $f0,$00,$00,$e0,$00,$00,$00,$00,$07,$00,$00,$00,$0 0,$00,$00,$00
; 00001325
dc.b $04,$00,$9e,$00,$00,$00,$00,$00,$00,$00,$07,$00,$0 0,$00,$00,$00
; 00001335
dc.b $00,$00,$00,$00,$00,$00,$06,$00,$00,$00,$00,$00,$a 4,$ff,$ff,$ff
; 00001345



En vez de esto


l000001 lea l000002,a7 ; 00001000
jsr l000003 ; 00001006
l000385 jsr l000381 ; 0000100c
bra.s l000385 ; 00001012
ds.b 785 ; 00001014
dc.b $f0,$00,$00,$e0,$00,$00,$00,$00,$07,$00,$00,$00,$0 0,$00,$00,$00 ; 00001325
dc.b $04,$00,$9e,$00,$00,$00,$00,$00,$00,$00,$07,$00,$0 0,$00,$00,$00 ; 00001335
dc.b $00,$00,$00,$00,$00,$00,$06,$00,$00,$00,$00,$00,$a 4,$ff,$ff,$ff ; 00001345




Lo curioso es que si haces copy&paste del texto y despues lo pegas en otro editor te sale bien (como en el segundo caso).

^MiSaTo^
07/06/2013, 11:14
Tendrás que mirar las propiedades de NSTextView. Hay unos ejemplos de distintas maneras de formatear texto en los ejemplos que tiene Apple (y que se te bajan con el SDK).
Con esto no te puedo ayudar porque yo programo para iOS, no para Mac OS, y en iOS no hay NSTextView (hay otra clase parecida pero por lo que he visto, tienen distintos métodos)

swapd0
07/06/2013, 23:20
Ok, gracias por la pista, con esto ya va.


NSMutableParagraphStyle *parrafo = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[parrafo setLineBreakMode:NSLineBreakByClipping];
[mTextView setDefaultParagraphStyle:parrafo];




Jope, te pegas 1h mirando la documentacion y al final terminas escribiendo 3 lineas de codigo (y seguro que se puede hacer en menos).

Aun no me hago a la idea de que esten saparados en dos clases los objetos constantes y los objetos mutables (Ej NSParagraphStyle y NSMutableParagraphStyle, NSString y NSMutableString...)