Big Nerd iOS Programming 第10章以及后面的点

来源:互联网 发布:kafka pagecache 源码 编辑:程序博客网 时间:2024/05/21 10:30
1. A Simple iOS Application
2. Objective-C
3. Managing Memory with ARC
4. Views and the View Hierarchy
5. Views: Redrawing and UIScrollView
6. View Controllers
7. Delegation and Text Input
8. UITableView and UITableViewController
9. Editing UITableView
10. UINavigationController
11. Camera
12. Touch Events and UIResponder
13. UIGestureRecognizer and UIMenuController
14. Debugging Tools
15. Introduction to Auto Layout
16. Auto Layout: Programmatic Constraints
17. Autorotation, Popover Controllers, and Modal View Controllers
18. Saving, Loading, and Application States
19. Subclassing UITableViewCell
20. Dynamic Type
21. Web Services and UIWebView
22. UISplitViewController
23. Core Data
24. State Restoration
25. Localization
26. NSUserDefaults
27. Controlling Animations
28. UIStoryboard
29. Afterword

bignerd第10章 UINavigationController
1.rely on each other
    drill-down interface.向下获取数据

2.UINavigationController 保持了所有screens的堆栈

    root view controler: UIViewController是堆栈的最底层

    when a UIViewController is pushed onto the stack,its view slides onto the screen from the right

                    |navigateBar ->
    UIViewController|                        |rootViewController(ListViewController)
                    |viewControllers(array) |
                    |                        |appViewController(DetailViewController)

    属性 topViewController获取最顶端的视图控制器

    UINavigationController是 UIViewController的子类,也有view属性,
    view 一般都有两个子view: UINavigationBar 和 the view of topViewController

3.tip
    when writing IOS applications, it is important to treat each UIViewController as its own little world.

4.几个要点:
    控制器之间传递数据
        重写比如BNRItem *item的setter,
        在viewDidAppear之类的函数中操作显示
    手动push viewController

//////几个章节做概览即可。然后去做实际的项目练习,不清楚的再回来翻/////////
11章Camera
    UIImageView:
                    aspect fit  contentMode
    UIToolbar

    UIImagePickerController


 设定类型
    image picker's source type  UIImagePickerControllerSourceTypeCamera,PhotoLibrary,PhotosAlbum.类型
          使用之前先判定 isSourceTypeAvailable:
设定delegata
    头文件声明 <UINavigationControllerDelegate,UIImagePickerControllerDelegate>
        image picker's delegate = self;

        成功选择图片:
            imagePickerController:didFinishPickingMediaWithInfo:
        取消选择
            imagePickerControllerDidCancel
          
        presenting the image picker modally
            - (IBAction)takePicture:(id)sender
                {
                    UIImagePickerController *imagePicker =
                            [[UIImagePickerController alloc] init];

                    // If the device has a camera, take a picture, otherwise,
                    // just pick from photo library
                    if ([UIImagePickerController
                            isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
                        imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
                    } else {
                        imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
                    }

                    imagePicker.delegate = self;
                    [self presentViewController:imagePicker animated:YES completion:nil];
                }
    --------------------------------
    获取图片saving image
        - (void)imagePickerController:(UIImagePickerController *)picker
        didFinishPickingMediaWithInfo:(NSDictionary *)info
        {
            // Get picked image from info dictionary
            UIImage *image = info[UIImagePickerControllerOriginalImage];

            // Put that image onto the screen in our image view
            self.imageView.image = image;

            // Take image picker off the screen -
            // you must call this dismiss method
            [self dismissViewControllerAnimated:YES completion:nil];
        }

注意:按上面那种方式,当你保存很多图片时,很占内存,甚至应用被强行关闭。
       用BNRImageStore来保存图片,当受到内存不足的警告时清理不需要的。

    NSDictionary

    NSUUID  创建一个唯一的 码?

    #pragma mark

    隐藏键盘:
        -(BOOL)textFieldShouldReture:(UITextField *)textField
        {
            [textField resignFirstResponder];
            return YES;
        }
        BNRDetailViewController.xib中,选择view,更改类为UIControl,将view链接出一个单击action,
            [self.view endEditing:YES];

    Recording Video
        判断是否支持录像
         UIImagePickerController *ipc = [[UIImagePickerController alloc] init];
            NSArray *availableTypes = [UIImagePickerController
                availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];
            ipc.mediaTypes = availableTypes;
            ipc.sourceType = UIImagePickerControllerSourceTypeCamera;
            ipc.delegate = self;

        委托
        - (void)imagePickerController:(UIImagePickerController *)picker
        didFinishPickingMediaWithInfo:(NSDictionary *)info
        {
            // 保存在影片在磁盘中的地址
            NSURL *mediaURL = info[UIImagePickerControllerMediaURL];
            if (mediaURL) {

            // Make sure this device supports videos in its photo album
            if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum([mediaURL path])) {

                // Save the video to the photos album
                UISaveVideoAtPathToSavedPhotosAlbum([mediaURL path], nil, nil, nil);

                // Remove the video from the temporary directory
                [[NSFileManager defaultManager] removeItemAtPath:[mediaURL path]
                                                           error:nil];
            }
        }
        }
注意:限制用户只选择拍照或者只录像
    两者都可选:pass the return value from availableMediaTypesForSourceType:
    拍照的话:保持mediaTypes为默认的即可
    只要录像:First, you must make sure the device supports video, and then you must set the mediaTypes property to an array containing only the identifier for video.
            NSArray *availableTypes = [UIImagePickerController
        availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];
        if ([availableTypes containsObject:(__bridge NSString *)kUTTypeMovie]) {
            [ipc setMediaTypes:@[(__bridge NSString *)kUTTypeMovie]];
        }

12章 Touch Events and UIResponder
    触摸事件touch events,手势 gestures, 调试 debugging application

    UIView 继承UIResponder,所以可以重写以下四个方法:
        touchBegan:(NSSet *)touches withEvent:
        touchMoved:withEvent:
        touchEnded:withEvent:
        touchCancel:withEvent:

        touche中有个UITouch的对象,包含了触碰的位置等信息
        你不需要保存UITouch的对象,因为在事件中你可以访问得到。
        当手指滑出初始触碰到视图,会受到touchMoved和touchEnded
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 重写几个touch事件,获取location。
// setNeedDisplay,系统自动调用drawRect,
// 如何绘制、设置颜色、stoke等。

            #import "BNRDrawView.h"
            #import "BNRLine.h"

            @interface BNRDrawView()
            
                @property (nonatomic,strong) NSMutableArray *finishedLines;
                @property (nonatomic,strong) BNRLine *currentLine;
            
            @end

            @implementation BNRDrawView

            -(instanceType)initWithFrame:(CGRect)r
            {
                self = [super initWithFrame:r];
                if(self)
                {
                    self.finishedLines = [[NSMutableArray alloc] init];
                    self.backgroundColor = [UIColor grayColor];
                }
                
            }

            - (void) strokeLine: (BNRLine *)line
            {
                UIBezierPath *bp = [UIBezierPath bezierPath];
                bp.lineWith = 10;
                bp.lineCapStyle = kCGLineCapRound;
                
                [bp moveToPoint:line.begin];
                [bp addLineToPoint: line.end];
                [bp stroke];
            }

            -(void)drawRect:(CGRect) rect
            {
                // 每次都要重新遍历finishedLines再重新绘制???
                [[UIColor blackColor] set];
                for(BNRLine *line in self.finishedLines]
                {
                    [self strokeLine:line];
                }
                
                if(self.currentLine){
                    [[UIColor redColor] set];
                    [self strokeLine:self.currentLine];
                }
            }   

            - (void) touchBegan:(NSSet *)touches withEvent:(UIEvent *)event
            {
                UITouch *touch = [touches anyObject];
                CGPoint location = [touch locationInView:self];
                self.currentLine = [[BNRLine alloc] init];
                self.currentLine.begin = location;
                self.currentLine.end = location;
                [self setNeedDisplay];
            }

            - (void) touchMoved:(NSSet *)touches withEvent:(UIEvent *)event
            {
                UITouch *t = [touches anyObject];
                CGPoint location = [t locationInView:self];
                self.currentLine.end = location;
                [self setNeedDisplay];
            }

            -(void) touchEnded:(NSSet *)touches withEvent:(UIEvent *)event
            {
                [self.finishedLines addObject:self.currentLine];
                self.currentLine = nil;
                [self setNeedDisplay];
            }

            @end
-----------------------------------------------------------------------
    多点触控。
        默认情况下一个view只能接受一个finger的touch: 一个手指触发了touchBegan,但是没有ended。则view会忽略其他触碰

     self.multipleTouchEnabled = YES;
     touchCancelled发生在系统事件,比如电话来了~,一般这时候会把当前线段都移除掉

     保存多个数据
         for (UITouch *t in touches) {
            CGPoint location = [t locationInView:self];

            BNRLine *line = [[BNRLine alloc] init];
            line.begin = location;
            line.end = location;

            NSValue *key = [NSValue valueWithNonretainedObject:t];
            self.linesInProgress[key] = line;
        }
        //用NSValue *key来作为字典的key而不是直接用t,因为字典的key是实现了NSCopying协议

    ------------------------------------------------------------------------
        #import "BNRDrawView.h"
        #import "BNRLine.h"

        @interface BNRDrawView
        {
            @property (nonatomic,strong) NSMutableDictionary *linesInProgress;
            @property (nonatomic,strong) NSMutableArray *finishedLines;
            // @property (nonatomic,strong) BNRLine *currentLine;
        }
        @end

        @implementation BNRDrawView

        -(instanceType)initWithFrame:(CGRect)r
        {
            self = [super initWithFrame:r];
            if(self)
            {
                self.linesInProgress = [[NSMutableArray] alloc] init];
                self.finishedLines = [[NSMutableArray alloc] init];
                self.backgroundColor = [UIColor grayColor];
            }
            
        }

        - (void) strokeLine: (BNRLine *)line
        {
            UIBezierPath *bp = [UIBezierPath bezierPath];
            bp.lineWith = 10;
            bp.lineCapStyle = kCGLineCapRound;
            
            [bp moveToPoint:line.begin];
            [bp addLineToPoint: line.end];
            [bp stroke];
        }

        -(void)drawRect:(CGRect) rect
        {
            // finished
            [[UIColor blackColor] set];
            for(BNRLine *line in self.finishedLines]
            {
                [self strokeLine:line];
            }

            // current progress
            [[UIColor redColor] set];
            for(BNRLine *line in self.linesInProgress){
                [self strokeLine:line];
            }
        }   

        - (void) touchBegan:(NSSet *)touches withEvent:(UIEvent *)event
        {
            for(UITouch *t in touches){
                CGPoint location = [t locationInView:self];
                NSValue *key = [NSValue valueWithNonretainedObject:t];
                BNRLine *line = [[BNRLine alloc] init];
                line.begin = location;
                line.end = location;
                self.linesInProgress[key] = line;
            }
            [self setNeedDisplay];
        }

        - (void) touchMoved:(NSSet *)touches withEvent:(UIEvent *)event
        {
            for(UITouch *t in touches){
                CGPoint location = [t locationInView:self];
                NSValue *key = [NSValue valueWithNonretainedObject:t];
                BNRLine *line = self.linesInProgress[key];
                line.end = location;
            }
            [self setNeedDisplay];
        }

        -(void) touchEnded:(NSSet *)touches withEvent:(UIEvent *)event
        {
            for(UITouch *t in touches){
                NSValue *key = [NSValue valueWithNonretainedObject:t];
                BNRLine *line = self.linesInProgress[key];
                [self.finishedLines addObject:line];
                [self.linesInProgress removeObjectForKey:key];
            }
            [self setNeedDisplay];
        }

        -(void) touchCancelled:(NSSet *)touches withEvent:(UIEvent *)event
        {
            for(UITouch *t in touches){
                NSValue *key = [NSValue valueWithNonretainedObject:t];
                [self.linesInProgress removeObjectForKey:key];
            }
            [self setNeedDisplay];
        }

        @end





    Responder chain
        每个responder有一个nextResponder属性,构成chain。 rootView: window's nextResponder is UIApplication
'
    UIControl:can set targets and actions
        the superclass of UIButton,UISlider...
        [rButton addTarget:tempController action:@selector(resetTemperature:) forControlEvents:UIControlEventTouchUpInSide | UIControlEventTouchUpOutSide]

        then you can send event:
        [self sendActionsForControlEvents:UIControlEventTouchUpInSide]

        消息不是直接发送给目标view,而是通过UIApplication来找到target
        -----------重写UIResponder---------------------
        - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
        {
            // Reference to the touch that is ending
            UITouch *touch = [touches anyObject];

            // Location of that point in this control's coordinate system
            CGPoint touchLocation = [touch locationInView:self];

            // Is that point still in my viewing bounds?
            if (CGRectContainsPoint(self.bounds, touchLocation))
            {
                // Send out action messages to all targets registered for this event!
                [self sendActionsForControlEvents:UIControlEventTouchUpInside];
            } else {
                // The touch ended outside the bounds, different control event
                [self sendActionsForControlEvents:UIControlEventTouchUpOutside];
            }
        }

13章 UIGestureRecognizer and UIMenuController
    创建自定义手势
    按钮: 例如长按文本出现的按钮,自定义

    UILongPressGestureRecognizer
    UIPanGestureRecognizer and Simultaneous Recognizers

    UIMenuController and UIResponderStajdardEditAction

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

Chapter 13 UIGestureRecognizer and UIMenuController.

1. gesture like pinch or swipe
2.you don't instantiate UIGestureRecognizer, system has some subclass that u can use for the particular gesture. the action message like:
- (void) action:(UIGestureRecognizer *)gestureRecognizer;
** when recognizing a gesture,the gesture recognizer intercepts the touch destined for the view.so the like touchBegan: may not receive. the flow:
    UIApplication --touch event--> UIWindow --touch event--> UIGestureRecognizer -- recognized gesture(yes/no)--> if yes: send action: to view; if not,send touchesBegan:withEvent: to the view.
*********************
UITapGestureRecognizer: double tap screen and clear the lines:
-(instancetype)initWithFrame:(CGRect)r
{
//......
UITapGestureRecognizer *doubleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTap:)];
doubleTapRecognizer.numberOfTapsRequired = 2;
[self addGestureRecognizer:doubleTapRecognizer];

return self;
}

-(void)doubleTap:(UIGestureRecognizer *)gr
{
// for a double tap, u don't need information from gr
[self.linesInProgress removeAllObjects];
[self.finishedLines removeAllObjects];
[self setNeedsDisplay];
}
the flow: 1.send touchesBegan:; 2.recognized the double tap, send doubleTap: 3.send touchedCancelled:.
*** so if u don't want the 1 happens,set like:
doubleTapRecognizer.delaysTouchesBegan = YES;

----------------multiple gesture recognizers----------
like: if u add a tap and double tap to a view,when u double the view,it will send to tap first and then send to doubleTap. So, the truth is : if u double tap the screen,the tap may not what u want to trigger,so set like:
[tapRecognizer requireGestureRecognizerToFail:doubleTapRecognizer];
means during the double tap happen, the one tap will force to fail.

***** one tap to choose a line*******
when select a line,a menu appear right at the tap point.

UIMenuController, 
UIMenuItem (the list that controller has) each item has a title and action. the action message is send to the first responder of the window,so there is not the gesture,view 's business///
***There is only one UIMenuController per Application, u can fill it with menu items to it, and give it a rectangle to present form,and set it to be visible.******

do like:
-(void) tap:(UIGestureRecognizer *)gr
{
// get the tap location
CGPoint point = [gr locationInView:self];
self.selectedLine = [self lineAtPoint:point];
if(self.selectedLine){
//!!! make ourselves the target of menu item
// action messages
[self becomeFirstResponder];
// grab the msnu controller
UIMenuController *menu = [UIMenuController sharedMenuController];
// create delete item
UIMenuItem *deleteItem = [[UIMenuItem alloc] initWithTitle:@"Delete" action:@selector(deleteLine:)];
menu.menuItems = @[deleteItem];
// show it
[menu setTargetRect:CGRectMake(point.x,point.y,2,2) inView:self];
[menu setMenuVisible:YES animated:YES];
}else{
// hide menu controller
[[UIMenuController sharedMenuController] setMenuVisible:NO animated:YES];
}
[self setNeedsDisplay];
}



*****if u have a custom class needs to become the first responder,u must override canBecomeFirstResponder:
-(BOOL)canBecomeFirstResponder
{
return YES;
}


*** what u do below, when u tap a line, the menu is not shown at all. the reason:
1.becomeFirstResponder       [done]
2.implemented each item's selector  [not yet]

so:
-(void) deleteLine:(BNRLine *) line
{
[self.finishedLines removeObject:self.selectedLine];
[self setNeedsDisplay];
}
 ======================================
UILongPressGestureRecognizer
***when u hold down on a line (a long press),u selected the line and then drag it around by dragging you finger (pan)
as add other gesture add the long press gesture.
notice that need more than 0.5s,u can change it by set minimumPressDuration.

%%the below gesture is the simple gesture: by the time it is recognized,the gesture is over, and the message has been delivered . 
%% long press is occurs over time and is defined by three separate events.
UIGestureRecognizerStatePossible,   [press a while]
UIGestureRecgonizerStateBegan,    [like at lease 0.5]
UIGestureRecognizerStateEnded. [remove finger]

the state property

*************
-(void)longPress:(UIGestureRecognizer *)rg
{
if(rg.state == UIGestureRecognizerStateBegan){
CGPoint *point = [rg locationInView:self];
self.selectedLine = [self lineAtPoint:point];
if(self.selectedLine){
self.linesInProgress removeAllObjects];
}
}else if(rg.state == UIGestureRecognizerStateEnded){
self.selectedLine = nil;
}
[self setNeedsDisplay];
}

------------UIPanGestureRecognizer Simultaneous Recognizer---------------
pan: move the line with finger around the screen

** normally ,a gesture recognizer does not share the touches.just like eat the touch,and no other recognizer get a chance to handle it. But this is bad ,u need the long press and panning.

do like:
@interface BNRDrawView () <UIGestureRecognizerDelegate>

@property (nonatomic,strong) UIPanGestureRecognizer *moveRecognizer;
// other code ....

@end

// code in implementation

self.moveRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(moveLine:) ];
self.moveRecognizer.delegate = self;
self.moveRecognizer.cancelsTouchesInView = NO;
[self addGestureRecognizer:self.moveRecognizer];

*****u just need to implementation one method about UIGestureRecognizerDelegate protocol,:
gestureRecognizer:shouldRecognizerSimultaneouslyWithGestureRecognizer:

&&when a recognizer hold the gesture,at the same time ,another recognizer recognized the gesture,so, it will send the message.

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizerShouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)other
{
if(gestureRecognizer == self.moveRecognizer){
return YES;
}
return NO;
}

-(void)moveLine:(UIPanGestureRecognizer *)gr
{
if(!self.selectedLine){
return;
}
if(gr.state == UIGestureRecognizerStateChanged){
CGPoint translation = [gr translationInView:self]
CGPoint begin = self.selectedLine.begin;
CGPoint end = self.selectedLine.end;
begin.x += translation.x;
begin.y += translation.y;
end.x += translation.x;
end.y += translation.y;
self.selectedLine.begin = begin;
self.selectedLine.end = end;
[self setNeedsDisplay];

//************]
[gr setTranslation:CGPointZero inView:self];
}
}
-----------------------------------------------------------------------------------------------------------------------------------------


14章 Debugging Tools

    Gauges
    Instruments
    leaks Instrument
    static analyzer

    Projects, targets and Build settings

15章 Introduction to Auto Layout

    add constraints
    Debugging constraints
    unsatisfiable constraints

    Debugging using the Auto Layout trace

    multiple xib files

16章 programmatic constraints

    NSAutoresizingMaskLayoutConstraint

17章 Autorotation,Popocwe controllers Modal view controllers
    set in xib
    rotation notification
        prepareViewsForOrientation:orientation

    UIPopoverController
    Modal view controllers
    Dismissing modal view controllers
    modal view controller styles

    Thread-Safe Singletons

    block

    View controller relationship
        parent-child relationships
        presenting-presenter relationships
        Inter-family relationships

18章 Saving,Loading and Application States
    Application Sandbox
    Constructing a file path
    NSKeyedArchiver and NSKeyedUnarchiver

    Application States and Transitions

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

存档 
1.Archiving,永久存储数据。
Archiving:记录并存储属性
Unarchiving:从数据中重新重新创建对象。


实现NSCoding协议,实现两个方法 encodeWithCoder:, initWithCoder:


    - (void)encodeWithCoder:(NSCoder *)aCoder
{
   [aCoder encodeObject:self.itemName forKey:@"itemName"];
   [aCoder encodeObject:self.serialNumber forKey:@"serialNumber"];
   [aCoder encodeObject:self.dateCreated forKey:@"dateCreated"];
   [aCoder encodeObject:self.itemKey forKey:@"itemKey"];


   [aCoder encodeInt:self.valueInDollars forKey:@"valueInDollars"];
}


-(instancetype) initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if(self){
_itemName = [aDecoder decodeObjectForKey:@"itemName"];
}
return self;
}


2.应用沙箱, Application sandbox
程序的数据,缓存等。 不能访问其他应用的沙箱


!!!!!!!!!存储路径!!!!!!!!!!
-(NSString *)itemArchivePath
{
NSArray *documentDirectories = 
NSSearchPathForDirectoriesInDomain(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentDirectiry = [documentDirectories firstObject];
return [documentDirectories stringByAppendingPathComponent:@"items.archive"];


}


**************上面的到了存储的路径,以及药存储的模型数据。那什么时候出发存储已经什么时候加载数据呢?******************


1.存储: 
使用NSKeyedArchiver when application exits.


eg. BNRItem
-(BOOL) saveChanges
{
NSString *path = [self itemArchivePath];
return [NSKeyedArchiver archiveRootObject:self.privateItems];
}


!archiveRootObject:toFile: 工作流程:
1.创建NSKeyedArchiver 对象
2.privateItems发送消息 encodeWithCoder: 并且把 NSKeyedArchiver的对象作为参数。
3.privateItems发送每个其中的字对象  encodeWithCoder,并且传入 NSKeyedArchiver
4.NSKeyedArchiver 写数据到系统文件夹中




当按下home键,applicationDidEnterBackground:会发送到applicationDelegate中,你可以在其中调用saveChanges
它会存在系统文件夹下,一个document文件夹中 item.archive


加载!!:
-(instancetype)initPrivate
{
self = [super init];
if(self){
NSString *path = [self itemArchivePath];
_privateItems = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
if(!_privateItems){
_privateItems = [[NSMutableArray alloc] init];
}
}
return self;
}

------------------------------------------------------------------------------------------------------------------------------------------------------------------------
~~~~~~~~~~~~~~~~~~
Application State and Transitions


    Writing to the Filesystem with NSData

    NSNotificationCenter and Low-Memory Warnings

    Model-View-Controller Store Design Pattern

    Cur:Application States Transitions
    Cur:Reading and Writing to the Filesystem
    Cur:the application bundle

19章 subclassing UITableViewCell 自定义单元格

    Image Manipulation

    Variable capturing

20章 Dynamic Type
    动态
    using preferred fonts
    responding to user changes
    updating auto Layout


21章 web services and UIWebView
    Json data
    the main thread

    credentials

    Cur:the request body

22章 UISplitViewController
    like ipad app,left part is center ,right part is views
    !Displaying the master view controller in portrait mode

    Universalizing Nerdfeed

!23章 Core Data
    Local saving
    SQL
    Faults

24章 State Restoration 对象恢复技术

25章 Localization
    Internationalization using NSNumberFormat
    Localizing resources
    NSLocalizedString() and String Tables

    Cur:Localizing XIB files without Base Internationalization

26章 NSUserDefauls
    read a preference
    change a preference
    setting bundle

    editing the root.plist
    localized root.plist

27章 Controlling Animations
    Base Animations
    Timing functions
    keyframe animations

    animations completion

    spring animations 弹簧 弹性

28章 UIStoryboard
    creating a storyboard [xcode interface]
    UITableViewControllers in storyboards // 指定root
    segues // navigation type
    enabling color changes

    !passing data around

29章 afterword
    next:
        犯些错
        阅读tedious乏味的文档
        多问,多交流
    建议:
        1.动手写App
            如果你没有立即使用你现在学到,知识将慢慢褪去。现在开始练习并且拓展你的知识
        2.深入
            本书的每个章节都可以更深入的写成一本书。找一个你感兴趣的然后去探索,做些联系,阅读苹果的官方文档,看博客或者stackoverflow上的问答
        3.交流
            多与别人交流
        4.出bug,修bug
            慢慢就能成长起来
        5.分享知识
            虚心回答别人的问题,分享代码
0 0
原创粉丝点击