Objective-C-2 Flashcards

1
Q

How do dispatch queues work?

A

1) Create a queue or use the provided system queue (global)
2) add a task to the queue, either async or sync by calling dispatch_async() or dispatch_sync()
3) The queues operate in FIFO order

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_async(queue, ^{

NSLog(@"Block for asynchronous execution");

});

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

How many concurrent dispatch queues does the system provide?

A

Four global, differentiated by priority level.

DISPATCH_QUEUE_PRIORITY_DEFAULT
DISPATCH_QUEUE_PRIORITY_HIGH
DISPATCH_QUEUE_PRIORITY_LOW
DISPATCH_QUEUE_PRIORITY_BACKGROUND

Create a queue: dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Why might you use autorelease in an ARC context?

A

If in a block of code you’re allocating lots of Objective-C objects surround parts of the code with autorelease blocks to free memory.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Why use serial queues?

A

To ensure statements execute in specified order.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Create a custom serial queue

A

dispatch_queue_t queue;

queue = dispatch_queue_create(“com.example.MyQueue”, NULL);

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

How do you test the identity of a queue (for debugging)?

A

dispatch_get_current_queue. Call from inside a block object to return the queue to which the block was submitted.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

What is the concurrent looping construct available?

A

dispatch_apply (or dispatch_apply_f)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Add a cleanup function to a serial queue?

A

dispatch_set_finalizer_f

dispatch_queue_t serialQueue = dispatch_queue_create(“com.example.CriticalTaskQueue”, NULL);

dispatch_set_context(serialQueue, data);

dispatch_set_finalizer_f(serialQueue, &myFinalizerFunction);

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

What does the cleanup function do?

A

executes and cleans up context data associated with the queue (only called if the context pointer isn’t NULL)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Replace the following loop with a concurrent loop:

for (i = 0; i < count; i++) {

printf(“%u\n”,i);

}

A

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_apply(count, queue, ^(size_t i) {

printf(“%u\n”,i);

});

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

How do you perform tasks on the main queue?

A

dispatch_get_main_queue

You can get the dispatch queue for your application’s main thread by calling the dispatch_get_main_queue function. Tasks added to this queue are performed serially on the main thread itself.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Using Grand Central Dispatch (GCD) you have an automatic autorelease pool inside the executing block. Would you need another one for any reason?

A

Yes, if you want to immediately release objects at the end of each loop for example, surround it with autorelease block.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

How do you suspend a queue?

A

call dispatch_suspend then dispatch_resume. These calls must match.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Why would you want to use Dispatch Groups instead of Dispatch Queue?

A

Use dispatch groups when you want to accomplish a set of work and cannot progress until it’s complete.

Dispatch groups block a thread until one or more tasks are complete

Instead of dispatching tasks to a queue using the dispatch_async function, you use the dispatch_group_async function instead. This function associates the task with the group and queues it for execution.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

What are the steps required to use a dispatch group?

A

1) get the global queue:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

2) Create the dispatch group:
dispatch_group_t group = dispatch_group_create();

3) Add the group to the queue:
dispatch_group_async(group, queue, ^{

// Some asynchronous work

});

4) Wait on the group:
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

5) Release the group:
dispatch_release(group);

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

What is the GCD synchronous call to dispatch a block to a queue?

A

dispatch_sync

dispatch_sync(queue, ^{
NSLog(@”HELLO”);
});

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

What is basic Class interface syntax?

A

@interface MyClass:NSobject

@end

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

How do you declare private variables in a class without using a private keyword? What are private variables known as?

A

Put them in the implementation file inside curly braces:

@implementation Person{
int age;
NSString *name;
}

Known as iVars.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

Can you create a private variable in a class with a private keyword? public?

A

Yes, use the @private, @protected, or @public keywords. These are visibility modifiers though - two instances of a class can access all of each others variables, including private, no issues. These modifiers only affect the INHERITED classes.

Declare the variables in the implementation (to hide them), inside curly braces:

@implementation SampleClass{

NSMutableArray *myArr;

@private
int test;

@public
int test2; } @end
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

Can you use self to access an iVar?

A

No, self is only for properties. Refer directly to an iVar.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

Why wouldn’t you put iVars into the interface file?

A

1) exposes implementation to end user
2) adding/changing/removing an iVar from the header makes compilation take longer: each .m file that imports the interface needs recompilation.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
22
Q

What is the default when a @property is declared in terms of properties?

A

readwrite
strong
atomic
getter/setter synthesized automatically

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
23
Q

Are these declarations the same?

@property NSArray *name;
@property (strong, atomic, readwrite) NSArray *name;

A

yes

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
24
Q

What should a primitive type attribute be set to?

A

Assign

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
25
Q

Describe an appropriate parent->child relationship?

A

Parent has strong pointer to child and child shouldn’t have strong back to parent or there’s a retain cycle.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
26
Q

What does the copy attribute do?

A

A variable/property with the copy attribute does not get a reference to the original assignment. It gets a copy of the value of that reference. When the actual referenced variable is changed it does not get reflected in the copy variable.

@property (nonatomic,copy) NSString *lastName;

NSString *str = @"HELLO";
model.lastName = str;
// model.lastname = HELLO
str = @"Goodbye"
//model.lastName still = HELLO, reference doesn't change it
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
27
Q

What does the atomic attribute do?

A

prevents concurrent access to an object by multiple threads.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
28
Q

What does nonatomic attribute do?

A

No guarantee what happens if value is accessed simultaneously from different threads.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
29
Q

Is it faster to access an atomic or non-atomic property?

A

Faster for non-atomic

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
30
Q

What are the two access attributes?

A

readonly, readwrite.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
31
Q

What does weak attribute signify? What are they best used on?

A

keep the object in memory as long as someone else holds a strong pointer to it. When the other that holds the strong pointer is set to nil, if the retain count of the object is 0, then the weak pointer is set to nil and the object is destroyed.

Delegates
IBOutlets, Subviews- (strongly held by superview)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
32
Q

Declare a weak IBOutlet to a UILabel?

A

__weak IBOutlet UILabel *titleLabel

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
33
Q

Declare a weak property to a delegate of type SampleDelegate

A

@property (weak, nonatomic) id sDelegate;

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
34
Q

What is unsafe_unretained?

A

It specifies a reference that does not keep the referenced object alive and is not set to nil when there are no strong references to the object. If the object it references is deallocated, the pointer is left dangling.. ARC doesn’t maintain control over memory of unsafe-unretained variables.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
35
Q

How to set a custom name for a getter and setter?

A

@property (nonatomic, strong, getter=getTestProperty, setter=setTestProperty:) NSString *testProperty;

Define the custom methods in the header and implement in implementation.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
36
Q

What must you do to write a custom getter and setter when declaring a property?

A

Ensure nonatomic
@interface Customer
@property (nonatomic) NSString* name;
@end

//Synthesize assigning a new name w/underscore
@synthesize name = _name;  //Must do this
//Implement the methods
//Setter method
- (void) setName:(NSString *)n {
    NSLog(@"Setting name to: %@", n);
    _name = [n uppercaseString];
}
//Getter method
- (NSString*) name {
    NSLog(@"Returning name: %@", _name);
    return _name;
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
37
Q

What does the following mean: @synthesize mushroom = _mushroom;

A

@synthesize tells the compiler that _mushroom backs up the property mushroom for the mushroom and setMushroom methods, that instance variable should be created if not yet.

@interface Badger : NSObject ()
@property (nonatomic) Mushroom *mushroom;
@end

@implementation Badger;
@synthesize mushroom = _mushroom;
- (Mushroom *)mushroom
{ 
    return _mushroom;
}
- (void)setMushroom:(Mushroom *)mush
{
    _mushroom = mush;
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
38
Q

Given the following declaration how can you access and set the name property?

@property (nonatomic,strong) NSString* name;

Which is direct access and which is through the auto-generated setter and getter methods?

A

_name = @”HELLO”;

OR

self.name = @”HELLO”;

self uses the setter
_name directly accesses the property

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
39
Q

Declare a static class method that takes in an NSString variable, void return?

A
\+ (void) myStaticFunction:(NSString *)myStr{
   //do stuff
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
40
Q

Declare a static variable of type NSString named url? Where does it go, the Implementation or Interface?

A

static NSString *url = @”something”;

Goes in the implementation outside the curly braces.

@implementation SampleClass{

NSMutableArray *myArr;

@private
int test;

@public
int test2;

}
static NSString *url = @”something”;

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
41
Q

Whats the difference between Static and Extern keywords?

A

Static makes methods and variables globally visible in a single file.

Extern makes them globally visible across all files.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
42
Q

Declare an enum named direction that has four directions as options? Then assign it to a variable named currentDirection.

A

enum direction{north, south, east, west};

enum direction currentDirection = south;

43
Q

Assign explicit values to an enum named direction that has all four directions as types

A

enum direction {north=1, south = 2, west = 5, east=6};

44
Q

Assign explicit values to an enum named direction that has all four directions as types

A

enum direction {north=1, south = 2, west = 5, east=6};

45
Q

Name some preprocessor directives?

A
#define
#include
#ifdef
#ifndef
#if
#else
#elif
46
Q

Define a constant using preprocessor directive.

Next do a MAX function.

Then a square function

A

define MAX_ARRAY_LENGTH 20

47
Q

How do you declare an include for Foundation and a custom class MyClass?

A

include

48
Q

What’s the difference between Error Handling and Exceptions?

A

Exceptions are used for out of bounds access or invalid method args, etc.

All Other errors are dealt with using NSError

49
Q

What are the four compiler directives for Exceptions?

A

@try

@catch

@finally

@throw

50
Q

What does a try/catch/finally block look like?

A

@try {

[treeController setValue:[predicateEditorView predicate]

								forKeyPath:@"selection.predicate"];

}@catch ( NSException *e ) {

	[treeController setValue:nil forKeyPath:@"selection.predicate"];

}@finally {

 	[NSApp endSheet:sheet];

}
51
Q

What does a try/catch/finally block loo like that captures NSExceptions from most to least specific?

A

@try {

	// code that throws an exception

	...

}@catch (CustomException *ce) { // most specific type

// handle exception ce

&hellip;


}@catch (NSException *ne) { // less specific type

	// do whatever recovery is necessary at this level

	...

	// rethrow the exception so it's handled at a higher level

	@throw;

}@catch (id ue) { // least specific type

	// code that handles this exception

	...

}@finally {

	// perform tasks necessary whether exception occurred or not

	...

}
52
Q

When would you use autoreleasepool yourself?

A

In a loop where many objects are allocated and you want to immediately release at the end of each loop. E.g.:

for(i=0;i<10000000;i++) {
@autoreleasepool {
NSString *contents = [self getFileContents:files[i]];
NSString *emojified = [contents emojified];
[self writeContents:contents toFile:files[i]];
}
}

53
Q

Explain what ARC is?

A

Automatic Reference Counting is a compiler feature that provides automatic memory management of Objective-C objects. It automatically inserts retain, release, and autorelease at compile time and generates the appropriate dealloc methods for you (setting things to null and releasing)

54
Q

Is ARC garbage collection

A

No.

55
Q

What does ARC not work on?

A

Core Foundation or anything malloc() or free() where the caller is responsible for memory management.

56
Q

Is dealloc method required to be implemented?

A

ARC takes care of Objective-C objects. If there are other things that need to be freed not under the purview of ARC then implement dealloc()

Timers that need invalidating

Notifications that should be unregistered

CFRelease on Core Foundation objects

Free() for memory allocated with malloc()

57
Q

What should you always think of when dealing with ARC?

A

How long an object should remain in existence.

58
Q

What property attributes are responsible for dealing with ARC?

A

strong, weak.

59
Q

What happens to a weak reference

A

Does not extend the life of the object it points to and becomes nil when no strong references point to the target object.

60
Q

Does ARC guard against strong retain cycles?

A

No.

61
Q

Name the four Variable Qualifiers?

A

__strong
__weak
__unsafe_unretained
__autoreleasing

62
Q

what’s unsafe_unretained do?

A

specifies a reference that doesn’t keep the referenced object alive and is not set to nil when there are no strong references to the object. If the object int references is deallocated the pointer is left dangling.

63
Q

What’s a dangling pointer?

A

Dangling pointers arise when an object is deleted or deallocated, without modifying the value of the pointer, so that the pointer still points to the memory location of the deallocated memory

64
Q

Whats the format to add a variable qualifier?

A

ClassName *qualifier variableName;

MyClass * __weak myWeakReference;

MyClass * __unsafe_unretained myUnsafeReference;

65
Q

Name common memory leaks?

A
  • Not invalidating NSTimers when dismissing view controllers
  • Forgetting to remove any observers to NSNotificationCenter when dismissing the view controller.
  • Keeping strong references to self in blocks.
  • Using strong references to delegates in view controller properties
66
Q

Name the tools that can be used in Xcode to debug memory issues? What Xcode debugger can help find and fix retain cycles and leaked memory?

A

Memory Report
Memory Graph Debugger
Allocations Instrument

Inspect the memory graph, profile the allocations.

67
Q

What’s the Memory Report do and where is it found?

A

Debug Navigator, shows the apps current memory usage along with highest value seen.

68
Q

What’s the Memory Graph Debugger? Where’s it found?

A

Helps find and fix retain cycles and leaked memory. Pauses app execution and displays objects currently on the heap w/relationships and references keeping them alive.

Use the debug bar button (looks like a graph)

69
Q

What’s the allocations instrument for and where is it?

A

Tracks the size and number of all heap and anonymous virtual memory (VM) allocations and organizes them by category.

Has three timelines:
1) timeline: total amount of memory allocated across time

2) statistics view: see categories of allocations and sizes.
3) generations view: set mark points at beginning and end of feature you want to test. Instruments organizes allocations by generation

70
Q

What technique is used to help the compiler understand a cast?

A

Bridging

Insert a bridge modifier to set the responsibility for memory allocation and maintenance. (Core Foundation or Arc)

71
Q

What’s __bridge do and how does it work. Give an example using a CFStringRef.

A

Bridge: keeps the owner the same but permits the temporary cast to work. In the example below the CFRelease is still required since ownership wasn’t transferred to ARC.

Used when accessing a CF object and don’t want ARC to control.

CFStringRef stringRef = CFStringCreateWithCString(NULL, “Hello World via bridge”, kCFStringEncodingUTF8);
NSString *text = (__bridge NSString *) stringRef;
NSLog(@”%@”, text);
CFRelease(stringRef);

72
Q

Will this method require bridging of some kind to cast to an NSObject?

A

CFStringCreateWithCString(NULL, “Hello”, kCFStringEncodingUTF8);

73
Q

If I want to cast this CFStringRef but don’t want ARC to take control of memory management what bridging keyword should be used? Give example.

A

__bridge

CFStringRef stringRef = CFStringCreateWithCString(NULL, “Hello World via bridge”, kCFStringEncodingUTF8);

NSString *text = (__bridge NSString *) stringRef;

74
Q

Where does the bridging keyword go in the cast?

A

in the object type.

NSString *text = (__bridge NSString *) stringRef;

75
Q

What’s the __bridge_transfer keyword do?

A

Gives ARC ownership. Moves the Core Foundation pointer to Objective-C.

Use when casting a Core Foundation object to standard object. (CF StringRef to NSString)

CFStringRef stringRef = CFStringCreateWithCString(NULL, “Hello World via bridge transfer”, kCFStringEncodingUTF8);
NSString *text = (__bridge_transfer NSString *) stringRef;

76
Q

What’s the bridge_retained keyword do?

A

Transfers ownership of an Object to CF for management and receives ARC of ownership. Responsibility is on the programmer to call CFRelease.

NSString *text = @”Hello World via bridge retained”;

CFStringRef stringRef = (__bridge_retained CFStringRef)text;

CFRelease(stringRef);

77
Q

What’s the term “Toll Free Bridging” mean?

A

Bridging (Casting) from a CG to Objective-C object or vice-versa without penalty or impact on the user.

78
Q

Declare a Protocol named XYZPieChartViewDataSource?

A

@protocol XYZPieChartViewDataSource

  • (NSUInteger)numberSegments;
    (NSString *) titleForSegmentAtIndex:(NSUInteger)segmentIndex;

@end

79
Q

Declare a Protocol named XYZPieChartViewDataSource?

A

@protocol XYZPieChartViewDataSource

  • (NSUInteger)numberSegments;
    (NSString *) titleForSegmentAtIndex:(NSUInteger)segmentIndex;

@end

@interface XYZPieChartView : UIView

@property (weak) id dataSource;

@end

80
Q

Can a Protocol declare a property?

A

Yes!

81
Q

Declare a class that conforms to the XYZPieChartViewDataSource protocol.

A

@interface MyClass: NSObject

@end

82
Q

Declare a class that conforms to the XYZPieChartViewDataSource and AnotherProtocol protocols

A

@interface MyClass: NSObject

@end

83
Q

What is a category, what’s it used for? What about class extensions?

A

Categories let you add new methods to an existing class.

Class extensions are best for making private properties and method names in classes because it must be done in the implementation file not interface (header). You can only do a class extension for a class you have the source code.

  • Make possible to split a classes’ interface and implementation into several files for modularity
  • Fix bugs in an existing class without the need to subclass it.
  • Avoid unnecessary subclassing and reduce amount of code w/categories.
84
Q

What’s the syntax for class extension?

A

@interface ClassName ()

@end

(Add parens after classname)

85
Q

What do you name the interface and implementation files for a Class Category?

A

+

NSString+RemoveNums.h

@interface NSString(RemoveNums)
-(NSString *)removeNumbersFromString:(NSString *)string;
@end

NSString+RemoveNums.m
- (NSString *)removeNumbersFromString:(NSString *)string
{
NSString *trimmedString = nil;
NSCharacterSet *numbersSet = [NSCharacterSet characterSetWithCharactersInString:@”0123456789”];
trimmedString = [string stringByTrimmingCharactersInSet:numbersSet];
return trimmedString;
}

86
Q

Whats the difference between Extension and Class Category?

A

Class Categories can be added to any class. Class Extensions you must have the source code and implement the extension in the implementation file.

87
Q

Where are the methods written in a Class Extension?

A

In the Implementation file.

88
Q

Can you implement a class extension on a framework class like Cocoa or Cocoa Touch NSString?

A

No, you need the source code for a Class Extension.

89
Q

Whats the main purpose of a Class Extension?

A

Adding private methods and variables. Think of class extensions as a private interface to a class.

90
Q

Are variables declared inside extensions accessible to inherited classes?

A

No.

91
Q

Show an extension to XYZAnimal() that adds a variable of generic type

A

@interface XYZAnimal(){
id _someCustomInstanceVariable;
}
@end

92
Q

How could you expose a property as readonly publicly but readwrite privately?

A

declare it readonly in the original interface then use a Class Extension inside the implementation file that re-declares it as readwrite

@interface XYZPerson : NSObject
    ...
    @property (readonly) NSString *uniqueIdentifier;
    - (void)assignUniqueIdentifier;
@end

@interface XYZPerson()
@property (readwrite) NSString *uniqueIdentifier;
@end

93
Q

What’s Key-Value Coding?

A

When framework classes want to push data into your objects they use Key-Value Coding setValue:forKey method. When framework classes want to read data they use the valueForKey method.

E.g., CoreData uses Key-Value Coding to manipulate custom objects data.

94
Q

What is Key-Value Coding? What are the two methods used to retrieve data?

A

setting and retrieving class properties and variables based on their name as a string:

setValue
valueForKey

[a setValue:@”Washing Machine” forKey:@”productName”];

[a valueForKey:@”productName”];

95
Q

How do you use Key-Value Coding to retrieve a value that’s several layers deep in the object graph? What about setting it?

A

use the valueForKeyPath method call to retrieve and the setValue:forKeyPath to set, using dot notation to traverse between classes and grab variables.:

NSString *numberToDial =
[sales valueForKeyPath:@”manager.emergencyContact.phoneNumber”];

96
Q

What is Key-Value Observing?

A

is an informal protocol that defines a common mechanism for observing and notifying state changes between objects. The main value proposition of KVO is rather compelling: any object can subscribe to be notified about state changes in any other object.

97
Q

Name four ways to communicate events?

A

NSNotification/NSNotificationCenter (One to Many)

Key-Value Observing: 1-1

Delegates: 1-1

Callbacks: blocks (1-1)

98
Q

What’s the method to subscribe as an Observer?

A

addObserver

  • (void)addObserver:(NSObject *)observer
    forKeyPath:(NSString *)keyPath
    options:(NSKeyValueObservingOptions)options
    context:(void *)context
  • observer: The object to register for KVO notifications. The observer must implement the key-value observing method observeValueForKeyPath:ofObject:change:context:.
  • keyPath: The key path, relative to the receiver, of the property to observe. This value must not be nil.
  • options: A combination of the NSKeyValueObservingOptions values that specifies what is included in observation notifications. For possible values, see “NSKeyValueObservingOptions”.
  • context: Arbitrary data that is passed to observer in observeValueForKeyPath:ofObject:change:context:.
99
Q

In the KVO method addObserver, what are the options for in the method call?

  • (void)addObserver:(NSObject *)observer
    forKeyPath:(NSString *)keyPath
    options:(NSKeyValueObservingOptions)options
    context:(void *)context
A

NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld | NSKeyValueObservingOptionIniitial

[self.child1 addObserver:self forKeyPath:@”name” options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];

100
Q

What method needs to be overridden in the observing class for KVO to work?

A

observeValueForKeyPath

  • (void)observeValueForKeyPath:(NSString *)keyPath
    ofObject:(id)object
    change:(NSDictionary *)change
    context:(void *)context
101
Q

When implementing the observeValueForKeyPath method how do you check what observation is incoming?

A

Check the incoming keyPath is equal to the Object/Class that’s being observed:

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{

if ([keyPath isEqualToString:@”name”]) {
NSLog(@”The name of the child was changed.”);
NSLog(@”%@”, change);
}

if ([keyPath isEqualToString:@”age”]) {
NSLog(@”The age of the child was changed.”);
NSLog(@”%@”, change);
}

}

102
Q

Is relying on the key path and checking the string names in observeValueForKeyPath enough for KVO to work properly?

A

No, if the superclass is observing the same key path for different outcomes it becomes problematic.

Resolve it by declaring a custom context and sending the context in when you add the observer.

Then in the observeValueForKeyPath method, check the context then check the keyPath(if necessary)

static void *child1Context = &child1Context;

[self.child1 addObserver:self forKeyPath:@”age” options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:child1Context];

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{

if (context == child1Context) {
if ([keyPath isEqualToString:@”name”]) {
NSLog(@”The name of the FIRST child was changed.”);
NSLog(@”%@”, change);
}

if ([keyPath isEqualToString:@”age”]) {
NSLog(@”The age of the FIRST child was changed.”);
NSLog(@”%@”, change);
}
}
else if (context == child2Context){
if ([keyPath isEqualToString:@”age”]) {
NSLog(@”The age of the SECOND child was changed.”);
NSLog(@”%@”, change);
}
}
}

103
Q

What’s the last thing necessary for KVO?

A

removing the observers. Do this in viewWillDisappear using removeObserver:forKeyPath method

-(void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];

[self.child1 removeObserver:self forKeyPath:@”name”];
[self.child1 removeObserver:self forKeyPath:@”age”];
[self.child2 removeObserver:self forKeyPath:@”age”];
}

104
Q

How would you override a registered observers automatic notifications on changes from the observed class?

A

Override the automaticallyNotifiesObserversForKey method and return NO for items the shouldn’t be notified. Then surround changes with willChangeValueForKey and didChangeValueForKey methods to manually notify observers.

\+(BOOL)automaticallyNotifiesObserversForKey:(NSString *)key{
if ([key isEqualToString:@"name"]) {
return NO;
}
else{
return [super automaticallyNotifiesObserversForKey:key];
}
}

[self.child1 willChangeValueForKey:@”name”];
self.child1.name = @”Michael”;
[self.child1 didChangeValueForKey:@”name”];