iOS interview series 2018
ios interview questions swift
Blocks in Objective C
As it seems finding out interview question and its answer is easy but what i feel difficult is that gaining expertise from those questions and using it in real life, to become successful iOS developer.
I am going to create a series of blogs so that every one can learn together and grow.
Chapter 1:
So let’s start with “Blocks in Objective C” -
Blocks should not be confused with Grand Central Dispatch (GCD): GCD is primarily a queue library, which typically uses blocks.
Let’s breakdown the two primary types of block syntax:
- Block literals
- Block pointers
Block literals are defined inline with your code. Here is an example of directly calling a method, passing a block literal as an argument:
NSUInteger foundAtIndex = [someArray indexOfObjectPassingTest:^ BOOL (id object, NSUInteger idx, BOOL *stop) {
return [object hasPrefix:@"SOME_PREFIX"];
}];
Block pointers look similar to function pointers, but use the ^ (caret) instead of the * (asterisk/star/splat). Here is an example of assigning a block literal to a block pointer:
// checkMatch is a block pointer that we assign to.
BOOL (^checkMatch)(id, NSUInteger, BOOL *) = ^ BOOL (id object, NSUInteger idx, BOOL *stop) {
return [object hasPrefix:@"SOME_PREFIX"];
};
NSUInteger foundPrefixAtIndex = [someArray indexOfObjectPassingTest:checkMatch];
Declaring a Block Reference
Syntax for declaring single block : return_type (^ block-name) (argument); Syntax for declaring array of blocks : return_type (^ block-name[block-count]) (argument);
void (^blockReturningVoidWithVoidArgument)(void);
int (^blockReturningIntWithIntAndCharArguments)(int, char);
void (^arrayOfTenBlocksReturningVoidWithIntArgument[10])(in
Note:-
1. Blocks also support variadic (…) arguments.
2.
You can also create types for blocks — doing so is generally
considered to be best practice when you use a block with a given
signature in multiple places:
typedef float (^MyBlockType)(float, float);
MyBlockType block1 = // ... ;
MyBlockType block2 = // ... ;
Use __block Variables to Share Storage
As noted, trying to assign a new value to
x
within the
block would result in an error:
int x = 100; //Wrong , Correct one -__block
int x = 100;
//Defining a block
void (^AddXAndY)(int) = ^(int y) {
x = x + y; // error
printf("%d %d\n", x, y);
};
To allow a variable to be changed within a block, you use the
__block
storage type modifier.
Note:
There are two further restrictions on
__block
variables: they cannot be variable length arrays, and cannot be
structures that contain C99 variable-length arrays.
You Can Pass Blocks as Arguments to Methods or Functions
The declaration for the
beginTaskWithCallbackBlock:
method shown in this example would look like this:
- (void)beginTaskWithCallbackBlock:(void (^)(void))callbackBlock;
The
(void (^)(void))
specifies that the parameter is a block that doesn’t take any
arguments or return any values. The implementation of the method
can invoke the block in the usual way:
- (void)beginTaskWithCallbackBlock:(void (^)(void))callbackBlock {
callbackBlock();
}
Objects Use Properties to Keep Track of Blocks
The syntax to define a property to keep track of a block is similar to a block variable:
typedef void (^XYZSimpleBlock)(void);
@interface XYZObject : NSObject
@property (copy) XYZSimpleBlock blockProperty;
@end
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.
Avoid Strong Reference Cycles when Capturing self
it’s best practice to capture a weak reference to
self
, like
this:
- (void)configureBlock {
XYZBlockKeeper * __weak weakSelf = self;
self.block = ^{
[weakSelf doSomething]; // capture the weak reference
// to avoid the reference cycle
}
}
By capturing the weak pointer to
self
, the block
won’t maintain a strong relationship back to the
XYZBlockKeeper
object. If that object is deallocated before the block is
called, the
weakSelf
pointer will simply be set to
nil
.
Blocks + Concurrent Tasks
iOS offer a variety of technologies for concurrency, including
two task-scheduling mechanisms: Operation queues and Grand
Central Dispatch.
These mechanisms revolve around the idea
of a queue of tasks waiting to be invoked. You add your blocks
to a queue in the order you need them to be invoked, and the
system dequeues them for invocation when processor time and
resources become available. Use the
NSBlockOperation
to create an operation using a block, like this:
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
...
}];
It’s possible to execute an operation manually but operations are usually added either to an existing operation queue or a queue you create yourself, ready for execution:
// schedule task on main queue:
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
[mainQueue addOperation:operation];
// schedule task on background queue:
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation];
Debugging
You can set breakpoints and single step into blocks. You can
invoke a block from within a GDB session using
invoke-block
,
as illustrated in this example:
$ invoke-block myBlock 10 20
That’s all about block!! its time for you to play with blocks and try about blocks.
Hope this article is useful for people looking to gain knowledge as well as clear interview, Please ❤️ to recommend this post to others 😊. Let me know your feedback. :)