顯示具有 開放課程心得 標籤的文章。 顯示所有文章
顯示具有 開放課程心得 標籤的文章。 顯示所有文章

2012年3月10日 星期六

Filter4Cam 學習之 Graphics 小記

since: 2012/03/02
update: 2012/03/02

reference: Developing iPad Applications for Visualization and Insight
                    => Lecture 12: Graphics

   1. Graphics Stack

   2. Blitting
        blit = Bit-Block Image Transfer (位元區塊影像轉換)

   3. CoreGraphics is a Vector graphics API
       Coordinate system:


   4. CoreGraphics is a CoreFoundation API
       a. CoreFoundation takes the ideas of Objective-C and applies them to C
           (p.s. CoreFoundation is a C API; Foundation is a Objective-C API )

       b. Memory management:
          (1). CFRetain / CFRelease
          (2). Methods with Create in the name: you need to release
          (3). Methods with Get in the name: same semantics as autorelease

          (4). Many CF types have their own free.
                 For example, CGPathRelease instead of CFRelease.
                 You can use either one. (使用 CGPathRelease, 讓程式碼更清楚)
              (唯一的差異: 將 nill 傳入 CFRelease 會 crash 掉; CGPathRelease 則不會)

       c. Toll-Free Bridging:
          (1). Any CF object type can be cast to id
          (2). NSArray* and CFArrayRef are compatible
          (3). Same with NSDictionary* and CFDictionaryRef


2011年11月22日 星期二

Stanford CS193p Fall 2011 Note-05

StoryBoard:

A. create a segue:









B. Five kinds of segues:
   1. Push - It is the kind of segue you use when the two Controllers are inside a
       UINavigationController.
   2. Replace - Replaces the right-hand side of a UISplitViewController (iPad only)
   3. Popover - Puts the view controller on the screen in a popover (iPad only)
   4. Modal - Puts the view controller up in a way that blocks the app until it is
       dismissed
   5. Custom - You can create your own subclasses of UIStoryboardSegue

2011年11月19日 星期六

Stanford CS193p Fall 2011 Note-04

Instance vs. Class Methods

Instance Methods:
1. Starts with a dash:
   - (BOOL)dropBomb:(Bomb *)bomb
                                    at:(CGPoint)position
                               from:(double)altitude;

2. "Normal" Instance Methods

3. Calling syntax:
     [<pointer to instance> method]
     e.g.
     Ship *ship = ...; // instance of a Ship
     destroyed = [ship dropBomb:firecracker
                                                      at:dropPoint
                                               from:300.0];

4. self/super is calling instance
    self means "my implementation"
    super means "my superclass's implementation"

Class Methods:
1. Starts with a plus sign:
   + (id) alloc;
   + (Ship *)motherShip;
   + (NSString *)stringWithFormat:...

2. Creation & Utility Methods

3. Calling syntax:
    [Class method]
    e.g.
    Ship *ship = [Ship motherShip];
    NSString *resultString =
    [NSString stringWithFormat:@"%g", result];
    [[ship class] doSomething];

4. self/super is this class
    self means "this class's class methods"
    super means "this class's superclass's class methods"

-----------------------------------------------------------------------------

Coordinates
1. bounds // @property CGRect bounds;
   a. your view's internal drawing space's origin and size
   b. The bounds property is what you use inside your view's own implementation.
   c. It is up to your implementation as to how to interpret the meaning of
       bounds.origin.
       e.g. View B's bounds = ((0,0),(200,250)) // ((x, y), (width, height))  

2. center // @property CGPoint center;
    the center of your view in your superview's coordinate space
     e.g. View B's center = (300,225) // (x, y)

3. frame // @property CGRect frame;
    a rectangle in your superview's coordinate space which entirely contains your
    view's bounds.size
    e.g. View B's frame = ((140,65),(320,320)) // ((x, y), (width, height))

4. Use frame and center to position the view in the hierarchy
    a. These are used by superviews, never inside your UIView subclass's
        implementation.
    b. You might think frame.size is always equal to bounds.size, but you'd be wrong ...
        Because views can be rotated (and scaled and translated too).

2011年11月17日 星期四

Stanford CS193p Fall 2011 Note-02

直接從 UI 新增 property 的方式:
=> 按住 "control" , 點選 UI 上的元件(在此為 UILabel), 將其拖拉到
      對應的 Controller.h 程式區塊內放開.




-----------------------------------------------------------------------------

直接從 UI 新增 action 的方式:
=> 按住 "control" , 點選 UI 上的元件(在此為 UIButton), 將其拖拉到
      對應的 Controller.m 程式區塊內放開.



-----------------------------------------------------------------------------

@synthesize 的對象為物件時, 通常可以藉由更改其 getter 來作初始化的動作.
ex:

@property (nonatomic, strong) NSMutableArray *operandStack;
....
@synthesize operandStack = _operandStack;
....

- (NSMutableArray *) operandStack
{
    if (_operandStack == nil) {
        _operandStack = [[NSMutableArray alloc] init];
    }
   
    return _operandStack;
}

2011年11月16日 星期三

Stanford CS193p Fall 2011 Note-01

參考: iPad and iPhone Application Development (HD) - Download free content from Stanford on iTunes

MVC:


-----------------------------------------------------------------------------
private methods:

-----------------------------------------------------------------------------
nonatomic:
@property nonatomic means its setter and getter are not thread-safe.
That's no problem if this is UI code because all UI code happens
on the main thread of the application.

-----------------------------------------------------------------------------
synthesize:
ex: @synthesize topSpeed = _topSpeed;

1. We almost always use @synthesize to create the implementation of the setter
   and getter for a @property. It both creates the setter and getter methods AND
   creates some storage to hold the value.

2. _topSpeed
  (1). This is the name of the storage location to use.
  (2). _ (underbar) then the name of the property is a common naming convention.
 
3. If we don't use = here, @synthesize uses the name of the property
   (which is bad so always use =).

4. This is what the methods created by @synthesize would look like:
- (void)setTopSpeed:(double)speed
{
    _topSpeed = speed;
}
- (double)topSpeed
{
    return _topSpeed;
}

-----------------------------------------------------------------------------

private property:
ex:
// in Spaceship.m
@interface Spaceship()
// declaration of private methods (as needed)
@property (nonatomic, strong) Wormhole *nearestWormhole;
@end

@synthesize nearestWormhole = _nearestWormhole;

1. strong:
   It's a pointer to an object (of class Wormhole). It's strong which means that the
   memory used by this object will stay around for as long as we need it.

2. *nearestWormhole:
    All objects are always allocated on the heap. So we always access them through
    a pointer. Always.

3. @synthesize:
    does NOT create storage for the object this pointer points to.
    It just allocates room for the pointer.

2011年7月10日 星期日

Stanford CS193P Note-05

Universal Applications: am I on an iPad?
    // iOS 3.2 以上
    BOOL iPad = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);

-----------------------------------------------------------------------------------------------------------------

Gesture Recognizers (手勢 識別器)

◎ Gestures are handled by the class UIGestureRecognizer
    This class is "abstract." We only actually use "concrete(具體的) subclasses" of it.

◎ There are two sides to using a gesture recognizer
    1. Adding a gesture recognizer to a UIView to ask it to recognize that gesture.
    2. Providing the implementation of a method to "handle" that gesture
       when it happens.

◎ Adding a gesture recognizer to a UIView from a Controller
    - (void)viewDidLoad
    {
        UIView*panView=...;

        UIGestureRecognizer *pangr =

        [[UIPanGestureRecognizer alloc] initWithTarget:panView action:@selector(pan:)];
        /* 1. panning: moving something around with your finger.

           2. panView: the target to handle a pan gesture
           3. action method(pan:) will be sent to the target (the panView)
           4. the action message(pan:) takes one argument: UIGestureRecognizer
        */
        
         // add this gesture recognizer to the view's list of gestures that it recognizes.
         [panView addGestureRecognizer:pangr];

         // the view has taken ownership of this object, so we must release it
         [pangr release];
    }

    // Only UIView instances can recognize a gesture
    // (because UIViews handle all touch input).


◎ How do we implement the target of a gesture recognizer?
    Each concrete class provides some methods to help you do that.
    For example, UIPanGestureRecognizer provides 3 methods
    - (CGPoint)translationInView:(UIView *)aView; // 多遠
    - (CGPoint)velocityInView:(UIView *)aView;    // 速度
    - (void)setTranslation:(CGPoint)translation inView:(UIView *)aView; // 位移: 常設為 0

 
◎ what would action method(pan:) look like?
   - (void)pan:(UIPanGestureRecognizer *)sender
   {
       // If the gesture is continuous,
       // it'll move on to the Changed and eventually the Ended state

       if ((sender.state == UIGestureRecognizerStateChanged) ||
          (sender.state == UIGestureRecognizerStateEnded)) {
              // The new movement is added to the translation that was there before.
              CGPoint translation = [recognizer translationInView:self];

              // move something in myself (I'm a UIView) by translation.x and translation.y
              // for example, if I were a graph and my origin was set by
              // an @property called origin

              self.origin = CGPointMake(self.origin.x+translation.x,
                                          self.origin.y+translation.y);


              // Here we are resetting the "translation that was there before" to zero.
              [recognizer setTranslation:CGPointZero inView:self];
          }
   }

 
◎ Other Concrete Gestures
    1. UIPinchGestureRecognizer // 捏: 縮放
      
//note that this is NOT readonly(can reset each movement)
       @property CGFloat scale;
      
// note that this IS readonly; scale factor per second
       @property (readonly) CGFloat velocity;

    2. UIRotationGestureRecognizer // 旋轉
      
//note that this is NOT readonly; inradians
       @property CGFloat rotation;
      
// note that this IS readonly; radians per second
       @property (readonly) CGFloat velocity;

    3. UISwipeGestureRecognizer // 滑過
      
// what direction swipes you want
       @propertyUISwipeGestureRecognizerDirectiondirection;
      
// two finger swipes? or just one finger? more?
       @property NSUInteger numberOfTouchesRequired;

    4. UITapGestureRecognizer // 輕拍
      
//single tap or double tap or triple tap,etc.
       @propertyNSUIntegernumberOfTapsRequired;
      
//e.g., require two finger tap?
       @propertyNSUIntegernumberOfTouchesRequired;


2011年7月7日 星期四

Stanford CS193P Note-04

View-based Application

main.m
    1. Basically just the C entry point function int main(int argc, char *argv[])
    2. Calls UIApplicationMain which creates a UIApplication object and starts the
       run loop
    3. Also creates a catch-all autorelease pool

MainWindow.xib
    1. Contains a UIWindow (top of the view hierarchy) for things to be installed in
    2. Contains the Application Delegate
       (just an NSObject with its class set to xxxAppDelegate)
    3. Application Delegate also has a couple of outlets wired up
       (notably to xxxViewController)
  
◎ xxx-Info.plist
    A variety of application configuration properties

◎ xxxAppDelegate.[mh]
   1. Has an instance variable for the UIWindow in MainWindow.xib called window.
   2. Has an instance variable for xxxViewController called viewController.
   3. Has stubs for a lot of applicationDidThis and applicationWillDoThat.
   4. Most importantly application:didFinishLaunchingWithOptions:.
      (1). This is the method where xxxViewController's view is added to the UIWindow.
      (2). Also where the UIWindow is made visible ... [window makeKeyAndVisible]
     
-----------------------------------------------------------------------------------------------------

Application Lifecycle


◎ After application:didFinishLaunchingWithOptions:, then what?
    Application enters a "run loop" repeatedly doing the following ...
    1. An autorelease pool is created
    2. Application waits for events (touch, timed event, I/O, etc.)
    3. Events are dispatched through UIKit objects and often on to your objects
       (via delegates, etc.)
    4. When all is done, the screen is updated
       (appropriate drawRect: methods are called)
    5. The autorelease pool is drained

    Rinse, repeat.
-----------------------------------------------------------------------------------------------------

View Controller

VERY important property in UIViewController
    @property (retain) UIView *view;
    This is a pointer to the top-level UIView in the Controller's View (in MVC terms)
After the UIViewController is initialized, viewDidLoad is called
    - (void)viewDidLoad;
    1. This is an exceptionally good place to put a lot of setup code.
    2. But be careful because the geometry of your view (its bounds) is not set yet.

Just before the view appears on screen, you get notified
    - (void)viewWillAppear:(BOOL)animated;
    1. When this is called, your bounds has been set
       (via your frame by your superview or some such).
    2. Your view will probably only get "loaded" once, but it might appear and
       disappear a lot.
    3. So don't put something in this method that really wants to be in viewDidLoad.

You already know about viewDidUnload
    - (void)viewDidUnload;
    1. Called in low-memory situations.
    2. Be sure to release your outlets
       (or other data tied to the view and its subviews) here.

-----------------------------------------------------------------------------------------------------

IBOutlet Memory Management

◎ set outlets to be private & do't call your outlet's "setter" from dealloc

   //
interface
   @interface MyVC : UIViewController {
       IBOutlet UILabel *outlet;
   }
   @end

   // implementation
   @interface MyVC()
   @property (retain) IBOutlet UILabel *outlet;
   @end

   @implementation MyVC
   @synthesize outlet;
   - (void)viewDidUnload {
      
self.outlet = nil;
       [self releaseOutlets];
   }
   - (void)dealloc {
       [outlet release];
       [self releaseOutlets];
       [super dealloc];
   }

  //@add
  - (void)releaseOutlets {
     
self.outlet = nil;
  }
   @end
-----------------------------------------------------------------------------------------------------

Memory Management

Alarm should go off in your head when you type alloc/copy/new
    You should immediately drop everything and go figure out where this object
    will be released
    1. If it's an instance variable, probably you're looking at dealloc
    2. If it's a local variable, release it as soon as you're done using it
       (at least just before return)
    3. If it's a local variable that you are returning, autorelease it
Go immutable! // 儘量使用不可修改的
    It's simpler and less error-prone than allocing a mutable object, modifying it,
    then releaseing it
◎ Try to use methods other than alloc/copy/new
    // Fine:
    - (NSDictionary *)testVariableValues {
        NSMutableDictionary *returnValue = [[NSMutableDictionary alloc] init];
        [returnValue setObject:[NSNumber numberWithFloat:3.5] forKey:@"x"];
        [returnValue setObject:[NSNumber numberWithFloat:23.8] forKey:@"y"];
        return [returnValue autorelease]; // set
autorelease
    }

    // Better:
    - (NSDictionary *)testVariableValues {
       
// autorelease
        NSMutableDictionary *returnValue = [NSMutableDictionary dictionary];

        [returnValue setObject:[NSNumber numberWithFloat:3.5] forKey:@"x"];
        [returnValue setObject:[NSNumber numberWithFloat:23.8] forKey:@"y"];
        return returnValue;
    }

    // Best:
    - (NSDictionary *)testVariableValues {
       
       
// immutable & autorelease
        return [NSDictionary dictionaryWithObjectsAndKeys: 
               [NSNumber numberWithFloat:3.5], @"x",
               [NSNumber numberWithFloat:23.8], @"y",
               nil];

    }

◎ But don't abuse autorelease by creating a huge pool
    // Bad:
    - (NSString *)tenThousandGs {
        NSString *s = "";
        for (int i = 0; i < 10000; i++)
            s = [s stringByAppendingString:@"G"]; // 10000 個
autorelease
        return s;
    }

    // Good:
    - (NSString *)tenThousandGs {
        NSMutableString *s = [[NSMutableString alloc] init];
        for (int i = 0; i < 10000; i++)
            [s appendString:@"G"];
        return [s autorelease];
    }

    // Best:
    - (NSString *)tenThousandGs {
       
NSMutableString *s = [NSMutableString string]; // 產生 autorelease 的 obj
        for (int i = 0; i < 10000; i++)
            [s appendString:@"G"];
        return s;

    }

2011年6月22日 星期三

Stanford CS193P Note-03

Foundation Framework

- (NSString *)description is a useful method to override (it's %@ in NSLog()).

NSString
    1. International (any language) strings using Unicode.
    2. Used throughout iOS instead of C language's char * type.
    3. An NSString instance can not be modified! They are immutable.
    4. Usual usage pattern is to send a message to an NSString and it will return you
       a new one.

NSMutableString (Mutable version of NSString.)
    Can do some of the things NSString can do without creating a new one
    (i.e. in-place changes).

NSNumber
    1. Object wrapper around primitive types like int, float, double, BOOL, etc.
    2. ex:
       NSNumber *num = [NSNumber numberWithFloat:36.5];
       float f = [num floatValue];

◎ NSValue
    1. Generic object wrapper for other non-object data types.
    2. ex:
       CGPoint point = CGPointMake(25.0, 15.0);
       NSValue *val = [NSValue valueWithCGPoint:point];

NSData (Bag of bits)
    Used to save/restore/transmit data throughout the iOS SDK.

NSDate
    Used to find out the time right now or to store past or future times/dates.
   
NSArray
    1. Ordered collection of objects.
    2. Immutable. That's right, you cannot add or remove objects to it once it's created.
    3. Some methods:
       - (void)makeObjectsPerformSelector:(SEL)aSelector;
       ex: [array makeObjectsPerformSelector:@selector:(doSomething)];

       -(id)lastObject; //returns nil if there are no objects in the array(convenient)

NSDictionary
    1. Hash table. Look up objects using a key to get a value.
    2. Immutable. That's right, you cannot add or remove objects to it once it's created.
    3. Keys are objects which must implement - (NSUInteger)hash &
       - (BOOL)isEqual:(NSObject *)obj

    4. Keys are usually NSString objects.

NSSet
    1. Unordered collection of objects.
    2. Immutable. That’s right, you cannot add or remove objects to it once it’s created.
    3. Some methods:
       - (id)anyObject; // 隨機丟出一個 object
      
-----------------------------------------------------------------------------------------------------

Enumeration
    1. Looping through members of a collection in an efficient manner
    2. Language support using for-in (similar to Java)
    3. Example: NSSet of id (could just as easily be an NSArray of id)
       NSSet *mySet = ...;
       for (id obj in mySet) {
           // do something with obj, but make sure you don't send it a message it does
           // not respond to

           if ([obj isKindOfClass:[NSString class]]) {
               // send NSString messages to obj with impunity
           }
        }
        // or use: isMenberOfClass:

Property List (.plist)
    1. The term "Property List" just means a collection of collections
    2. Specifically, it is any graph of objects containing only the following classes:
       NSArray
, NSDictionary, NSNumber, NSString, NSDate, NSData
    3. Why define this term?
       Because the SDK has a number of methods which operate on Property Lists.
       Usually to read them from somewhere or write them out to somewhere.
       [plist writeToFile:(NSString *)path atomically:(BOOL)];
       // plist is NSArray or NSDictionary


NSUserDefaults
    1. Lightweight storage of Property Lists.
    2. It's basically an NSDictionary that persists between launches of your application.
       Not a full-on database, so only store small things like user preferences.
    3. Read and write via a shared instance obtained via class method
       standardUserDefaults:
       [[NSUserDefaults standardUserDefaults] setArray:rvArray
       forKey:@"RecentlyViewed"];

    4. Always remember to write the defaults out after each batch of changes!
       [[NSUserDefaults standardUserDefaults] synchronize];

-----------------------------------------------------------------------------------------------------

Objects

Creating Objects
It is a two step operation to create an object in Objective-C
    1. Allocating (almost always done with the NSObject class method alloc)
    2. Initializing (done with a method that starts with the four letters init)
alloc makes space in heap for the class's instance variables
    Also sets them all to zero, so instance variables which are object pointers
    start out nil

◎ Each class has a "designated" initializer method
    1. NSObject's is init (by convention, all init methods start with the four letters init)
    2. When you subclass an object, you must call your superclass's
       designated initializer from your designated initializer
       (and make sure that it did not fail and return nil)
    3. All init methods should be typed (in their declaration) to return id
       (not statically typed)
    4. Callers should statically type though, e.g., MyObject *obj = [[MyObject alloc] init];

Initializing Objects
◎ Example: A direct subclass of NSObject
    @implementation MyObject
    - (id)init
    {
        if (self = [super init]) {
            // initialize our subclass here
        }
        return self;
    }
    @end

A Tale of Initializer
    @implementation MyView
    - (id)initWithFrame:(CGRect)aRect {
        if (self = [super initWithFrame:aRect]) {
            // initialize my subclass here
        }
        return self;
     }

    - (id)initToFit:(Shape *)aShape {
        CGRect fitRect = [MyView sizeForShape:aShape];
        return [self initWithFrame:fitRect];
    }
    @end

-----------------------------------------------------------------------------------------------------

Object Ownership

◎ When do you take ownership?(所有權)
    1. You immediately own any object you get by sending a message starting
       with new, alloc or copy.
    2. The most common one of these is, of course, the combination
       of alloc followed by init...
    3. If you get an object from any other source you do not own it, but you can take
       ownership by sending it the NSObject message retain.

◎ How do you give up ownership when you are done?
    1. Send the object the NSObject message release.
    2. Do not send release to an object you do not own. This is very bad.

◎ ex for retain count:
    NSString *str = [[NSString alloc]initWithString:@"foo"]; // retain count: 1
    NSString *strB = [str retain];                             // retain count: 2
    [str release];                                              // retain count: 1
    [strB release];                                 // retain count: 0 ; it will invoke [str dealloc];

Temporary Ownership
◎ So how does this "temporary ownership" thing work?
    1. If you want to give someone an object with the "option" for them to take
       ownership of it, you must take ownership of it yourself, then send the
       object the message autorelease.
    2. Your ownership will "expire" at some future time
       (but not before the current event is finished).
       In the meantime, someone else can send retain to the object if they want to
       own it themselves.

◎ Best understood by example
    - (Money *)showMeTheMoney:(double)amount {
        Money *theMoney = [[Money alloc] init:amount];
        [theMoney autorelease]; // We are responsible for sending it release
        return theMoney;
    } 
    // Caller
    Money *myMoney = [bank showMeTheMoney:4500.00];
    [myMoney retain];

Collections and autorelease
Loading up an array or dictionary to return to a caller
    @implementation MyObject
    - (NSArray *)coolCats
    {
        NSMutableArray *returnValue = [[NSMutableArray alloc] init];
        [returnValue addObject:@"Steve"];
        [returnValue addObject:@"Ankush"];
        [returnValue addObject:@"Sean"];
        [returnValue autorelease];
        return returnValue;
    }
    @end

    // But there's a better way. Get an autoreleased NSMutableArray in the first place.
    @implementation MyObject
    - (NSArray *)coolCats
    {
        NSMutableArray *returnValue = [[NSMutableArray alloc] init];
        NSMutableArray *returnValue = [NSMutableArray array];
        [returnValue addObject:@"Steve"];
        [returnValue addObject:@"Ankush"];
        [returnValue addObject:@"Sean"];
        [returnValue autorelease];
        return returnValue;
    }
    @end

   // But there's an even better way! Use collection classes "create with" methods.
    @implementation MyObject
    - (NSArray *)coolCats
    {
        NSMutableArray *returnValue = [NSMutableArray array];
        [returnValue addObject:@"Steve"];
        [returnValue addObject:@"Ankush"];
        [returnValue addObject:@"Sean"];
        return returnValue;
       
        return [NSArray arrayWithObjects:@"Steve", @"Ankush", @"Sean", nil];
    }
    @end  

Other convenient create with methods (all return autoreleased objects):
1. [NSString stringWithFormat:@"Meaning of %@ is %d", @"life", 42];
2. [NSDictionary dictionaryWithObjectsAndKeys:ankush, @"TA", janestudent,
   @"Student", nil];

3. [NSArray arrayWithContentsOfFile:(NSString *)path];

Other Ownership Rules
Collections take ownership when an object is added to them
    NSArray, NSDictionary, NSSet
    (NSDictionary takes ownership of both keys and values).
    They then release ownership when an object is removed.

Think of @"string" as autoreleased
    In reality, they are constants, so retain and release have no effect on them.

NSString objects are usually sent copy rather than retain (會產生新物件)
    1. That gives you an immutable version of the string to hold on to.
    2. The method copy in NSMutableString returns an NSString,
       not an NSMutableString.
    3. Of course, you still release it when you are done with it.

Deallocation
What happens when the last owner calls release?
    A special method, dealloc, is called on the object
    & the object's memory is returned to the heap.
    After this happens, sending a message to the object will crash your program.

You should override dealloc in your classes, but NEVER call it!
    1. It only gets called by release when the last owner has released the object.
    2. The one exception about calling it is that you must call [super dealloc]
       in your dealloc.

Example
    - (void)dealloc
    {
        [brain release];
        [otherObjectInstanceVariable release];
        [super dealloc];
    }


@property
There are three options for setters made by @synthesize
    1. @property (retain) NSArray *myArrayProperty;      // retain count + 1
    2. @property (copy) NSString *someNameProperty;  //
retain count + 1
    3. @property (assign) id delegate;                            // retain count + 1
 
Example for retain:
    @property (retain) NSString *name;
    @synthesize
    // will create a setter equivalent to this ...
   
    - (void)setName:(NSString *)aString
    {
        [name release];
        name = [aString retain];
    }
    // Note that @synthesize will release the previous object
    // (if any, could be nil) before setting and retaining the new one.

Example for copy:
    @property (copy) NSString *name;
    @synthesize
    // will create a setter equivalent to this ...
   
    - (void)setName:(NSString *)aString
    {
        [name release];          // Still release-ing before copying.
        name = [aString copy];
    }


Example for assign:
    @property (assign) NSString *name;
    @synthesize
    // will create a setter equivalent to this ...
    - (void)setName:(NSString *)aString
    {
        name = aString; // No release here because we never retain or copy.
    }

-----------------------------------------------------------------------------------------------------

Protocols

Similar to @interface, but no implementation
    @protocol Foo
    - (void)doSomething;    // implementors must implement this
    @optional
    - (int)getSomething;    // implementors do not need to implement this
    @required
    - (NSArray *)getManySomethings:(int)howMany;    // must implement
    @end
    // The above is added to a header file


Classes then implement it
    // They must proclaim that they implement it in their @interface
    @interface MyClass : NSObject <Foo>
    ....
    @end

 
You must implement all non-@optional methods

Can now declare id variables with added protocol requirement
    id<Foo> obj = [[MyClass alloc] init]; //多型: compiler will love this!


Also can declare arguments to methods to require protocol
    - (void)giveMeFooObject:(id <Foo>)anObjectImplementingFoo;
    // If you call this and pass an object which does not implement Foo
    // ... compiler warning!


Number one use of protocols in iOS: delegates and dataSources
    The delegate or dataSource is always defined as an assign @property
    @property (assign) id <UISomeObjectDelegate> delegate;

-----------------------------------------------------------------------------------------------------

Views
Hierarchical
    1. Only one superview - (UIView *)superview
    2. Can have many (or zero) subviews - (NSArray *)subviews
    3. Subview order (in that array) matters:
       those later in the array are on top of those earlier

 
it can be done in code as well
    - (void)addSubview:(UIView *)aView;
    - (void)removeFromSuperview;
View Transparency(透明度)
    1. By default, drawing is fully opaque(預設: 不透明)
    2. you can hide a view completely by setting hidden property
       @property BOOL hidden;
       myView.hidden = YES;    // view will not be on screen and will not handle events

       (不畫)
 
View Memory Management
    1. A superview retains its subviews
       Once you put a view into the view hierarchy, you can release your ownership 

       if you want
    2. Be careful when you remove a view from the hierarchy
       (1). If you want to keep using a view, retain ownership before you send 

           removeFromSuperview
       (2). Removing a view from the hierarchy immediately causes a release on it 

           (not autorelease)
       (3). So if there are no other owners, it will be immediately deallocate

           (and its subviews released)    
    3. IBOutlets are retained
-----------------------------------------------------------------------------------------------------

IBOutlet Memory Management


UIViewController calls a method on itself after view load/unload
   
- (void)viewDidLoad is called just after the Controller's view has been created
      (& outlets are set). This method is an awesome place to set initial state 

      in an outlet (if you couldn't do it in IB).

    - (void)viewDidUnload is called just after the view has been "unloaded"
    This is the place we can release our outlets in the case of unloading.


Here's how we release our outlets in viewDidUnload & dealloc
    // private method to share code between viewDidUnload and dealloc

    - (void)releaseOutlets {
        self.myOutlet = nil;
        self.myOtherOutlet=nil;
    }
    - (void)viewDidUnload {
        [self releaseOutlets];
    }

    - (void)dealloc {
        [self releaseOutlets];
        [super dealloc];
    }

-----------------------------------------------------------------------------------------------------

Coordinates
Origin of a view's coordinate system is upper left 

Units are "points" (not pixels)

    @property CGFloat contentScaleFactor;
    // returns pixels per point on the screen this view is on.
    // This property is not (readonly), but you should basically pretend that it is for this class.



Views have 3 properties related to their location and size
    1. @property CGRect bounds;  

       // your view's internal drawing space's origin and size
       The bounds property is what you use inside your view's own implementation
       It is up to your implementation as to how to interpret bounds.origin

 
    2. @property CGPoint center;  

       // the center of your view in your superview's coordinate space
 
    3. @property CGRect frame;  

       // a rectangle in your superview's coordinate space which entirely
       // contains your view's bounds.size

 
-----------------------------------------------------------------------------------------------------

Creating Views

How do you create a UIView in code (i.e. not in IB)?
    Just use alloc and initWithFrame: (UIView's designated initializer).

Example:
    CGRect buttonRect = CGRectMake(20, 20, 120, 37);
    UIButton *button = [[UIButton alloc] initWithFrame:buttonRect];
    button.titleLabel.text = @"Do it!";
    [window addSubview:button];
    [button release];    // okay because button is in view hierarchy now

 
-----------------------------------------------------------------------------------------------------

Custom Views

Drawing is easy ... create a UIView subclass & override 1 method
    - (void)drawRect:(CGRect)aRect; // 會使用 CGCore Graphic, CPU 畫圖效能好
    You can optimize by not drawing outside of aRect if you want (but not required).

NEVER call drawRect:!! EVER! Or else!
   Instead, let iOS know that your view's drawing is out of date with one of
   these UIView methods:
   - (void)setNeedsDisplay;
   - (void)setNeedsDisplayInRect:(CGRect)aRect;
   It will then set everything up and call drawRect: for you at an appropriate time
   Obviously, the second version will call your drawRect: with only rectangles that
   need updates

So how do I implement my drawRect:?
    Use the Core Graphics framework
    The API is C (not object-oriented)


-----------------------------------------------------------------------------------------------------

Context
How to get this magic context?
    Call the following C function inside your drawRect: method to get 

    the current graphics context ...
    CGContextRef context = UIGraphicsGetCurrentContext();
    You do not have to free it or anything later, just use it for all drawing.


-----------------------------------------------------------------------------------------------------

Graphics State
Special considerations for defining drawing "subroutines"
    - (void)drawGreenCircle:(CGContextRef)ctxt {
        UIGraphicsPushContext(ctxt);
        [[UIColor greenColor] setFill];
        // draw my circle
        UIGraphicsPopContext();
    }

    - (void)drawRect:(CGRect)aRect {
        CGContextRef context = UIGraphicsGetCurrentContext();
        [[UIColor redColor] setFill];
        // do some stuff
        [self drawGreenCircle:context];
        // do more stuff and expect fill color to be red
    }

-----------------------------------------------------------------------------------------------------

Drawing Images
Use UIImageView to draw images, but if you feel you must ...

Create a UIImage object from a file in your Resources folder
    UIImage *image = [UIImage imageNamed:@"foo.jpg"];

Or create one from a named file or from raw data
    UIImage *image = [[UIImage alloc] initWithContentsOfFile:(NSString *)fullPath];
    UIImage *image = [[UIImage alloc] initWithData:(NSData *)imageData];

 
Or you can even create one by drawing with CGContext functions
    UIGraphicsBeginImageContext(CGSize);
    // draw with CGContext functions
    UIImage *myImage = UIGraphicsGetImageFromCurrentContext(); // screenshot
    UIGraphicsEndImageContext();

Now blast the UIImage's bits into the current graphics context

    UIImage *image = ...;
    [image drawAtPoint:(CGPoint)p];    // p is upper left corner of the image
    [image drawInRect:(CGRect)r];      // scales the image to fit in r
    [imagedrawAsPatternInRect:(CGRect)patRect; //tiles the image into patRect


Aside: You can get a PNG or JPG data representation of UIImage
    NSData *jpgData = 
    UIImageJPEGRepresentation((UIImage *)myImage, (CGFloat)quality);
 
    NSData *pngData = 

    UIImagePNGRepresentation((UIImage *)myImage);