Note that there are some explanatory texts on larger screens.

plurals
  1. POIs it possible to have a __block variable point to different objects, without altering the blocks copied before?
    primarykey
    data
    text
    <p>I've asked a similar question before, but this time the situation is a bit different.</p> <p>For one, this time around I'm using ARC (inviting a whole new world of problems). Second: The code I have basically works, but I'm wondering if I could do with less code.</p> <p>Right now, my code looks like this:</p> <pre><code>__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. } </code></pre> <p>Now, further down the line, I'm doing this:</p> <pre><code>Object = Add(-1, [CustomType makeObjectWithParameters]); [Object addCallback:^{ doAverage(Object, 56, 57); }]; </code></pre> <p>Inside <code>addCallback</code>, the passed block with the call to <code>doAverage</code> is sent a <code>copy</code> message and saved for later execution.</p> <p>This works, no retain cycles, the callbacks fold if the object is deallocated.</p> <p>But it's not 'as elegant' as I'd like.</p> <p>What I'd like would be something along these lines:</p> <pre><code>__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; } </code></pre> <p>And further down the line:</p> <pre><code>[Add(-1, [CustomType makeObjectWithParameters]) addCallback:^{ doAverage(Object, 56, 57); }]; </code></pre> <p>However if I do it like this, it'll change the <code>Object</code> passed to the callback to whatever <code>Add</code> I called last, which isn't what I want.</p> <p>Basically I'd need to <code>set</code> the value of <code>Object</code> in a block and then <code>copy</code> that reference as a parameter, instead of passing the reference to the variable itself.</p> <p>Furthermore, as a second step, it'd be about perfect, if I didn't have to pass the parameter <code>Object</code> in the first place, but could use it in the block. But if I do that, the variable in the block will default to nil when the block is finally called (well past the expiration of the scope it was defined in).</p> <p>So instead of:</p> <pre><code>void (^doAverage)(CustomType *, int, int) = ^(CustomType *Trigger, int Val1, int Val2) { //Calculations with Trigger } </code></pre> <p>I'd like to do use:</p> <pre><code>void (^doAverage)(int, int) = ^(int Val1, int Val2) { //Calculations with Object } </code></pre> <p>With whatever value <code>Object</code> (weak reference) had at that moment in time.</p> <p>Is either of the two somehow possible?</p> <p>Thank you very much.</p> <p>Edit:</p> <p>Following the below suggestion, I refactored my code like this:</p> <pre><code>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]; } </code></pre> <p>I'm trying to call this construct with:</p> <pre><code>[Add(-1, CustomType makeObjectWithParameters]) addCallBack:^{ doAverage(Object, 56, 57); }]; </code></pre> <p>However <code>Object</code> isn't defined for the <code>doAverage</code> block for some reason, and I don't quite know why. After all, it's a block of type <code>CallBlock_t</code>, which takes a parameter of type <code>id</code> and the name <code>Object</code>. Shouldn't it 'know' about the variable <code>Object</code> then?</p> <p>Edit 2: After a bit of tinkering around (namely using the actual type and stuff), it now gives me a different error message: <code>Incompatible block pointer types sending 'void (^)(void)' to parameter of type 'CallBlock_t'</code>, though I'm not. I want that block to return a <code>BOOL</code> and take the argument <code>Object</code>...what am I doing wrong?</p> <p>Edit 3: I may have found it. I was missing something in my <code>addCallback</code> call. I have yet to test it, but it would seem, that I'm required to call it like this:</p> <pre><code>[Add(-1, CustomType makeObjectWithParameters]) addCallBack:^(CustomObject *Object){ doAverage(Object, 56, 57); }]; </code></pre> <p>Thinking about it, it makes sense...it's horrible on the eyes, but it makes sense. And it works like a charm. I don't even need excess variables of type <code>__block</code> any more.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload