1

我正在尝试使用 Obj-C 块并尝试创建一个包含两个块的结构,其中一个块用于更改另一个块的功能。

这是一种非常迂回的方法来做一些简单的事情......并且可能有更好的方法来做到这一点,但练习的重点是让我理解块。这是代码,它不起作用,所以我错过/不理解和/或做错了什么?

//enumerate my math operation options so i can have something more understandable
//than 0, 1, 2, etc... also makes it easier to add operations, as opTypeTotal
//will be 1 plus the index of the operation before it.
typedef enum
{
 opTypeAdd = 0,
 opTypeSubtract = 1,
 opTypeTotal
} opType; 

//not sure if (struct someMathStruct)* is correct, probably is wrong
//the intent is to pass a pointer to someMathStruct, but the compiler
//won't know about its existance until a few lines later...
typedef (void)(^changeBlock)(opType,(struct someMathStruct)*);
typedef (void)(^mathBlock)(int,int,int*);

//hold two blocks, to be defined later at runtime
typedef struct someMathStruct{
 mathBlock doMath;
 changeBlock changeOperation;
} SomeMath;

//i want to declare an array of blocks of type mathBlock
//the intent is to have the array index to correspond with the opTypes enumerated above
//almost certain i'm doing this wrong
mathBlock *m[opTypeTotal] = malloc(sizeof(mathBlock *)*opTypeTotal);

//just two simple math operations as blocks
m[opTypeAdd] = ^(void)(int a,int b,int *result){*result = a+b;};
m[opTypeSubtract] = ^(void)(int a,int b,int *result){*result = a-b;};

//this block is what's supposed to change the other block in the struct
//it takes an opType, and a pointer to the SomeMath struct
//is this the right way to access the member variables of the struct?
changeBlock changeMe = ^(void)(opType a, SomeMath *b) {
  //should make adding operations as easy as just adding cases
 switch (a)
 {
  case opTypeAdd: *b.doMath=m[a]; break;
  case opTypeSubtract:
  default:  *b.doMath=m[a];  //catch-all goes to subtracting
 }
}

...

SomeMath mathFun;
int theTotal = 0;  //a test int to work with

//do i need to copy the changeMe block?
//or can i just do what i'm doing here as the block itself isn't unique
mathFun.changeOperation = changeMe;

mathFun->changeOperation(opTypeAdd, &mathFun);
mathFun->doMath(theTotal,11,&theTotal); //result should be 11

mathFun->changeOperation(opTypeSubtract, &mathFun);
mathFun->doMath(theTotal,3,&theTotal); //result should be 8

NSLog(@"the result: %d",theTotal); //should output "the result: 8"
4

1 回答 1

1

修复编译错误后,代码似乎可以按预期工作(结果为 8):

编译:gcc -o test test.m -framework Foundation

#import <Foundation/Foundation.h>

//enumerate my math operation options so i can have something more understandable
//than 0, 1, 2, etc... also makes it easier to add operations, as opTypeTotal
//will be 1 plus the index of the operation before it.
typedef enum
{
 opTypeAdd = 0,
 opTypeSubtract = 1,
 opTypeTotal
} opType; 

struct someMathStruct; // Forward declare this as a type so we can use it in the 
                       // changeBlock typedef

typedef void (^changeBlock) (opType,struct someMathStruct*);
typedef void (^mathBlock) (int,int,int*);

//hold two blocks, to be defined later at runtime
typedef struct someMathStruct{
 mathBlock doMath;
 changeBlock changeOperation;
} SomeMath;


int main()
{

    //i want to declare an array of blocks of type mathBlock
    //the intent is to have the array index to correspond with the opTypes
    // enumerated above
    mathBlock *m = calloc(opTypeTotal, sizeof(mathBlock *));

    //just two simple math operations as blocks
    m[opTypeAdd] = ^(int a,int b,int *result){*result = a+b;};
    m[opTypeSubtract] = ^(int a,int b,int *result){*result = a-b;};

    changeBlock changeMe = ^(opType a, SomeMath *b) {
      //should make adding operations as easy as just adding cases
     switch (a)
     {
      case opTypeAdd: b->doMath = m[a]; break;
      case opTypeSubtract:
      default:  b->doMath = m[a];  //catch-all goes to subtracting
     }
    };

    SomeMath mathFun;
    int theTotal = 0;  //a test int to work with

    mathFun.changeOperation = changeMe;

    mathFun.changeOperation(opTypeAdd, &mathFun);
    mathFun.doMath(theTotal,11,&theTotal); //result should be 11

    mathFun.changeOperation(opTypeSubtract, &mathFun);
    mathFun.doMath(theTotal,3,&theTotal); //result should be 8

    NSLog(@"the result: %d",theTotal); //should output "the result: 8"
}
于 2009-10-17T00:52:01.880 回答