diff options
| -rw-r--r-- | objective-c.html.markdown | 195 | 
1 files changed, 191 insertions, 4 deletions
| diff --git a/objective-c.html.markdown b/objective-c.html.markdown index 0f0165ec..59169b16 100644 --- a/objective-c.html.markdown +++ b/objective-c.html.markdown @@ -249,14 +249,17 @@ int main (int argc, const char * argv[])          // Your statements here          @throw [NSException exceptionWithName:@"FileNotFoundException"                              reason:@"File Not Found on System" userInfo:nil]; -    } @catch (NSException * e) +    } @catch (NSException * e) // use: @catch (id exceptionName) to catch all objects.       {          NSLog(@"Exception: %@", e);      } @finally      { -        NSLog(@"Finally"); +        NSLog(@"Finally. Time to clean up.");      } // => prints "Exception: File Not Found on System" -      //           "Finally" +      //           "Finally. Time to clean up." + +    // NSError objects are useful for function arguments to populate on user mistakes.  +    NSError *error = [NSError errorWithDomain:@"Invalid email." code:4 userInfo:nil];      ///////////////////////////////////////      // Objects @@ -549,6 +552,116 @@ int main (int argc, const char * argv[]) {      NSLog(@"Car locked."); // Instances of Car can't use lockCar because it's not in the @interface.  } +// Categories +// A category is a group of methods designed to extend a class. They allow you to add new methods +// to an existing class for organizational purposes. This is not to be mistaken with subclasses.  +// Subclasses are meant to CHANGE functionality of an object while categories instead ADD  +// functionality to an object. +// Categories allow you to: +// -- Add methods to an existing class for organizational purposes. +// -- Allow you to extend Objective-C object classes (ex: NSString) to add your own methods. +// -- Add ability to create protected and private methods to classes.  +// NOTE: Do not override methods of the base class in a category even though you have the ability  +// to. Overriding methods may cause compiler errors later between different categories and it  +// ruins the purpose of categories to only ADD functionality. Subclass instead to override methods. + +// Here is a simple Car base class. +@interface Car : NSObject + +@property NSString *make; +@property NSString *color; + +- (void)turnOn; +- (void)accelerate; + +@end + +// And the simple Car base class implementation: +#import "Car.h" + +@implementation Car + +@synthesize make = _make; +@synthesize color = _color; + +- (void)turnOn { +    NSLog(@"Car is on."); +} +- (void)accelerate { +    NSLog(@"Accelerating."); +} + +@end + +// Now, if we wanted to create a Truck object, we would instead create a subclass of Car as it would +// be changing the functionality of the Car to behave like a truck. But lets say we want to just add  +// functionality to this existing Car. A good example would be to clean the car. So we would create  +// a category to add these cleaning methods: +// @interface filename: Car+Clean.h (BaseClassName+CategoryName.h) +#import "Car.h" // Make sure to import base class to extend. + +@interface Car (Clean) // The category name is inside () following the name of the base class. + +- (void)washWindows; // Names of the new methods we are adding to our Car object. +- (void)wax; + +@end + +// @implementation filename: Car+Clean.m (BaseClassName+CategoryName.m) +#import "Car+Clean.h" // Import the Clean category's @interface file. + +@implementation Car (Clean) + +- (void)washWindows { +    NSLog(@"Windows washed."); +} +- (void)wax { +    NSLog(@"Waxed."); +} + +@end  + +// Any Car object instance has the ability to use a category. All they need to do is import it: +#import "Car+Clean.h" // Import as many different categories as you want to use. +#import "Car.h" // Also need to import base class to use it's original functionality. + +int main (int argc, const char * argv[]) { +    @autoreleasepool { +        Car *mustang = [[Car alloc] init]; +        mustang.color = @"Red"; +        mustang.make = @"Ford"; + +        [mustang turnOn]; // Use methods from base Car class. +        [mustang washWindows]; // Use methods from Car's Clean category. +    } +    return 0;  +} + +// Objective-C does not have protected method declarations but you can simulate them. +// Create a category containing all of the protected methods, then import it ONLY into the +// @implementation file of a class belonging to the Car class: +@interface Car (Protected) // Naming category 'Protected' to remember methods are protected. + +- (void)lockCar; // Methods listed here may only be created by Car objects. + +@end +//To use protected methods, import the category, then implement the methods: +#import "Car+Protected.h" // Remember, import in the @implementation file only. + +@implementation Car  + +- (void)lockCar { +    NSLog(@"Car locked."); // Instances of Car can't use lockCar because it's not in the @interface. +} + +@end + +// Protocols +// A protocol declares methods that can be implemented by any class. +// Protocols are not classes themselves. They simply define an interface +// that other objects are responsible for implementing. +@protocol MyProtocol +    - (void)myProtocolMethod;  @end  /////////////////////////////////////// @@ -594,7 +707,7 @@ int main (int argc, const char * argv[]) {  // A protocol declares methods that can be implemented by any class.  // Protocols are not classes themselves. They simply define an interface  // that other objects are responsible for implementing. - // @protocol filename: "CarUtilities.h" +// @protocol filename: "CarUtilities.h"  @protocol CarUtilities <NSObject> // <NSObject> => Name of another protocol this protocol includes.      @property BOOL engineOn; // Adopting class must @synthesize all defined @properties and      - (void)turnOnEngine; // all defined methods. @@ -605,6 +718,7 @@ int main (int argc, const char * argv[]) {  @interface Car : NSObject <CarUtilities> // Name of protocol goes inside <>      // You don't need the @property or method names here for CarUtilities. Only @implementation does.  - (void)turnOnEngineWithUtilities:(id <CarUtilities>)car; // You can use protocols as data too. +<<<<<<< HEAD  @end  // The @implementation needs to implement the @properties and methods for the protocol.   @implementation Car : NSObject <CarUtilities> @@ -646,6 +760,49 @@ if ([myClass conformsToProtocol:@protocol(CarUtilities)]) {  - (void)beNiceToBrother:(id <Brother>)brother; +======= +@end +// The @implementation needs to implement the @properties and methods for the protocol.  +@implementation Car : NSObject <CarUtilities> + +@synthesize engineOn = _engineOn; // Create a @synthesize statement for the engineOn @property. + +- (void)turnOnEngine { // Implement turnOnEngine however you would like. Protocols do not define +    _engineOn = YES; // how you implement a method, it just requires that you do implement it. +} +// You may use a protocol as data as you know what methods and variables it has implemented. +- (void)turnOnEngineWithCarUtilities:(id <CarUtilities>)objectOfSomeKind {  +    [objectOfSomeKind engineOn]; // You have access to object variables +    [objectOfSomeKind turnOnEngine]; // and the methods inside.  +    [objectOfSomeKind engineOn]; // May or may not be YES. Class implements it however it wants. +} + +@end +// Instances of Car now have access to the protocol.  +Car *carInstance = [[Car alloc] init]; +[[carInstance setEngineOn:NO]; +[carInstance turnOnEngine]; +if ([carInstance engineOn]) { +    NSLog(@"Car engine is on."); // prints => "Car engine is on." +} +// Make sure to check if an object of type 'id' implements a protocol before calling protocol methods: +if ([myClass conformsToProtocol:@protocol(CarUtilities)]) { +    NSLog(@"This does not run as the MyClass class does not implement the CarUtilities protocol."); +} else if ([carInstance conformsToProtocol:@protocol(CarUtilities)]) { +    NSLog(@"This does run as the Car class implements the CarUtilities protocol."); +} +// Categories may implement protocols as well: @interface Car (CarCategory) <CarUtilities> +// You may implement many protocols: @interface Car : NSObject <CarUtilities, CarCleaning> +// NOTE: If two or more protocols rely on each other, make sure to forward-declare them: +#import "Brother.h" + +@protocol Brother; // Forward-declare statement. Without it, compiler would through error. + +@protocol Sister <NSObject> + +- (void)beNiceToBrother:(id <Brother>)brother; + +>>>>>>> 8c6f583... Add much more to the protocols section.  @end  // See the problem is that Sister relies on Brother, and Brother relies on Sister.  #import "Sister.h" @@ -658,6 +815,36 @@ if ([myClass conformsToProtocol:@protocol(CarUtilities)]) {  @end + +/////////////////////////////////////// +// Blocks +/////////////////////////////////////// +// Blocks are statements of code, just like a function, that is able to be used as data.  +// Below is a simple block with an integer argument that returns the argument plus 4. +int (^addUp)(int n); // Declare a variable to store the block.  +void (^noParameterBlockVar)(void); // Example variable declaration of block with no arguments.  +// Blocks have access to variables in the same scope. But the variables are readonly and the +// value passed to the block is the value of the variable when the block is created.  +int outsideVar = 17; // If we edit outsideVar after declaring addUp, outsideVar is STILL 17. +__block long mutableVar = 3; // __block makes variables writable to blocks, unlike outsideVar. +addUp = ^(int n) { // Remove (int n) to have a block that doesn't take in any parameters.  +    NSLog(@"You may have as many lines in a block as you would like."); +    NSSet *blockSet; // Also, you can declare local variables. +    mutableVar = 32; // Assigning new value to __block variable. +    return n + outsideVar; // Return statements are optional.  +} +int addUp = add(10 + 16); // Calls block code with arguments.  +// Blocks are often used as arguments to functions to be called later, or for callbacks. +@implementation BlockExample : NSObject  +  + - (void)runBlock:(void (^)(NSString))block { +    NSLog(@"Block argument returns nothing and takes in a NSString object."); +    block(@"Argument given to block to execute."); // Calling block. + } + + @end + +  ///////////////////////////////////////  // Memory Management  /////////////////////////////////////// | 
