您的位置:首页 > 移动开发 > IOS开发

IOS学习之斯坦福大学IOS开发课程笔记(第四课)

2014-08-14 14:46 821 查看
转载请注明出处

作者:小马

第三节课没什么重要内容,直接跳过。

这节课前半节课, 其实是对第二课的深入,第二课讲了一个简易的计算器,这节课让这个计算器“可编程”。所谓的“可编程”就是可以解析变量并计算,比如我传入”3+2”,就可以得到结果5。 老师在课堂上只实现了部分功能,完整的是作为学生的作业。下半节课讲关于view的一些概念。

一 上半节课

1 增加两个类方法作为公共的API, 为了向上兼容,上节课的那两个也还保留。如下:

[objc] view
plaincopy

@interface calculatorBrain : NSObject

- (void)pushOperand:(double)operand;

- (double)performOperation:(NSString *)operation;

@property (nonatomic, readonly)id program;

+ (double)runProgram:(id)program;

+ (NSString*) descriptionOfProgram:(id)program;

@end

2 让内部的数据堆栈更加通用。

原来的堆栈只能存操作数,不能存操作符,这里要让它也能存操作符。如下(为了增加可读性,把它的名字也改了):

[objc] view
plaincopy





@interface calculatorBrain ()

@property (nonatomic, strong)NSMutableArray *programStack; //可以存操作数和操作符。

@end

-(void)pushOperand:(double)operand

{

[self.programStack addObject:[NSNumber numberWithDouble:operand]];

}

-(double)performOperation:(NSString *)operation

{

[self.programStack addObject:operation];//操作符也进栈

return [calculatorBrain runProgram:self.programStack];

}

3 popOperand方法就用不到了:

[objc] view
plaincopy





//-(double)popOperand

//{

// NSNumber *operandObject = [self.operandStack lastObject];

//

// //注意这里,如果operandObject为nil, 下面执行remove会让程序崩溃,所以要加上判断

// //lastObject方法不用判断

// if (operandObject)

// {

// [self.operandStack removeLastObject];

// }

//

// return [operandObject doubleValue];

//}

4 为program实现getter.

Program是只读属性,只要实现getter就行了,我们打算用这个getter返回内部的programStack。 但是有个问题,programStack是内部的一个变量,我们不希望别人破坏它,所以只是返回它的一个copy,如下:

[objc] view
plaincopy





-(id)program

{

return [self.program copy];

}

而且,对一个NSMutableArray做copy,得到的是一个NSArray。 是不可改变的。 如果想要得到可变的,要用mutableCopy。Stackoverflow上有如下的解释:

mutableCopy alwaysreturns a mutable result.

copy alwaysreturns an immutable result。

5 runProgram做了什么

代码如下:

[objc] view
plaincopy





+ (double)runProgram:(id)program

{

NSMutableArray *stack;

if ([program isKindOfClass:[NSArray class]])

{

//注意这个判断条件是不能少的,并不是id类型都有mutableCopy方法。

stack = [program mutableCopy];

}

return [self popOperandOffStack:stack];

}

+ (double)popOperandOffStack:(NSMutableArray *)stack

{

double result = 0;

//注意类型是id, 因为取出来的可能是操作数,也可能是操作符。

id topStack= [stack lastObject];

if(topStack)

{

[stack removeLastObject];

}

if([topStack isKindOfClass:[NSNumber class]])

{

result = [topStack doubleValue];

}

else if([topStackisKindOfClass:[NSString class]])

{

NSString*operation = topStack;

if([operation isEqualToString:@"+"]) //只实现加法

{

result = [self popOperandOffStack:stack] +[self popOperandOffStack:stack];

}

}

return result;

}

源码下载地址:
http://download.csdn.net/detail/pony_maggie/7314481
二 下半节课

首先讲到创建一个view的方法示例,这里注意一下self.view的用法,self指的是当前的controller, self.view就是这个controller的top level view.



另外,要补充一点,这节课里老师不断的强调简单这个词,他的意思是,最好的代码一定是最少的的代码实现同样的功能。果然是apple出来的人,提倡简单之美.

接着,什么时候我们需要自定义一个view(custom view), 如何自定义一个view?



主要是两个情况,一是要重画view, 二是重定义touch事件.

重画的方法马上就说了,重载drawRect方法就可以了,给个实现的示例,注意这里实现调用的都是基于C的API, 回想一下第一节课讲IOS架构时的内容,融会贯通一下。

[objc] view
plaincopy





//绘制一个方块

-(void)drawRect:(CGRect)rect {

// Drawing code.

//获得处理的上下文

CGContextRef context =UIGraphicsGetCurrentContext();

//设置线条样式

CGContextSetLineCap(context, kCGLineCapSquare);

//设置线条粗细宽度

CGContextSetLineWidth(context,1.0);

//设置颜色

CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0);

//开始一个起始路径

CGContextBeginPath(context);

//起始点设置为(0,0):注意这是上下文对应区域中的相对坐标,

CGContextMoveToPoint(context, 0,0);

//设置下一个坐标点

CGContextAddLineToPoint(context,100, 100);

//设置下一个坐标点

CGContextAddLineToPoint(context,0, 150);

//设置下一个坐标点

CGContextAddLineToPoint(context,50, 180);

//连接上面定义的坐标点

CGContextStrokePath(context);

}

记得不要主动调用drawRect方法,它是系统调用的,你只要实现就行了。 当然你可以通知系统你改了drawRect,用下面两个方法:

setNeedsDisplay

setNeedsDisplayInRect

drawRect只会被调用一次, 因为draw是很expensive的(请原谅我装逼,卖弄英文),比如我自己定义了一个view, 这个view里面有一些属性,然后外部通过setter访问了这些属性, 那这个view的drawRect也只会被调用一次,并不是你调用一次setter,drawRect就调用一次.

如何在自定义视图上写文字?



有两种方式, 一种最直观的方法,用UILabel,生成一个UILabel的实例,设置它的text属性,非常简单。

另一种方式是自己”画文字”, 首先定义字体:

[objc] view
plaincopy





UIFont *myFont = [UIFontsystemFontOfSize:12.0];

UIFont *theFont = [UIFont fontWithName:@”Helvetica”size:36.0];

然后是NSString:

[objc] view
plaincopy





NSString *text = “abc”;

[text drawAtPoint:(CGPoint)pwithFont:theFont];

这个看起来有点奇怪,NSString是foundation kit里的对象,怎么能用来”画图”呢,关键在于drawAtPoint这个方法,这个方法通过category机制,加到UIKit里,所以它其实算是NSString在UI框架里的一个扩展.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐