A. Heap & Stack , Compiling a program

Objective C is superset of C, so when we declare a variable:  NSString * aString;  -> 2 parts of the variable: the address is stored in Stack, and the object is stored in Heap.

Stack vs Heap in data structure

Memory in the Heap is managed directly via reference counting, but the stack-memory will be cleared when the frame containing that variable is popped out.

Variable not-pointer-type, which uses stack-memory:   CGRect aFrame;

These are structure, which consists only of primitives (when data contains only primitives, structure is mostly used in Obj-C).

A1. Compile in Terminal

Terminal commands to compile 3 files (Program.h, Program.m, prog.m) to

clang -framework Foundation Program.m prog.m -o program
 

B. Forward declaration, Literal Syntax & Typed Constants

  • Forward declaration: @class Employer;

We don’t #import directly in .h files, but #import in .m files – this avoids coupling classes and decreases compilation time a lot.

  • Literal Syntax: In Foundation.h, NSString, NSNumber, NSArray and NSDictionary can use Literal Syntax:
NSNumber * floatNumber = @1.25f;
NSNumber * z = @{x * y}; // expression
NSArray * animals = @[ @"cat", @"dog"];
NSString * aDog = animals[1]; // subscripting
NSDictionary * dict = @{ @"name":@"Matt", @"age":@28};

Subscripting is very convenient. Literals also check and throws exception when one of the objects are nil, therefore making it safer than using conventional arrayWithObjects.

  • Typed Constants : don’t use #define ANIMATION_DURATION    0.3  (no specific type, name not follow naming convention, it is global and so can be overwritten without warning).

There are 2 types of const,

1. local const (scope within a class):   static const NSTimeInterval kAnimationDuration = 0.3   (.m)

2. global const (for example name of NOTIFICATION) – declared it in .h and .m:

(.h) extern const NSString * PAYMENT_NOTIFICATION;
(.m) const NSString * PAYMENT_NOTIFICATION = @"VALUE";

Extern:  extern means add this variable to global symbol table!

C. Blocks:        

          float (^aBlock)(const int*, int, float)  –  use the caret ^ instead of pointer * !

Declare: float (^myblock)(int);
Define:  myblock = ^(int param) { return param / 5; }

D. Category:  

     define additional methods of an existing class—even one whose source code is unavailable —without subclassing.

SystemClass+CategoryName.h

#import “SystemClass.h”
@interface SystemClass (CategoryName)
// some methods
@end
 
D1. Add Property in a Category:  
@interface NSObject (CategoryWithProperty)
@property (nonatomic, strong) NSObject *property;
@end

Use that property’s selector as the key:

@implementation NSObject (CategoryWithProperty)

- (NSObject *)property {
    return objc_getAssociatedObject(self, @selector(property));
}

- (void)setProperty:(NSObject *)value {
    objc_setAssociatedObject(self, @selector(property), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

E. Delegate Protocols

// MyViewController.h: // declare protocol & delegate property in .h
#import <UIKit/UIKit.h>
@protocol MyProtocolName;

@interface MyViewController: UIViewController
@property (nonatomic, weak) id<MyProtocolName> delegate;
@end

@protocol MyProtocolName <NSObject>
-(void)requiredDelegateMethod;
@end // end of delegate protocol

// MyViewController.m: // checks the delegate first before calling
if (self.delegate && [self.delegate respondsToSelector:@selector(requiredDelegateMethod)]) { 
   [self.delegate requiredDelegateMethod]; 
}

.m file of class which is Delegate
#include "MyViewController.h"  // to include the @delegate protocol info
@interface AnotherViewController : UIViewController <MyProtocolName> // follows the protocol
...
-(void)requiredDelegateMethod;  // has the function
E1. Decorator pattern
Decorator adds behaviors and responsibilities to an object without modifying its code.
 2 implementations are : Category & Delegation

F. Singleton which is thread-safe

+ (Class*)sharedInstance
{
    static dispatch_once_t once;
    static Class *sharedInstance;
    dispatch_once(&once, ^{          // this code never executes again!
        sharedInstance = [self new];
    });
    return sharedInstance;
} // As singletons may exist for the life-time of the app, don't have many strong pointers in singletons
F1. Facade design patterns 

–  provides a single interface to a complex subsystem.

(Instead of exposing user to a set of classes and their APIs, only expose one simple unified API.)

@interface LibraryAPI () {        // this library will hide the Database and Remote work inside it.
    PersistencyManager *persistencyManager;
    HTTPClient *httpClient;
    BOOL isOnline;
}
@end

G. Observer Pattern & Notifications

Register as Observer
[[NSNotificationCenter defaultCenter] addObserver: self selector:@selector(downloadImage:) name:@"ImageNotification" object:nil];
Posting a Notification
[[NSNotificationCenter defaultCenter] postNotificationName:@"ImageNotification"
     object:self   userInfo:@{@"imageView":coverImage, @"coverUrl":albumCover}];
Processing a Notification
- (void)downloadImage:(NSNotification*)notification
{
    UIImageView *coverImage = notification.userInfo[@"imageView"];
    NSString *coverUrl = notification.userInfo[@"coverUrl"];
 ....
Remove Observer in viewDidUnload or viewDidDisappear
[[NSNotificationCenter defaultCenter] removeObserver:self];

H. KVO Pattern 

an object can ask to be notified of any change to properties of other objects:

// Register 
[coverImage addObserver:self forKeyPath:@"image" options:0 context:nil];
// When image is changed: this will be called
- (void)observeValueForKeyPath😦NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"image"])
    {
        [indicator stopAnimating];
    }
}
// Unregister 
[coverImage removeObserver:self forKeyPath:@"image"];
Advertisements