AVISO: Cualquier pregunta que no cumpla ninguno de estos criterios podrá ser borrada sin previo aviso.

Hola, Tengo una clase que deriva de NSManagedObject la cual tiene un block para satisfacer unas llamadas asíncronas. Cuando trato de invocar a este block tras cargar mi NSManagedObject me da un error de acceso a memoria. No esta persistido. Me gustaría si pudiera ser guardarme el block y no tener que settearlo cada vez. ¿Alguna idea al respecto?

Mi clase seria algo así:

@interface EnergyEntry : NSManagedObject{
    void (^datablock)(NSMutableArray *listRegister);
}

-(void) setBlock: (void (^)(NSMutableArray *listRegister))block;
- (void)invokeWithData: (NSMutableArray *)listRegister;

@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSNumber * value;
@property (nonatomic, retain) NSManagedObject * board;

#import "EnergyEntry.h"

@implementation EnergyEntry

@dynamic name;
@dynamic value;
@dynamic board;

-(void) setBlock: (void (^)(NSMutableArray *listRegister))block
{
        datablock = block;
}

- (void)invokeWithData: (NSMutableArray *)listRegister{
    datablock(listRegister);
}

@end

preguntado 09 Mar '12, 12:27

Wego's gravatar image

Wego
61238


Te tienes que hacer una copia del bloque, y además como lo vas a tratar como una variable con set y get deberías crearte una propiedad. Y para mayor facilidad de uso te podrías crear también un typedef para nombrar el tipo de ese bloque:

El typedef:

typedef void (^DataBlockType)(NSMutableArray *listRegister);

Propiedad:

@property (nonatomic, copy) DataBlockType * dataBlock;

El método setBlock ya no te haría falta, desde el código harías:

anEneryEntry.dataBlock = ^{...};

Y luego para usarlo dentro de la clase llámalo con self:

- (void)invokeWithData: (NSMutableArray *)listRegister{
    self.datablock(listRegister);
}

Por último tendrías que liberarlo en el dealloc con [dataBlock release];

Muy importante el COPY de la propiedad, si no quisieras hacerte propiedad tendrías que hacer

datablock = [block copy];

Pero con esto tendrías memory leaks, porque no liberas el bloque anterior si haces varias asignaciones y al liberar tu objeto manejado.

Los bloques se guardan en el stack, como cuando pasas variables en los argumentos de los métodos, si te quieres guardar uno permanentemente tienes que hacer una copia al heap.

Espero que esto te solucione tus problemas, y si es así pues vota :)

enlace permanente

respondido 10 Mar '12, 08:45

LightMan's gravatar image

LightMan
1.7k4617

Hola,

He estado probando un poco lo que me comentabas pero me salta un error de memoria al invocar al bloque. "EXC_BAD_ACCESS" El bloque lo estoy guardando como un atributo Transformable y Transient en el modelo.

Si NO lo marco como transient me salta una excepción del tipo, creo q es necesario ponerlo como transient:

-[__NSStackBlock__ encodeWithCoder:]: unrecognized selector sent to instance 0xbfffd930

Por cierto, estoy con iOS 5 SDK con ARC activado. Resumo un poco el código q tengo metido:

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@class ModbusRegister, Board;
typedef void (^DataBlockType)(NSArray *listRegister);

@interface EnergyEntry : NSManagedObject
- (void)invokeWithData: (NSArray *)listRegister;

@property (nonatomic, copy) DataBlockType  datablock;

@end

#import "EnergyEntry.h"

@implementation EnergyEntry

@dynamic datablock;

- (void)invokeWithData: (NSArray *)listRegister{

    self.datablock(listRegister);
}

@end

Cuando almaceno el bloque seria algo asi:

    [energyEntry setValue:@"Energía activa" forKey:@"name"];
    [energyEntry setValue:[NSNumber numberWithDouble:0] forKey:@"value"];
    [energyEntry setValue:currentBoard forKey:@"board"];

    [energyEntry setValue:^(NSArray *listRegister){
        //...mis operaciones en el bloque
    } forKey:@"datablock"];

Finalmente cuando invoco al bloque q es donde salta en error:

NSArray *listRegister=... //mi array preparado
[energyEntry invokeWithData:listRegister];

Disculpa si se me escapa algo básico pues llevo poco tiempo en el mundillo iOS. Y muchas grácias ante todo.

enlace permanente

respondido 16 Mar '12, 17:55

Wego's gravatar image

Wego
61238

No sé si se pueden guardar los bloques en core data... ¿Has visto en algún sitio que se puedan guardar?

(16 Mar '12, 19:06) LightMan
Tu respuesta:
Activar/desactivar vista previa

Sobre esta pregunta

Etiquetas de la pregunta:

×20
×14
×4
×3

Pregunta realizada el: 09 Mar '12, 12:27

Pregunta visitada: 340 veces

Última modificación: 16 Mar '12, 19:06

Seguir esta pregunta

Por Email:

Una vez que entres podrás suscribirte desde aquí para recibir actualizaciones

Por RSS:

Respuestas

Respuestas y Comentarios

Realizar Donación