Tag Archives: blocks

self does not hold strong ref to dispatch_async

ref – https://digitalleaves.com/blog/2015/05/demystifying-retain-cycles-in-arc/

Examples of non-cycles

      Using dispatch_async as the example is misleading as self does not hold a strong reference to it so, there is no threat of a retain cycle.

    • The block retains self, but self doesn’t retain the block. If one or the other is released, no cycle is created and everything gets deallocated as it should.

    How you get into trouble

    Where you get into trouble is something like:

    Now, your object (self) has an explicit strong reference to the block. And the block has an implicit strong reference to self. That’s a cycle, and now neither object will be deallocated properly.

Block Property use copy or strong

ref –
http://stackoverflow.com/questions/27152580/cocoa-blocks-as-strong-pointers-vs-copy

Short Answer

The answer is it is historical, you are completely correct that in current ARC code there is no need to use copy and a strong property is fine. The same goes for instance, local and global variables.

Long Answer

Unlike other objects a block may be stored on the stack, this is an implementation optimisation and as such should, like other compiler optimisations, not have direct impact on the written code. This optimisation benefits a common case where a block is created, passed as a method/function argument, used by that function, and then discarded – the block can be quickly allocated on the stack and then disposed of without the heap (dynamic memory pool) being involved.

Compare this to local variables, which
(a) created on the stack
(b) are automatically destroyed when the owning function/method returns and
(c) can be passed-by-address to methods/functions called by the owning function.

The address of a local variable cannot be stored and used after its owning function/method has return – the variable no longer exists.

However objects are expected to outlast their creating function/method. So unlike local variables, objects are allocated on the heap and are not automatically destroyed based on their creating function/method returning but rather based on whether they are still needed (used) – and “need” here is determined automatically by ARC these days.

So what about Blocks?

Creating a block on the stack may optimise a common case but it also causes a problem – if the block needs to outlast its creator, as objects often do, then it must be moved to the heap before its creating method’s local stack is destroyed.

When the block implementation was first released the optimisation of storing blocks on the stack was made visible to programmers as the compiler at that time was unable to automatically handle moving the block to the heap when needed – programmers had to use a function block_copy() to do it themselves.

While this approach might not be out-of-place in the low-level C world (and blocks are C construct), having high-level Objective-C programmers manually manage a compiler optimisation is really not good. As Apple released newer versions of the compiler improvements where made. Early on it programmers were told they could replace block_copy(block) with [block copy], fitting in with normal Objective-C objects. Then the compiler started to automatically copy blocks off stack as needed, but this was not always officially documented.

There has been no need to manually copy blocks off the stack for a while, though Apple cannot shrug off its origins and refers to doing so as “best practice” – which is certainly debatable. In the latest version, Sept 2014, of Apple’s Working with Blocks, they stated that block-valued properties should use copy, but then immediately come clean (emphasis added):

Note: You should specify copy as the property attribute, because a block needs to be copied to keep track of its captured state outside of the original scope. This isn’t something you need to worry about when using Automatic Reference Counting, as it will happen automatically, but it’s best practice for the property attribute to show the resultant behavior.
There is no need to “show the resultant behavior” – storing the block on the stack in the first place is an optimisation and should be transparent to the code – just like other compiler optimisations the code should gain the performance benefit without the programmer’s involvement.

So as long as you use ARC and the current Clang compilers you can treat blocks like other objects, and as blocks are immutable that means you don’t need to copy them. Trust Apple, even if they appear to be nostalgic for the “good old days when we did things by hand” and encourage you to leave historical reminders in your code, copy is not needed.

Objective C stack and heap

https://mikeash.com/pyblog/friday-qa-2010-01-15-stack-and-heap-objects-in-objective-c.html

Stack
  • The stack is a region of memory which contains storage for local variables, as well as internal temporary values and housekeeping.
  • On a modern system, there is one stack per thread of execution.
  • When a function is called, a stack frame is pushed onto the stack, and function-local data is stored there.
  • When the function returns, its stack frame is destroyed.
Heap

The heap is, essentially, everything else in memory.

  • Memory can be allocated on the heap at any time, and destroyed at any time.
  • You have to explicitly request for memory to be allocated from the heap, and if you aren’t using garbage collection, explicitly free it as well.
  • This is where you store things that need to outlive the current function call. The heap is what you access when you call malloc and free.

Stack vs Heap Objects

Given that, what’s a stack object, and what’s a heap object?

First, we must understand what an object is in general. In Objective-C (and many other languages), an object is simply a contiguous blob of memory with a particular layout.

The precise location of that memory is less important. As long as you have some memory somewhere with the right contents, it’s a working Objective-C object. In Objective-C, objects are usually created on the heap:

NSObject *obj = [[NSObject alloc] init];

The storage for the obj pointer variable itself is on the stack
but the object it points to is in the heap.
In other words, the obj pointer variable is pushed onto the stack. The NSObject object that it points to, is allocated on the heap

The [NSObject alloc] call allocates a chunk of heap memory, and fills it out to match the layout needed for an NSObject.

Using NS Collection classes with blocks

Since Blocks are objective C objects that gets pushed onto the stack…

A Block is the one instance of an Objective-C object that starts on the stack. While you can happily collect together a bunch of Blocks in one of the Foundation provided collection classes (NSArray, NSDictionary, or NSSet), make sure you copy the Block before you do!

The last thing you want is a stack based object to end up in an autorelease pool….

The reason why Blocks start on the stack is because it is really really fast. Orders of magnitude faster than allocating a chunk of memory for each Block.

other ref-

http://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap

block with return value

Logic.h

Logic.m

…then when you access the method call with your own block definition like so:

How it runs through…

First, the code runs until it hits return userPwdChangedBlk(TRUE, newPwd);

We get the new password, then pass in TRUE, and the new password so the block of the caller can run.

So in the outside processSave method, the TRUE and new password gets passed into the parameter, and you evaluate it. Then return TRUE or FALSE.

This return from the onSuccess block will be the result of

in Logic.m’s

Using Block in Objective C by example

Overview

Say we have a class called SPFPriceFetcher that uses JCDHTTPConnection.

SPFPriceFetcher
|
|—JCDHTTPConnection

JCDHTTPConnection uses NSURLConnection connection where any data, finish loading, or response received would have to give feedback BACK to SPFPriceFetcher. We give feedback by retaining and using block definitions passed in from SPFPriceFetcher.

Passing block definitions from parent (SPFPriceFetcher) to child (JCDHTTPConnection)

Basically what happens is that SPFPriceFetcher provides block definitions for JCDHTTPConnection to retain and use:

SPFPriceFetcher — OnSuccess block definition —-> JCDHTTPConnection
SPFPriceFetcher — OnFailure block definition —-> JCDHTTPConnection
SPFPriceFetcher — OnDidSendData block definition —-> JCDHTTPConnection

where the block interface is defined in JCDHTTPConnection.h as:

Using blocks

1) When you declare a method interface that takes such block definitions, you need to have the block interface as defined by the typedefs above.

JCDHTTPConnection.h

Then in your block definition, you would use the block definitions as a variable. In our definition, we retain them:

JCDHTTPConnection.m

Now when the NSURLConnection runs to connectionDidFinishLoading, we use our retained block definitions and call them:

For example, self.onSuccess will call the block definitions you retained that was passed in from SPFPriceFetcher earlier. It will pass the needed parmaters NSHTTPURLResponse (self.response) and NSString * (self.body) in for it to process.

In SPFPriceFetcher.m, we pass in the block definition like so:

As you can see, when we provide block definitions, we simply use “^” to denote that its a block, and then use the block interface and continue with the code implementation. We just have to make sure to match the block interface.

For example, in our case we know that OnSuccess block takes is defined as:

OnSuccess block definition

and thus, we first denote “^” as a block, then match the block interface by having the parameters be NSHTTPURLResponse and NSString. We then write the method implementation.

OnSuccess block definition we pass in:

OnFailure block definition

Same thing with the OnFailure block definition.
We first note “^” to denote that its a block definition. Then we provide the interface needed by the OnFailure block definition as shown:

OnFailure block definition we pass in: