分享

2011年冬斯坦福大学公开课 iOS应用开发教程学习笔记(第四课) Views 视图

 现在决定明天 2014-03-08

第四课名称: Views 视图


课程开始老师怀念了一会老乔。接着介绍这次的课程分为两部分,一部分是Calculator的Demo,一部分是Views.

课程开始到第四课,其实斯坦福的课程里是有作业的,人家已经做完了第一个作业了,就是完善计算器这个程序,完成一个比较复杂的计算器:


计算器大概要完整这么多的功能,有兴趣的同学可以把这个作业的pdf下载下来自己完成。下载地址:作业1

个人感觉这个计算器比较奇葩的地方是设计了一个Enter键。可能是为了减小程序的难度吧。

Demo的演示包括下面内容:

1、可编程性,添加一些API,作用是返回计算程序!Api要保证程序向上兼容。Brain是操作数和操作符的组合。通过类方法执行这个程序,也就是计算运算结果。

他说的计算程序,就是操作数和操作符的组合,把这个组合里的操作数和操作符弹栈并做相应的计算。

Api向上兼容就是说他没有改变Controller,程序一样能正常运行。

2、演示使用到了id类型、property 、数组的可变和不可变复制、内省、还有递归,一下子关联了这么多知识。

这位老师还强调,希望大家通过课程和作业,熟悉各个集合类的使用,熟悉Founation框架的使用,甚至熟悉和适应Obj-c。

用到id是,要用内省判断来包含id使用时不至于崩溃。

3、里面的描述的api留到作业了,应该就是把计算时的操作数和操作符 组合成字符串,这样Controller就可以把这些操作显示到view上。

4、课程提问讨论下nil判断包含的问题,老师说这是编码艺术的范畴,他喜好更少的代码,在确定不需nil判断时,尽量不要添加。我个人认为还是添加比较好,这样可以增加代码的可读性。这可能和人家大师的区别吧。

演示代码如下:

brain头文件:

  1. #import <Foundation/Foundation.h>  
  2.   
  3.   
  4. @interface CalculatorBrain : NSObject  
  5. - (void)pushOperand:(double)operand;  
  6. - (double)performOperation:(NSString *)operation;  
  7. @property (readonly) id program;  
  8.   
  9. + (double)runProgram:(id)program;  
  10. + (NSString *)descriptionOfProgram:(id)promram;  
  11. @end  
brain的实现文件:
  1. #import "CalculatorBrain.h"  
  2.   
  3. @interface CalculatorBrain()  
  4. @property (nonatomic, strong) NSMutableArray *programStack;  
  5. @end  
  6.   
  7. @implementation CalculatorBrain  
  8.   
  9. @synthesize programStack = _programStack;  
  10.   
  11. - (NSMutableArray *)programStack  
  12. {  
  13.     if (_programStack == nil) _programStack = [[NSMutableArray alloc] init];  
  14.     return _programStack;  
  15. }  
  16.   
  17. - (id)program  
  18. {  
  19.     return [self.programStack copy];  
  20. }  
  21.   
  22. + (NSString *)descriptionOfProgram:(id)program  
  23. {  
  24.     return @"Implement this in Homework #2";  
  25. }  
  26.   
  27. - (void)pushOperand:(double)operand  
  28. {  
  29.     [self.programStack addObject:[NSNumber numberWithDouble:operand]];  
  30. }  
  31.   
  32. - (double)performOperation:(NSString *)operation  
  33. {  
  34.     [self.programStack addObject:operation];  
  35.     return [[self class] runProgram:self.program];  
  36. }  
  37.   
  38. + (double)popOperandOffProgramStack:(NSMutableArray *)stack  
  39. {  
  40.     double result = 0;  
  41.       
  42.     id topOfStack = [stack lastObject];  
  43.     if (topOfStack) [stack removeLastObject];  
  44.       
  45.     if ([topOfStack isKindOfClass:[NSNumber class]])  
  46.     {  
  47.         result = [topOfStack doubleValue];  
  48.     }  
  49.     else if ([topOfStack isKindOfClass:[NSString class]])  
  50.     {  
  51.         NSString *operation = topOfStack;  
  52.         if ([operation isEqualToString:@"+"]) {  
  53.             result = [self popOperandOffProgramStack:stack] +  
  54.             [self popOperandOffProgramStack:stack];  
  55.         } else if ([@"*" isEqualToString:operation]) {  
  56.             result = [self popOperandOffProgramStack:stack] *  
  57.             [self popOperandOffProgramStack:stack];  
  58.         } else if ([operation isEqualToString:@"-"]) {  
  59.             double subtrahend = [self popOperandOffProgramStack:stack];  
  60.             result = [self popOperandOffProgramStack:stack] - subtrahend;  
  61.         } else if ([operation isEqualToString:@"/"]) {  
  62.             double divisor = [self popOperandOffProgramStack:stack];  
  63.             if (divisor) result = [self popOperandOffProgramStack:stack] / divisor;  
  64.         }  
  65.     }  
  66.       
  67.     return result;  
  68. }  
  69.   
  70. + (double)runProgram:(id)program  
  71. {  
  72.     NSMutableArray *stack;  
  73.     if ([program isKindOfClass:[NSArray class]]) {  
  74.         stack = [program mutableCopy];  
  75.     }  
  76.     return [self popOperandOffProgramStack:stack];  
  77. }  
  78.   
  79. @end  

runProgram方法运行计算程序。

第二部分,Views

view的内容

这个是全新的课程。

1、View是屏幕上一个矩形的空间

2、View处理两件事:画出矩形控件,并处理其中的事件

3、view组织架构:View是层结构的,View只有superView,可以有多个subView。子view的顺序和数组中的位置有关系,数字越大,越显示在后面。

4、UIWindow ,iOS中,UIWindow没有那么重要了。交给view,viewcontroller处理。

views 组织架构

可以在通过工具来管理view的组织架构,也可以通过代码:

-(void)addSubView:(UIView *)aView;

-(void)removeFromSuperview;

需要注意点的是:

通过父view添加子view

通过子view自己移除自己

view的坐标系统

单位:

CGFloat ,是个float数字,在obj-c里就要用这个单位

CGPoint,是个C结构体,CGPoint p = CGPointMake(33.2.22.3); 表示位置。

CGSize, 是个结构体,表示大小。

CGRect :由一个 CGPoint和一个CGSize组成

用来描述view的主要四种类型。

坐标:

左上角是坐标的原点。

不用关心一个的点有都少像素,系统会自动适配。如果有需要获取一个点是多少像素,通过这个属性:@property CGFloat contentScaleFactor。

view有三个属性和它的位置大小有关:

CGRect bounds 自己内部的绘制空间。

下面两个属性是父类用来定位你的view的属性。

CGRect center 

CGRect frame

为什么bounds和frame 不一样呢?因为view是可以伸缩,可以旋转的,看下图:


创建views

继承UIView。

通过alloc  init 创建view .例子:

  1. CGRect labelRect = CGRectMake(20, 20, 50, 30);  
  2. UILabel *label = [[UILabel alloc] initWithFrame:labelRect];   
  3. label.text = @”Hello!”;  
  4. [self.view addSubview:label];  

每个controller都有一个顶级的view,其他view都放在这个view上。

什么时候需要自定义view呢?当需要特殊的图形,或控制触摸事件的时候

通常不要继承内置的控件。

drawRect

怎么绘图呢?覆盖一个方法:-(void)drawRect:(CGRect)aRect;

红色警告:决不能自己调用drawRect:。系统调用这个方法。如果你需要重绘怎么办?发送这两个消息

  1. - (void)setNeedsDisplay;  
  2. - (void)setNeedsDisplayInRect:(CGRect)aRect;  
绘制开销很大

如何利用drawRect呢?调用核心图形框架,它是C的接口,不是面向对象的。

Core Graphics framework的基本概念是,你创建一个环境,然后创建一些轨迹,比如直线和弧线,再设置他们都字体颜色样式等并描边或填充到轨迹里。这就是绘图的过程。

绘制图片和文字是主要的,文字和轨迹是一回事,它有很多精细的弧线组成。

绘制图片是赋值二进制码。

context(环境) ,决定了你要在哪绘制。

每次drawRect是的环境都是不一样的,所以不要缓存context。

获取环境的代码:

  1. CGContextRef context = UIGraphicsGetCurrentContext();  

几乎所有的drawRect都把这个放在第一行。
  1. CGContextBeginPath(context);  
  2. CGContextMoveToPoint(context, 75, 10);  
  3. CGContextAddLineToPoint(context, 160, 150);  
  4. CGContextAddLineToPoint(context, 10, 150);  
  5. [[UIColor greenColor] setFill];   
  6. [[UIColor redColor] setStroke];  
  7. CGContextDrawPath(context,kCGPathFillStroke); //kCGPathFillStroke is a constant  
上面代码:绘制的过程,先开始一个轨迹,移动轨迹的点,添加线,填充绿色,描边是红色, 颜色不需要指定context,默认就是当前的context。

调用 CGContextDrawpath在屏幕上画出来。

可以定义一个轨迹保存,在其他环境重用。
透明:

  1. @property CGFloat alpha  
  2. @property BOOL opaque  
alpha  1,不透明, 0透明。
  1. @property (nonatomic) BOOL hidden;  
隐藏view。

画文字

用UILabel
用UIFont设置字体 大小
  1. UIFont *myFont = [UIFont systemFontOfSize:12.0];  
  2. UIFont *theFont = [UIFont fontWithName:@“Helvetica” size:36.0];  
  3. NSArray *availableFonts = [UIFont familyNames];  
最后一个获取可用的字体。
用NSString 来画文字
  1. NSString *text = ...;  
  2. [text drawAtPoint:(CGPoint)p withFont:theFont]; // NSString instance method  
因为UIKit,所以NSString也能实现UI上的功能,用了categories .

画图像

UIImageView 
通过下面的方式后去图像:
xcode
  1. UIImage *image = [UIImage imageNamed:@“foo.jpg”];  
二进制,网络
  1. UIImage *image = [[UIImage alloc] initWithContentsOfFile:(NSString *)fullPath];  
  2. UIImage *image = [[UIImage alloc] initWithData:(NSData *)imageData];  
通过CGContext函数
  1. UIGraphicsBeginImageContext(CGSize);  
  2. // draw with CGContext functions  
  3. UIImage *myImage = UIGraphicsGetImageFromCurrentContext();  
  4. UIGraphicsEndImageContext();  
在环境里画出来
  1. [image drawAtPoint:(CGPoint)p];  
  2. [image drawInRect:(CGRect)r];  
  3. [image drawAsPatternInRect:(CGRect)patRect;  
drawAtPoint 会按原大小画出来
drawInRect会缩放。
drawAsPatternInRect会重复绘制来甜蜜指定的区域。

下节课预告。会讲到源码控制,协议,自定义的UIView ViewController的生命周期。还有storyboard的讲解。对应两个平台的storyboard的使用。

容芳志 (http://blog.csdn.net/totogo2010)

本文遵循“署名-非商业用途-保持一致”创作公用协议


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多