以前にも似たような質問をしたことがありますが、今回は少し状況が異なります。
1 つには、今回は ARC を使用しています (まったく新しい問題の世界を招きます)。2番目: 私が持っているコードは基本的に機能しますが、より少ないコードでできるかどうか疑問に思っています。
現在、私のコードは次のようになっています。
__weak CustomType *Object;
void (^doAverage)(CustomType *, int, int) = ^(CustomType *Trigger, int Val1, int Val2) {
//Calculations with Trigger
}
CustomType *(^Add)(int, CustomType *) = ^(int Val1, CustomType *NewObject) {
//Checks prerequisites, and returns either the passed object after adding it to
//an array or nil, if the prerequisites haven't been met.
}
今、さらに下に、私はこれをやっています:
Object = Add(-1, [CustomType makeObjectWithParameters]);
[Object addCallback:^{ doAverage(Object, 56, 57); }];
内部addCallback
では、 への呼び出しで渡されたブロックにメッセージdoAverage
が送信さcopy
れ、後で実行するために保存されます。
これは機能し、保持サイクルはありません。オブジェクトの割り当てが解除されると、コールバックは折りたたまれます。
しかし、それは私が望むほど「エレガント」ではありません。
私が望むのは、次のようなものです。
__block __weak CustomType *Object;
CustomType *(^Add)(int, CustomType *) = ^(int Val1, CustomType *NewObject) {
//Checks prerequisites, and returns either the passed object after adding it to
//an array or nil, if the prerequisites haven't been met.
Object = NewObject;
}
そしてさらに下に:
[Add(-1, [CustomType makeObjectWithParameters]) addCallback:^{ doAverage(Object, 56, 57); }];
ただし、このようにするObject
と、コールバックに渡されたAdd
ものが最後に呼び出したものに変更されますが、これは私が望んでいるものではありません。
基本的に、参照を変数自体に渡すのではなく、ブロック内set
の値を取得してから、その参照をパラメーターとして渡す必要があります。Object
copy
Object
さらに、2 番目のステップとして、そもそもパラメーターを渡す必要がなく、ブロックで使用できれば、ほぼ完璧です。しかし、それを行うと、ブロックが最終的に呼び出されたときに、ブロック内の変数はデフォルトで nil になります (定義されたスコープの有効期限をかなり過ぎています)。
したがって、代わりに:
void (^doAverage)(CustomType *, int, int) = ^(CustomType *Trigger, int Val1, int Val2) {
//Calculations with Trigger
}
私は使用したい:
void (^doAverage)(int, int) = ^(int Val1, int Val2) {
//Calculations with Object
}
Object
その時点でどのような値(弱い参照) があったとしても。
2つのどちらかがどういうわけか可能ですか?
どうもありがとうございました。
編集:
以下の提案に従って、コードを次のようにリファクタリングしました。
typedef BOOL (^stackBlock_t)();
typedef BOOL (^CallBlock_t)(__weak id Object);
-(void) addCallback(CallBlock_t)B {
stackBlock_t stackBlock = ^{
__weak id Object = self;
return B(Object);
};
Callback = [stackBlock copy];
}
私はこのコンストラクトを次のように呼び出そうとしています:
[Add(-1, CustomType makeObjectWithParameters]) addCallBack:^{ doAverage(Object, 56, 57); }];
ただし、何らかの理由でブロックに対してObject
定義されてdoAverage
いません。その理由はよくわかりません。結局、これは type のブロックであり、 typeと nameCallBlock_t
のパラメーターを取ります。それでは、変数について「知っている」べきではありませんか?id
Object
Object
編集2:少しいじくり回した後(つまり、実際の型などを使用して)、別のエラーメッセージが表示されるようになりました: Incompatible block pointer types sending 'void (^)(void)' to parameter of type 'CallBlock_t'
、私はそうではありません。BOOL
そのブロックに a を返して引数を取ってもらいたいObject
...何が間違っているのですか?
編集3:私はそれを見つけたかもしれません。addCallback
通話に何かが欠けていました。まだテストしていませんが、次のように呼び出す必要があるようです。
[Add(-1, CustomType makeObjectWithParameters]) addCallBack:^(CustomObject *Object){ doAverage(Object, 56, 57); }];
考えてみれば、理にかなっている...目には恐ろしいですが、理にかなっています。そして、それは魅力のように機能します。型の余分な変数はもう必要ありません__block
。