斯坦福大學公開課 iOS應用開發教程學習筆記(第四課) Views 檢視
第四課名稱: 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標頭檔案:
- #import <Foundation/Foundation.h>
- @interface CalculatorBrain : NSObject
- - (void)pushOperand:(double)operand;
- - (double)performOperation:(NSString *)operation;
-
@property (readonly) id program;
- + (double)runProgram:(id)program;
- + (NSString *)descriptionOfProgram:(id)promram;
- @end
- #import "CalculatorBrain.h"
- @interface CalculatorBrain()
- @property (nonatomic, strong) NSMutableArray *programStack;
- @end
- @implementation CalculatorBrain
- @synthesize programStack = _programStack;
- - (NSMutableArray *)programStack
- {
- if (_programStack == nil) _programStack = [[NSMutableArray alloc] init];
- return _programStack;
- }
- - (id)program
- {
- return [self.programStack copy];
- }
- + (NSString *)descriptionOfProgram:(id)program
- {
- return @"Implement this in Homework #2";
- }
- - (void)pushOperand:(double)operand
- {
- [self.programStack addObject:[NSNumber numberWithDouble:operand]];
- }
- - (double)performOperation:(NSString *)operation
- {
- [self.programStack addObject:operation];
- return [[self class] runProgram:self.program];
- }
- + (double)popOperandOffProgramStack:(NSMutableArray *)stack
- {
- double result = 0;
- id topOfStack = [stack lastObject];
- if (topOfStack) [stack removeLastObject];
- if ([topOfStack isKindOfClass:[NSNumber class]])
- {
- result = [topOfStack doubleValue];
- }
- elseif ([topOfStack isKindOfClass:[NSString class]])
- {
- NSString *operation = topOfStack;
- if ([operation isEqualToString:@"+"]) {
- result = [self popOperandOffProgramStack:stack] +
- [self popOperandOffProgramStack:stack];
- } elseif ([@"*" isEqualToString:operation]) {
- result = [self popOperandOffProgramStack:stack] *
- [self popOperandOffProgramStack:stack];
- } elseif ([operation isEqualToString:@"-"]) {
- double subtrahend = [self popOperandOffProgramStack:stack];
- result = [self popOperandOffProgramStack:stack] - subtrahend;
- } elseif ([operation isEqualToString:@"/"]) {
- double divisor = [self popOperandOffProgramStack:stack];
- if (divisor) result = [self popOperandOffProgramStack:stack] / divisor;
- }
- }
- return result;
- }
- + (double)runProgram:(id)program
- {
- NSMutableArray *stack;
- if ([program isKindOfClass:[NSArray class]]) {
- stack = [program mutableCopy];
- }
- return [self popOperandOffProgramStack:stack];
- }
- @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 .例子:
- CGRect labelRect = CGRectMake(20, 20, 50, 30);
- UILabel *label = [[UILabel alloc] initWithFrame:labelRect];
- label.text = @”Hello!”;
- [self.view addSubview:label];
每個controller都有一個頂級的view,其他view都放在這個view上。
什麼時候需要自定義view呢?當需要特殊的圖形,或控制觸控事件的時候
通常不要繼承內建的控制元件。
drawRect
怎麼繪圖呢?覆蓋一個方法:-(void)drawRect:(CGRect)aRect;
紅色警告:決不能自己呼叫drawRect:。系統呼叫這個方法。如果你需要重繪怎麼辦?傳送這兩個訊息
- - (void)setNeedsDisplay;
- - (void)setNeedsDisplayInRect:(CGRect)aRect;
如何利用drawRect呢?呼叫核心圖形框架,它是C的介面,不是面向物件的。
Core Graphics framework的基本概念是,你建立一個環境,然後建立一些軌跡,比如直線和弧線,再設定他們都字型顏色樣式等並描邊或填充到軌跡裡。這就是繪圖的過程。
繪製圖片和文字是主要的,文字和軌跡是一回事,它有很多精細的弧線組成。
繪製圖片是賦值二進位制碼。
context(環境) ,決定了你要在哪繪製。
每次drawRect是的環境都是不一樣的,所以不要快取context。
獲取環境的程式碼:
- CGContextRef context = UIGraphicsGetCurrentContext();
幾乎所有的drawRect都把這個放在第一行。
- CGContextBeginPath(context);
- CGContextMoveToPoint(context, 75, 10);
- CGContextAddLineToPoint(context, 160, 150);
- CGContextAddLineToPoint(context, 10, 150);
- [[UIColor greenColor] setFill];
- [[UIColor redColor] setStroke];
- CGContextDrawPath(context,kCGPathFillStroke); //kCGPathFillStroke is a constant
呼叫 CGContextDrawpath在螢幕上畫出來。
可以定義一個軌跡儲存,在其他環境重用。
透明:
- @property CGFloat alpha
- @property BOOL opaque
- @property (nonatomic) BOOL hidden;
畫文字
用UILabel 用UIFont設定字型 大小- UIFont *myFont = [UIFont systemFontOfSize:12.0];
- UIFont *theFont = [UIFont fontWithName:@“Helvetica” size:36.0];
- NSArray *availableFonts = [UIFont familyNames];
- NSString *text = ...;
- [text drawAtPoint:(CGPoint)p withFont:theFont]; // NSString instance method
畫影象
UIImageView 通過下面的方式後去影象: xcode- UIImage *image = [UIImage imageNamed:@“foo.jpg”];
- UIImage *image = [[UIImage alloc] initWithContentsOfFile:(NSString *)fullPath];
- UIImage *image = [[UIImage alloc] initWithData:(NSData *)imageData];
- UIGraphicsBeginImageContext(CGSize);
- // draw with CGContext functions
- UIImage *myImage = UIGraphicsGetImageFromCurrentContext();
- UIGraphicsEndImageContext();
- [image drawAtPoint:(CGPoint)p];
- [image drawInRect:(CGRect)r];
- [image drawAsPatternInRect:(CGRect)patRect;
原文地址:http://blog.csdn.net/totogo2010/article/details/8220943