UIViewController與UIView的關系


haoxue 2010-11-21 21:30

iphone--UIViewController與UIView的關系

UIView翻轉效果實現
新建一個view-based模板工程,在ViewController文件中添加下面的代碼,即可實現翻轉效果;
- (void)viewDidLoad {
     [super viewDidLoad];
//需要翻轉的視圖
UIView *parentView = [[UIView alloc] initWithFrame:CGRectMake(0, 150, 320, 200)];
parentView.backgroundColor = [UIColor yellowColor];
parentView.tag = 1000;
[self.view addSubview:parentView];
}
//需要在h頭文件聲明下面的動作響應函數
//在xib文件中添加一個button,其響應函數為下面的函數
//運行程序后,點擊button就看到翻轉效果
-(IBAction)ActionFanzhuan{
//獲取當前畫圖的設備上下文
CGContextRef context = UIGraphicsGetCurrentContext();
//開始准備動畫
[UIView beginAnimati*****:nil context:context];
//設置動畫曲線,翻譯不准,見蘋果官方文檔 
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
//設置動畫持續時間
[UIView setAnimationDuration:1.0];
//因為沒給viewController類添加成員變量,所以用下面方法得到viewDidLoad添加的子視圖
UIView *parentView = [self.view viewWithTag:1000];
//設置動畫效果
[UIView setAnimationTransition: UIViewAnimationTransitionCurlDown forView:parentView cache:YES];  //從上向下
// [UIView setAnimationTransition: UIViewAnimationTransitionCurlUp forView:parentView cache:YES];   //從下向上
// [UIView setAnimationTransition: UIViewAnimationTransitionFlipFromLeft forView:parentView cache:YES];  //從左向右
// [UIView setAnimationTransition: UIViewAnimationTransitionFlipFromRight forView:parentView cache:YES];//從右向左
//設置動畫委托
[UIView setAnimationDelegate:self];
//當動畫執行結束,執行animationFinished方法
[UIView setAnimationDidStopSelector:@selector(animationFinished:)];
//提交動畫
[UIView commitAnimati*****];
}
//動畫效果執行完畢
- (void) animationFinished: (id) sender{
NSLog(@"animationFinished !");
}
運行程序,點擊按鈕,就能看到動畫效果了。

                                     

 

haoxue 2010-11-21 21:33
UIView的一些基本方法理解:loadView、viewDidLoad、viewDidUnload、viewWillAppear、viewWillDisappear

經常使用UIView以及它的子類,一般對於init:,viewDidLoad:,dealloc:等方法應該是比較熟悉和了解的。
對於其它幾個基本方法就不那么常用了,為了更好地編程使用這些方法,在此集中收集整理一下各方法調用的時機和作用:

init:方法
在init方法中實例化必要的對象(遵從LazyLoad思想)
init方法中初始化ViewController本身



loadView:方法
這是當沒有正在使用nib視圖頁面,子類將會創建自己的自定義視圖層。絕不能直接調用
如果手工維護views,必須重載重寫該方法。
當view需要被展示而它卻是nil時,viewController會調用該方法。
loadView和IB構建view
你在控制器中實現了loadView方法,那么你可能會在應用運行的某個時候被內存管理控制調用。 如果設備內存不足的時候, view 控制器會收到didReceiveMemoryWarning的消息。 默認的實現是檢查當前控制器的view是否在使用。 如果它的view不在當前正在使用的view hierarchy里面,且你的控制器實現了loadView方法,那么這個view將被release, loadView方法將被再次調用來創建一個新的view。

viewDidLoad:方法
在視圖加載后被調用:
如果是在代碼中創建的視圖加載器,他將會在loadView方法后被調用;
如果是從nib視圖頁面輸出,他將會在視圖設置好后后被調用。
重載重寫該方法以進一步定制view
在iPhone OS 3.0及之后的版本中,還應該重載重寫viewDidUnload來釋放對view的任何索引
viewDidLoad后調用數據Model


viewDidUnload:方法
當系統內存吃緊的時候會調用該方法(注:viewController沒有被dealloc)
內存吃緊時,在iPhone OS 3.0之前didReceiveMemoryWarning是釋放無用內存的唯一方式,但是OS 3.0及以后viewDidUnload方法是更好的方式
在該方法中將所有IBOutlet(無論是property還是實例變量)置為nil(系統release view時已經將其release掉了)
在該方法中釋放其他與view有關的對象、其他在運行時創建(但非系統必須)的對象、在viewDidLoad中被創建的對象、緩存數據等 release對象后,將對象置為nil(IBOutlet只需要將其置為nil,系統release view時已經將其release掉了)
一般認為viewDidUnload是viewDidLoad的鏡像,因為當view被重新請求時,viewDidLoad還會重新被執行
viewDidUnload中被release的對象必須是很容易被重新創建的對象(比如在viewDidLoad或其他方法中創建的對象),不要release用戶數據或其他很難被重新創建的對象


dealloc:方法
viewDidUnload和dealloc方法沒有關聯,dealloc還是繼續做它該做的事情


viewWillAppear: 方法
Called when the view is about to made visible. Default does nothing
視圖即將可見時調用。默認情況下不執行任何操作


viewDidAppear: 
Called when the view has been fully transitioned onto the screen. Default does nothing
視圖已完全過渡到屏幕上時調用


viewWillDisappear:
Called when the view is dismissed, covered or otherwise hidden. Default does nothing
視圖被駁回時調用,覆蓋或以其他方式隱藏。默認情況下不執行任何操作


viewDidDisappear:
Called after the view was dismissed, covered or otherwise hidden. Default does nothing
視圖被駁回后調用,覆蓋或以其他方式隱藏。默認情況下不執行任何操作

 

lorky_luo 2010-11-21 22:08
- (BOOL)CreateFolder
{
    NSFileManager *fileManager = [NSFileManager defaultManager];
    //Get Documents folder
    NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentDir = [documentPaths objectAtIndex:0];
    //Get Video & Image folder path
    NSString *videoDoc = [NSString stringWithFormat:@"%@/Video",documentDir];
    NSString *imageDoc = [NSString stringWithFormat:@"%@/Image",documentDir];
    
    //Create Video & Image folder at right path
    if ([fileManager fileExistsAtPath:videoDoc]!=YES) {
        [fileManager createDirectoryAtPath:videoDoc withIntermediateDirectories:YES attributes:nil error:nil];
    }
    if ([fileManager fileExistsAtPath:imageDoc]!=YES) {
        [fileManager createDirectoryAtPath:imageDoc withIntermediateDirectories:YES attributes:nil error:nil];
    }
    
    // same as above for other six folders.
    return YES;
}

 

haoxue 2010-11-21 23:24
iphone--UIViewController與UIView的關系
UIViewController和Uiview是兩個不同的類
UIViewController是視圖控制器 
而UIView是視圖
也就是說,UIViewController是控制UIView的。 
你也可以認為UIViewController就是一個相框 
而UIView就是一個相片
相框可以隨時隨地的拿走這個相片而換另外一張相片
或者在這張相片上加一個新的相片。而相片
卻不能操縱相框的。 


UIView工作在第一線,向用戶展示表現的內容,並接受用戶的交互。UIViewController相當於導演,按照計划編排屬下的UIView以何種形式展現,其中包含一些花哨的技巧,如翻轉、淡入淡出等。 
UIVewController的另一個功能是處理用戶交互操作,注意這里我說的是"處理",當然UIViewController本身是不知道用戶交互的,這就需要UIView將用戶的交互操作(例如:touchesBegintouchesMoved)傳遞上來。一般常用的兩種方法完成這種傳遞: 

1、[self nextResponder] touchesBegin:touches... 

2、使用Notification 


不管以何種方式,如果UIViewController得到了用戶的輸入,那么它應該對UIView做些改變以響應用戶的輸入,這里要注意UIViewController應該只改變UIView的表現,而不應該處理其它事情,
更多的操作通過Delegate來進行,關於Delegate的應用場合下次講解消息的傳遞方式中一起闡述。


UIView是一個視圖,UIViewController是一個控制器,每一個viewController管理着一個view


 

haoxue 2010-11-21 23:28
關於UIView的userInteractionEnabled屬性
如果父視圖為ParentView包含一個Button,如果再ParentView上添加子視圖ChildView,且ChildView蓋住了Button,那么Button就得到不響應了,
為了讓Button響應,可以設置ChildView的userInteractionEnabled = NO;最近被這個問題困擾了很久,開始想用事件傳遞的方法,重寫類繼承自UIView,最后被這簡單屬性搞定了....

 

haoxue 2011-10-11 17:27
UIView與CALayer的區別?
1.UIView是iOS系統中界面元素的基礎,所有的界面元素都繼承自它。它本身完全是由CoreAnimation來實現的(Mac下似乎不是這樣)。它真正的繪圖部分,是由一個叫CALayer(Core Animation Layer)的類來管理。UIView本身,更像是一個CALayer的管理器,訪問它的跟繪圖和跟坐標有關的屬性,例如frame,bounds等等,實際上內部都是在訪問它所包含的CALayer的相關屬性。

2.UIView有個layer屬性,可以返回它的主CALayer實例,UIView有一個layerClass方法,返回主layer所使用的類,UIView的子類,可以通過重載這個方法,來讓UIView使用不同的CALayer來顯示,例如通過
1
- (class) layerClass {
2
  return ([CAEAGLLayer class]);
3
}
使某個UIView的子類使用GL來進行繪制。

3.UIView的CALayer類似UIView的子View樹形結構,也可以向它的layer上添加子layer,來完成某些特殊的表示。例如下面的代碼
1
grayCover = [[CALayer alloc] init];
2
grayCover.backgroundColor = [[[UIColor blackColor] colorWithAlphaComponent:0.2] CGColor];
3
[self.layer addSubLayer: grayCover];
會在目標View上敷上一層黑色的透明薄膜。

4.UIView的layer樹形在系統內部,被系統維護着三份copy(這段理解有點吃不准)。
第一份,邏輯樹,就是代碼里可以操縱的,例如更改layer的屬性等等就在這一份。
第二份,動畫樹,這是一個中間層,系統正在這一層上更改屬性,進行各種渲染操作。
第三份,顯示樹,這棵樹的內容是當前正被顯示在屏幕上的內容。
這三棵樹的邏輯結構都是一樣的,區別只有各自的屬性。

5.動畫的運作
UIView的主layer以外(我覺得是這樣),對它的subLayer,也就是子layer的屬性進行更改,系統將自動進行動畫生成,動畫持續時間有個缺省時間,個人感覺大概是0.5秒。在動畫時間里,系統自動判定哪些屬性更改了,自動對更改的屬性進行動畫插值,生成中間幀然后連續顯示產生動畫效果。

6.坐標系系統(對position和anchorPoint的關系還是犯暈)
CALayer的坐標系系統和UIView有點不一樣,它多了一個叫anchorPoint的屬性,它使用CGPoint結構,但是值域是0~1,也就是按照比例來設置。這個點是各種圖形變換的坐標原點,同時會更改layer的position的位置,它的缺省值是{0.5, 0.5},也就是在layer的中央。
某layer.anchorPoint = CGPointMake(0.f, 0.f);
如果這么設置,layer的左上角就會被挪到原來的中間的位置,
加上這樣一句就好了
某layer.position = CGPointMake(0.f, 0.f);

7.真實例子的分析

   
這是iphone上iBook翻頁的效果,假設每一頁都是一個UIView,我覺得一個頁面是貼了倆個Layer,文字Layer顯示正面的內容,背面layer用文字layer的快照做affine翻轉,貼在文字layer的后面。因為Layer可以設置顯示陰影,也許后面的陰影效果沒有使用單獨的一個layer來顯示。至於這個曲面效果,我查了很多資料也沒有結果,估計是使用了GL的曲面繪圖?

8.最后一個
layer可以設置圓角顯示,例如UIButton的效果,也可以設置陰影顯示,但是如果layer樹中的某個layer設置了圓角,樹中所有layer的陰影效果都將顯示不了了。如果既想有圓角又想要陰影,好像只能做兩個重疊的UIView,一個的layer顯示圓角,一個的layer顯示陰影.....
 



 

haoxue 2011-10-11 17:37
什么是CALayer? 
CALayer(這里簡單地稱其為層)。 
首先要說的是CALayers 是屏幕上的一個具有可見內容的矩形區域,每個UIView都有一個根CALayer, 
其所有的繪制(視覺效果)都是在這個layer上進行的。 
UILabel* lable = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 100, 30)]; 
lable.text = @"test"; 
[self.view addSubview: lable]; 
lable.backgroundColor = [UIColor clearColor]; 
[lable release]; 
// 設定CALayer 
self.view.layer.backgroundColor =[UIColor orangeColor].CGColor; 
self.view.layer.cornerRadius =20.0; 
self.view.layer.frame = CGRectInset(self.view.layer.frame, 20, 20); 
請注意,我創建的UILable始終隨着UIView的根CALayer的縮放而改變位置。) 
其次,CALayer的可以影響其外觀的特性有: 
      層的大小尺寸背景色內容(比如圖像或是使用
Core Graphics
    繪制的內容)是否使用圓角是否使用陰影等等
需要說明的是CALayer的大部分屬性都可以用來實現動畫效果。 
另外,你可以直接使用CALayer,也可以使用其子類,如CAGradientLayer,CATextLayer, CAShapeLayer等等。 
示例 
首先在Xcode中創建一個View-based App,CALayer是屬於QuartzCore framework的,所以需要引入QuartzCore framework,另外在程序中包括QuartzCore.h。 
第一個例子是創建一個帶圓角的層,在你的ViewController中的ViewDidLoad中加入下面代碼: 
// Import QuartzCore.h at the top of the file 
#import <QuartzCore/QuartzCore.h> 

// Uncomment viewDidLoad and add the following lines 
self.view.layer.backgroundColor =[UIColor orangeColor].CGColor; 
self.view.layer.cornerRadius =20.0; 
self.view.layer.frame = CGRectInset(self.view.layer.frame, 20, 20); 


然后添加一個帶陰影效果的子層,加入下列代碼: 
CALayer *sublayer = [CALayer layer]; 
sublayer.backgroundColor = [UIColor blueColor].CGColor; 
sublayer.shadowOffset = CGSizeMake(0, 3); 
sublayer.shadowRadius = 5.0; 
sublayer.shadowColor = [UIColor blackColor].CGColor; 
sublayer.shadowOpacity = 0.8; 
sublayer.frame = CGRectMake(30, 30, 128, 192); 
[self.view.layer addSublayer:sublayer]; 



為子層增加內容(圖片),你還可以設置層的邊框,代碼如下: 
sublayer.contents =(id)[UIImage imageNamed:@"BattleMapSplashScreen.png"].CGImage; 
sublayer.borderColor =[UIColor blackColor].CGColor; 
sublayer.borderWidth =2.0; 


如果你希望子層也是圓角怎么辦?你可能說很容易設置cornerRadius屬性就行。實際上你即算是設置了cornerRadius屬性,圖片仍然不會顯示圓角。你還需要設置masksToBounds為YES。但是這樣做還是不夠的,因為如果是這樣,這個層的陰影顯示就沒有了。簡單的實現方法如下(通過兩個層來實現): 
CALayer *sublayer =[CALayer layer]; 
sublayer.backgroundColor =[UIColor blueColor].CGColor; 
sublayer.shadowOffset = CGSizeMake(0, 3); 
sublayer.shadowRadius =5.0; 
sublayer.shadowColor =[UIColor blackColor].CGColor; 
sublayer.shadowOpacity =0.8; 
sublayer.frame = CGRectMake(30, 30, 128, 192); 
sublayer.borderColor =[UIColor blackColor].CGColor; 
sublayer.borderWidth =2.0; 
sublayer.cornerRadius =10.0; 
[self.view.layer addSublayer:sublayer]; 

CALayer *imageLayer =[CALayer layer]; 
imageLayer.frame = sublayer.bounds; 
imageLayer.cornerRadius =10.0; 
imageLayer.contents =(id)[UIImage imageNamed:@"BattleMapSplashScreen.png"].CGImage; 
imageLayer.masksToBounds =YES; 
[sublayer addSublayer:imageLayer]; 


最后,還介紹一下自繪圖型的實現,其要點是要設置所繪制層的delegate。比如在我們的例子中使用ViewController作為delegate,那么就需要在ViewController中實現drawLayer:inContext方法,對層進行繪制工作。另外,還需要調用setNeedsDisplay,來通知層需要進行繪制了,於是層才會通過對delegate的drawLayer:inContext方法進行調用。 
代碼如下: 
void MyDrawColoredPattern (void*info, CGContextRef context){ 
  
    CGColorRef dotColor =[UIColor colorWithHue:0 saturation:0 brightness:0.07 alpha:1.0].CGColor; 
    CGColorRef shadowColor =[UIColor colorWithRed:1 green:1 blue:1 alpha:0.1].CGColor; 
  
    CGContextSetFillColorWithColor(context, dotColor); 
    CGContextSetShadowWithColor(context, CGSizeMake(0, 1), 1, shadowColor); 
  
    CGContextAddArc(context, 3, 3, 4, 0, radians(360), 0); 
    CGContextFillPath(context); 
  
    CGContextAddArc(context, 16, 16, 4, 0, radians(360), 0); 
    CGContextFillPath(context); 
  


-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context { 
  
    CGColorRef bgColor =[UIColor colorWithHue:0.6 saturation:1.0 brightness:1.0 alpha:1.0].CGColor; 
    CGContextSetFillColorWithColor(context, bgColor); 
    CGContextFillRect(context, layer.bounds); 
  
    staticc*****t CGPatternCallbacks callbacks ={0, &MyDrawColoredPattern, NULL}; 
  
    CGContextSaveGState(context); 
    CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL); 
    CGContextSetFillColorSpace(context, patternSpace); 

還需要注意,radians是一個自定義函數: 
static inline double radians (double degrees) { return degrees * M_PI/180; } 
效果如下: 






 

haoxue 2011-10-11 18:55
CALayer 這個類么,和UIView有什么區別和聯系?Layer到底是個什么東西?
答:就是層啊,這個層你隨便控制他的大小,旋轉,角度,坐標變化或者內容之類的信息,這些變化還可以通過動畫表現出來。
UIView所有你能看到的顯示的內容,后面都有一個Layer。
UIView 的animation我覺得是一種簡化,實質還是調用的CALayer

Core Animation繪圖的基礎是“層”,叫做CALayer。你可以在View中設置層,層中可以放置更多的層。

每個層都可以設定單獨的動作,還可以給上一級的層設置動作,下一級的層就可以跟着上一層進行動作。

CALayer是為更好實現View的動畫,比如你想View消失時做成玻璃破碎的效果,
就可以在View的CALayer上密密麻麻排一層N個小的子CALayer,設置每個CALayer的落下動畫,用View就比較不合適。

一個UIView包含CALayer樹,CALayer是一個數據模型,包含了一些用於顯示的對象,但本身不用於顯示。






 

haoxue 2011-10-11 23:33
UIView的基礎知識
在iphone里你看到的,摸到的,都是UIView,所以UIView在iphone開發里具有非常重要的作用。 視圖和窗口展示了應用的用戶界面,同時負責界面的交互。UIKit和其他系統框架提供了很多視圖,你可以就地使用而幾乎不需要修改。當你需要展示的內容與標准視圖允許的有很大的差別時,你也可以定義自己的視圖。
不管你是使用系統的視圖還是創建自己的視圖,你需要理解UIView和UIWindow類所提供的基本結構。這些類提供了復雜的方法來管理視圖的布局和展示。理解這些方法的工作非常重要,使你在應用發生改變時可以確認視圖有合適的行為。
 視圖架構 
大部分你想要可視化操作都是由視圖對象-即UIView類的實例-來進行的。一個視圖對象定義了一個屏幕上的一個矩形區域,同時處理該區域的繪制和觸屏事件。一個視圖也可以作為其他視圖的父視圖,同時決定着這些子視圖的位置和大小。UIView類做了大量的工作去管理這些內部視圖的關系,但是需要的時候你也可以定制默認的行為。
視圖與層聯合起來處理着視圖內容的解釋和動畫過渡。每個UIKit框架里的視圖都被一個層對象支持通常是一個CALayer類的實例),它管理管理着后台的視圖存儲和處理視圖相關的動畫。然而,當你需要對視圖的解釋和動畫行為有更多的控制權時,你可以使用層。
為了理解視圖和層之間的關系,我們可以借助於一些例子。應用中的視圖包括了一個window(同時也是一個視圖),一個通用的表現得像一個容器視圖的UIView對象,一個圖像視圖,一個控制顯示用的工具條,和一個工具條按鈕(它本身不是一個視圖但是在內部管理着一個視圖)。(注意這個應用包含了一個額外的圖像視圖,它是用來實現動畫的)。為了簡化,同時因為這個視圖通常是被隱藏的,所以沒把它包含在下面的圖中。每個視圖都有一個相應的層對象,它可以通過視圖礶r屬性被訪問。(因為工具條按鈕不是一個視圖,你不能直接訪問它的層對象。)

 

xiaobaobao 2011-10-12 00:48
這個好東西,mark!!!

 

haoxue 2011-10-12 01:19
CALayer和UIView的關系?
一個UIView包含CALayer樹,CALayer是一個數據模型,包含了一些用於顯示的對象,但本身不用於顯示。 
CALayer相當於photoshop的一個層,很多動畫可以通過設置CALayer來實現。據說有人用CALayer顯示圖片來播放視頻。
Core animation應該是用CAlayer來實現各種動畫。

 

snowren 2011-10-12 10:01
    

 

haoxue 2011-10-15 01:52
CALayer簡單教程

首先要說的是CALayers 是屏幕上的一個具有可見內容的矩形區域,每個UIView都有一個根CALayer,其所有的繪制(視覺效果)都是在這個layer上進行的。(譯者注:為驗證這點,我寫下了如下代碼:

1
2
3
4
5
6
7
8
9
10
 
UILabel* lable = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 100, 30)];
lable.text =  @"test";
[self.view addSubview: lable];
lable.backgroundColor = [UIColor clearColor];
[lable release];

// 設定CALayer
self.view.layer.backgroundColor =[UIColor orangeColor].CGColor;
self.view.layer.cornerRadius =20.0;
self.view.layer.frame = CGRectInset(self.view.layer.frame, 20, 20);
請注意,我創建的UILable始終隨着UIView的根CALayer的縮放而改變位置。)
其次,CALayer的可以影響其外觀的特性有:層的大小尺寸背景色內容(比如圖像或是使用Core Graphics繪制的內容)是否使用圓角是否使用陰影等等
需要說明的是CALayer的大部分屬性都可以用來實現動畫效果。
另外,你可以直接使用CALayer,也可以使用其子類,如CAGradientLayer,CATextLayer, CAShapeLayer等等。
示例
首先在Xcode中創建一個View-based App,CALayer是屬於QuartzCore framework的,所以需要引入QuartzCore framework,另外在程序中包括QuartzCore.h。
第一個例子是創建一個帶圓角的層,在你的ViewController中的ViewDidLoad中加入下面代碼:

1
2
3
4
5
6
7
 
// Import QuartzCore.h at the top of the file
#import <QuartzCore/QuartzCore.h>

// Uncomment viewDidLoad and add the following lines
self.view.layer.backgroundColor =[UIColor orangeColor].CGColor;
self.view.layer.cornerRadius = 20.0;
self.view.layer.frame = CGRectInset(self.view.layer.frame, 20, 20);
結果如下:
然后添加一個帶陰影效果的子層,加入下列代碼:



1
2
3
4
5
6
7
8
 
CALayer *sublayer = [CALayer layer];
sublayer.backgroundColor = [UIColor blueColor].CGColor;
sublayer.shadowOffset = CGSizeMake(0, 3);
sublayer.shadowRadius = 5.0;
sublayer.shadowColor = [UIColor blackColor].CGColor;
sublayer.shadowOpacity = 0.8;
sublayer.frame = CGRectMake(30, 30, 128, 192);
[self.view.layer addSublayer:sublayer];
效果圖:
為子層增加內容(圖片),你還可以設置層的邊框,代碼如下:

1
2
3
 
sublayer.contents =( id)[UIImage imageNamed: @ "BattleMapSplashScreen.png"].CGImage;
sublayer.borderColor =[UIColor blackColor].CGColor;
sublayer.borderWidth = 2.0;
效果圖:
 

如果你希望子層也是圓角怎么辦?你可能說很容易設置cornerRadius屬性就行。實際上你即算是設置了cornerRadius屬性,圖片仍然不會顯示圓角。你還需要設置masksToBounds為YES。但是這樣做還是不夠的,因為如果是這樣,這個層的陰影顯示就沒有了。簡單的實現方法如下(通過兩個層來實現):
CALayer *sublayer =[CALayer layer];
sublayer.backgroundColor =[UIColor blueColor].CGColor;
sublayer.shadowOffset = CGSizeMake(0, 3);
sublayer.shadowRadius =5.0;
sublayer.shadowColor =[UIColor blackColor].CGColor;
sublayer.shadowOpacity =0.8;
sublayer.frame = CGRectMake(30, 30, 128, 192);
sublayer.borderColor =[UIColor blackColor].CGColor;
sublayer.borderWidth =2.0;
sublayer.cornerRadius =10.0;
[self.view.layer addSublayer:sublayer];

CALayer *imageLayer =[CALayer layer];
imageLayer.frame = sublayer.bounds;
imageLayer.cornerRadius =10.0;
imageLayer.contents =(id)[UIImage imageNamed:@"BattleMapSplashScreen.png"].CGImage;
imageLayer.masksToBounds =YES;
[sublayer addSublayer:imageLayer];
效果圖:
 
最后,還介紹一下自繪圖型的實現,其要點是要設置所繪制層的delegate。比如在我們的例子中使用ViewController作為delegate,那么就需要在ViewController中實現drawLayer:inContext方法,對層進行繪制工作。另外,還需要調用setNeedsDisplay,來通知層需要進行繪制了,於是層才會通過對delegate的drawLayer:inContext方法進行調用。
代碼如下:

void MyDrawColoredPattern (void*info, CGContextRef context){
 
    CGColorRef dotColor =[UIColor colorWithHue:0 saturation:0 brightness:0.07 alpha:1.0].CGColor;
    CGColorRef shadowColor =[UIColor colorWithRed:1 green:1 blue:1 alpha:0.1].CGColor;
 
    CGContextSetFillColorWithColor(context, dotColor);
    CGContextSetShadowWithColor(context, CGSizeMake(0, 1), 1, shadowColor);
 
    CGContextAddArc(context, 3, 3, 4, 0, radians(360), 0);
    CGContextFillPath(context);
 
    CGContextAddArc(context, 16, 16, 4, 0, radians(360), 0);
    CGContextFillPath(context);
 
}

-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context {
 
    CGColorRef bgColor =[UIColor colorWithHue:0.6 saturation:1.0 brightness:1.0 alpha:1.0].CGColor;
    CGContextSetFillColorWithColor(context, bgColor);
    CGContextFillRect(context, layer.bounds);
 
    staticc*****t CGPatternCallbacks callbacks ={0, &MyDrawColoredPattern, NULL};
 
    CGContextSaveGState(context);
    CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
    CGContextSetFillColorSpace(context, patternSpace);
    CGColorSpaceRelease(patternSpace);
 
    CGPatternRef pattern = CGPatternCreate(NULL,
                                           layer.bounds,
                                           CGAffineTransformIdentity,
                                           24,
                                           24,
                                           kCGPatternTilingC*****tantSpacing,
                                           true,
                                           &callbacks);
    CGFloat alpha =1.0;
    CGContextSetFillPattern(context, pattern, &alpha);
    CGPatternRelease(pattern);
    CGContextFillRect(context, layer.bounds);
    CGContextRestoreGState(context);
}
 
還需要注意,radians是一個自定義函數:



1
 
static inline double radians (double degrees) { return degrees * M_PI/180; }
效果如下:



 

u3dtest 2011-10-18 15:46
學習了,受教受教啊

 

leonqgl 2011-10-19 12:06
原來是經驗匯總貼,有價值

 

haoxue 2011-10-20 00:36
作為程序員,要特別注意:要積極參加體育鍛煉,預防糖尿病和頸椎病!(特別重要)

 

haoxue 2011-10-23 11:41
自定義UIViewController與xib文件關系深入分析

用xcode模板向工程加入UIViewController sub class的時候,如果選中了with xib for interface,那么就會向工作加入三個文件(.h .m .xib), 這樣生成的三個文件除后綴名后都是一樣的名字。

現在如果我們需要用這個剛加入的自定義UIVewController,可以如下方式定義:
CustomViewController* customViewController = [[CustomViewController alloc] initWithNibName:nil bundle:nil]; 
你可以看現第一個傳數是nil, 對沒錯,傳nil也是可以的。因為如果系統發現是nil的話,會在工程的bundle里找與CustomViewController同名的xib文件,因為模版生成的正好名字相同,所以能夠正確加載xib文件。
第二種方法:
CustomViewController* customViewController = [[CustomViewController alloc] init]; 
在這兒我們只是簡單的初始化,也能正解加載相應的xib文件,因為他們名字是相同的。
如果xib的名了與類的名字不同呢?
如果不同那么我們就不能用上面的兩種方法,必須顯示指明xib的名字,如:
CustomViewController* customViewController = [[CustomViewController alloc] initWithNibName:"firstView" bundle:nil]

在這兒我們顯示指明是firstView.xib這個文件。
網上有人說,自定義UITableViewController與自定義UIViewController不一樣,即使.h .m .xib文件名一樣(除后綴名),也必須顯示指明xib的名字。 參看:http://www.outofcore.com/2011/07/ios-development-proper-use-of-initwithnibnamebundle-affects-uitableviewcontroller/
我在xcode4 SDK 4.3上測試了,結果是一樣的,也可以不用指明, 我的測試是直接將自定義的controller賦值給windows.rootViewController,如:
testTableView *tableView = [[[testTableView alloc] initWithNibName:nil bundle:nil] autorelease]; 
self.window.rootViewController = tableView;

不知道是否我測試不夠准確,大家可以親自測試一下:)

 

無出吾右 2011-10-23 23:38
東西很不錯,樓主是個認真的人,mark

 

zhenhi 2011-10-24 09:52
樓主的帖子往往是精品

 

tidynine 2011-10-24 10:19
mark,收藏,謝謝

 

ljlwz1986 2011-10-24 14:49
不說啥了,必須mark啊。。

 

cao_ya_dong 2011-10-25 13:48
      咋現在才發現這么好的資料啊。

 

haoxue 2011-10-27 00:07
iphone 程序view的流程

由init、loadView、viewDidLoad、viewDidUnload、dealloc的關系說起
 init方法
  在init方法中實例化必要的對象(遵從LazyLoad思想)
‍  init方法中初始化ViewController本身
 loadView方法
  當view需要被展示而它卻是nil時,viewController會調用該方法。不要直接調用該方法。
  如果手工維護views,必須重載重寫該方法
  如果使用IB維護views,必須不能重載重寫該方法
 loadView和IB構建view
  你在控制器中實現了loadView方法,那么你可能會在應用運行的某個時候被內存管理控制調用。 如果設備內存不足的時候, view 控制器會收到didReceiveMemoryWarning的消息。 默認的實現是檢查當前控制器的view是否在使用。 如果它的view不在當前正在使用的view hierarchy里面,且你的控制器實現了loadView方法,那么這個view將被release, loadView方法將被再次調用來創建一個新的view。
 viewDidLoad方法
  viewDidLoad 此方法只有當view從nib文件初始化的時候才被調用。
  重載重寫該方法以進一步定制view
  在iPhone OS 3.0及之后的版本中,還應該重載重寫viewDidUnload來釋放對view的任何索引
  viewDidLoad后調用數據Model

 viewDidUnload方法‍
  當系統內存吃緊的時候會調用該方法(注:viewController沒有被dealloc)
  內存吃緊時,在iPhone OS 3.0之前didReceiveMemoryWarning是釋放無用內存的唯一方式,但是OS 3.0及以后viewDidUnload方法是更好的方式
  在該方法中將所有IBOutlet(無論是property還是實例變量)置為nil(系統release view時已經將其release掉了)
  在該方法中釋放其他與view有關的對象、其他在運行時創建(但非系統必須)的對象、在viewDidLoad中被創建的對象、緩存數據等  release對象后,將對象置為nil(IBOutlet只需要將其置為nil,系統release view時已經將其release掉了)
  一般認為viewDidUnload是viewDidLoad的鏡像,因為當view被重新請求時,viewDidLoad還會重新被執行
  viewDidUnload中被release的對象必須是很容易被重新創建的對象(比如在viewDidLoad或其他方法中創建的對象),不要release用戶數據或其他很難被重新創建的對象
 dealloc方法
  viewDidUnload和dealloc方法沒有關聯,dealloc還是繼續做它該做的事情。

文章二:
  viewDidUnload
該方法在收到內存警告,同時該視圖並不在當前界面顯示時候會被調用,此時該 controller 的 view 已經被釋放並賦值為 nil。
接下來你要做的是
把實例變量的子視圖釋放(IBOulet 的,以及自己添加的)
其他實例變量,比如之前在 -viewDidLoaded 中實例的數據數組、http 請求釋放掉
    因為當該 viewController 再次被激活准備顯示時(比如 navigationControler 返回到上一級),vc 發現自己的 view 為空后會重復之前的流程直到把 view 給創建起來。若沒將自己額外添加的子視圖,各種類實例變量釋放,這里便會重新再次創建

 

 

romboo 2011-10-28 20:33
好東西,標記

 

haoxue 2011-11-01 00:09
窗口(UIWindow)
視圖(UIView)是應用和用戶的視覺交互的主要場所,它也承擔了接收手勢並且做出響應的任務。
窗口(UIWindow)和網頁視圖(UIWebView)
窗口是視圖的一個子類窗口的主要功能:一是提供一個區域來顯示視圖,二是將事件(event)分發給視圖(請參考本節的小知識來了解iOS中的事件分發機制)。一個應用通常只有一個窗口,但也有例外,比如在一個iPhone應用中加載一個電影播放器,這個應用本身有一個窗口,而電影播放器還有另一個窗口。
小知識:iOS中的事件類型和分發
iOS設備上有很多硬件能夠因用戶的行為而產生數據,包括觸摸屏、加速度傳感器和陀螺儀。當原始數據產生后,系統的一些框架會對這些原始數據進行封裝,並作為事件傳遞給正在運行的應用來進行處理。
當應用收到一個事件后,會先將其放在事件隊列(event queue)當中。應用的singleton從事件隊列中取出一個事件並分發給關鍵窗口(key window)來處理。
如果這個事件是一個觸摸事件的話,那么窗口會將事件按照視圖層次傳遞到最上層(用戶可見)的視圖對象,這個傳遞順序叫做響應鏈(responder chain)向下順序。響應鏈最下層(也是視圖最上層)的視圖對象如果不能處理這個事件,那么響應鏈的上一級的視圖將得到這個事件並嘗試處理這個事件,如果不能處理的話就繼續向上傳遞,直到找到能處理該事件的對象為止。
如果這個事件不是一個觸摸事件,那么事件的分發機制有所不同,在此不做介紹。

 

carya 2011-11-01 09:12
好東西,mark,學習了

 

haoxue 2011-11-02 10:41
Cocoa的MVC架構分析

在Cocoa框架中:
所有的控件、窗口等都繼承自 UIView,對應MVC中的 V。UIView及其子類主要負責UI的實現,而UIView所產生的事件都可以采用委托的方式,交給UIViewController實現。對於不同的UIView,都有相應的UIViewController 對應MVC中的C。比如在iPhone OS上常用的UITableView,它所對應的Controller就是UITableViewController。至於MVC中的M,那需要根據用戶自己的需求來實現了。

下面看一下一個自定義UIView的架構是怎么樣的。這之前要認識一下Objective-C中的幾個重要的關鍵字。
@interface 定義一個類,這個很容易和Java中的interface混淆。
@protocol 定義一個協議,我跟喜歡把它理解成一個接口,相當於Java中的interface。
Objective-C只支持單繼承,但可以實現多個協議(接口),語法如下:

@interface Child : Parent <Protocol1,Protocol2> { //成員變量定義 } //成員方法,類方法,屬性定義 @end  
有了以上的知識后,我們就可以來定義自己的UIView了。
首先是定義一個UIView的子類。

@interface MyUIView : UIView { //定義一些控件 id<MyUIViewDelegate> delegate; //這個定義會在后面的解釋,它是一個協議,用來實現委托。 } //定義一些控件設置方法 @property id<MyUIViewDelegate> delegate; //定義一個屬性,可以用來進行get set操作 @end  
然后定義一個Protocol,按照Cocoa的習慣,一般它以delegate結尾,熟悉C#的同學應該知道它的意義。其實不論是接口,委托,還是回調函數,本質上都做了一件事情。就是定義了一個操作契約,然后由用戶自己來實現它的具體內容。

@protocol MyUIViewDelegate //這里只需要聲明方法 - (void)func1 - (int)func2:(int)arg @end 

完成以上兩步之后就需要設計自己的UIViewController了。一般簡單的做法,可以讓這個Controller來實現上面定義的MyUIViewDelegate。在Cocoa框架中,很多控件和它的Controller都是采用的這種方式。

@interface MyUIViewController : UIViewController <MyUIViewDelegate> { //成員變量 } //成員方法,類方法,屬性 @end 

定義都完成了,到這里其實還看不出這三者是怎么聯系起來的。那接下來就要看看,MyUIView和MyUIViewController的具體實現了。

首先是MyUIView的實現代碼,假設在MyUIView在發生某個事件后會調用doSometing方法。

- (void)doSomething { if( delegate != nil ) //這里的delegate就是UIView定義時候的一個委托對象 { [delegate func1]; //[]表示對一個對象發消息,如果在Java中會寫成delegate.func1() } } 

上面的代碼中 nil 相當於 Java中的 null,這里的意思就很明顯了,如果delegate委托對象不為空,則調用相應的方法,但是這個委托對象的方法在哪里實現呢。可以看一下MyUIViewController的定義,它實現了MyUIViewDelegate。所以這個方法當然是由它來實現。代碼如下

- (id)init { MyUIView *myView = [[MyUIView alloc] init]; //對MyUIView進行初始化 myView.delegate = self; //將MyUIViewController自己的實例作為委托對象 self.view = myView; } - (void)func1 { //具體實現,可以加入Model相關的代碼 } 

這么一來整個,整個代碼的線路就明白了。
1.MyUIViewController初始化
2.MyUIViewController初始化時初始化MyUIView,並且將自己作為委托對象賦值給MyUIView
3.MyUIView發生事件,調用(回調)委托對象的方法,其實就是調用MyUIViewController的方法。

 

haoxue 2011-11-12 11:24
CALayer就是層,這個層你隨便控制他的大小,旋轉,角度,坐標變化或者內容之類的信息,這些變化還可以通過動畫表現出來。UIView所有你能看到的顯示的內容,后面都有一個Layer。下面來自定義添加一個CALayer。
CALayer *layer = [[CALayer alloc]init];//定義一個layer
 
CGRect aa = CGRectMake(10, 30, 240,240);//設置該layer的坐標和大小
 
layer.frame = aa;
 
UIColor *c = [UIColor redColor];
 
[layersetBackgroundColor:(c.CGColor)];//設置該layer的背景,因為layersetBackgroundColor用到的是CGColor所以要進行一次轉換
 
[self.view.layer insertSublayer:layeratIndex:0];//在self view中添加該layer

 

haoxue 2011-11-12 11:25
在使用Xcode編寫程序的時候,在類方法上面option +雙擊就可以跳到Document中的相關說明下面,很方便!

 

haoxue 2011-11-12 13:09
模型 視圖 控制器(MVC)

MVC模式將應用程序中的對象設定為三種角色:模型角色(Model)、視圖角色(View)和控制器角色(Controller)。
模型對象(Model)表示數據。例如,在iPhone自帶的通訊錄應用中,聯系人是模型對象,在一個繪畫應用中,圓形、矩形是模型對象。
視圖對象(View)負責顯示數據,比如UILabel可以顯示文本、UIImageView可以顯示圖片,也會支持用戶對數據的編輯操作,例如UITextField可以支持用戶輸入。
控制器對象(Controller)介於模型和視圖之間。
在我們接下來要創建的項目中,當用戶點擊按鈕后,觸發更新操作,控制器對象將會從文本輸入框中獲取輸入的文字內容,並把文字存放在一個字符串中,然后再把文本顯示框的內容更新成格式化好的內容。

 

jinchishuxue 2011-11-12 13:38
樓主牛逼,頂。

 

winsdom 2011-11-12 13:41
lz高人哪,插個樓

 

wl103301 2011-11-12 15:25
mark  謝謝樓主,講得太好了

 

y500 2011-11-12 17:50
mark...........

 

雨綿綿 2011-11-12 23:43
多謝多謝啊

 

haoxue 2011-11-13 19:59
異步調用
異步調用就是你 喊 你朋友吃飯,你朋友說知道了,待會忙完去找你 ,你就去做別的了。 

同步調用就是你 喊 你朋友吃飯,你朋友在忙,你就一直在那等,等你朋友忙玩了,你們一起去。

 

haoxue 2011-11-14 15:01
iphone開發View-Based Application基本名詞
View: 
這個名詞相信大多數的朋友都知道了,你可以在 View 上面畫畫,可以在上頭放一些控件,甚至可以把一個 View 放到另外一個 View 裏面,所有的 View 都來自於 UIView 這個類,而 UIView 又來自於 UIResponder,如果你看一下 Apple 的文檔,大概就可以知道 UIResponder 主要工作在於處理事件的. View 的外框我們稱為 frame,我們透過這個 frame 來定義 View 的大小位置(例如:[view setFrame:frame]),至於要把一個 View 加到另一個 View 則可以用 [view addSubView:subView] 

Controller: 
在 XCode 產生代碼你會發現有一個繼承自 UIViewController 的類.甚至打開 MainWindow.xib 也可以看到它的蹤影. 也許有同學會以為這個和 MVC 裏面的 "C" 是同一個東東,其實 UIViewController 只是幫你控制 View 的 Layout,例如當你旋轉 iPhone 時,Controller 要幫你處理 View 的位置,另外像 View 與其他控件如 Toolbar 間的位置控制也是他的傑作. 當然Controller 並不是必要的,你也是可以用 View 就來完成同樣的事. 

Delegate: 

Delegate 這個名詞相信大家都常看到吧,這東西有點像是現代孝順兒子的父母一樣,父母親擔任 Delegate(代理)幫兒子寫家庭作業. 所有與用戶的互動都會交給 Delegate 來處理,這樣子好處是可以把畫面與事件的處理分開,通常我們是以 Controller 來擔任 Delegate 的角色. 
好了,看到這邊是不是有點了解又不太了解呢? 是的,我們只解釋了這些名詞,但是一個 iPhone 的程式是怎麼開始動起來的,這時候建議大家先產生一個應用程式看看,並且打開 MainWindow.xib 找到 File's Owner 後看看他的 Delegate 是什麼? 我們尋著線索找下去應該是 XXXAppDelegate,打開後大致上可以看到以下代碼片段: 


- (void)applicationDidFinishLaunching:(UIApplication *)application { 
[window addSubview:viewController.view]; 
[window makeKeyAndVisible]; 



- (void)dealloc { 
[viewController release]; 
[window release]; 
[super dealloc]; 

首先映入眼簾的是 UIApplication 這個類,我們都知道 iPhone 要求同時間只能有一個 Application 執行,因此每個應用程式都會對應到一個 UIApplication,我們可以用 [UIApplication sharedInstance] 來取得所對應的應用程式實例(instance),當你執行你的應用程式後applicationDidFinishLaunching 就會被呼叫到(記得我們上面談到 Delegate 這個可憐的父母吧,事件傳給了他,由 Delegate 來處理事件)接著我們把 view 加到 window(其實他也是個 view),然後讓這個 window 變成可見的. 好了,如果你有興趣,最好能夠把 MainWindow.xib 內的每一個圖標打開來看看(File's Owner,First Responder,XXXController...),然後追蹤一下他們的 delegate,相信你能了解的更多. 


 

haoxue 2011-11-14 15:54
iPhone開發如何從nib文件中載入自定義的UIView呢?


  1. @interface MyView : UIView
  2. @property (nonatomic, retain) IBOutlet MyImage *image;
  3. @end
  4.  
  5. @implementation MyView
  6. @synthesize image;
  7.  
  8. - (id)init
  9. {
  10.    self = [super initWithNibName:@"MyView" bundle:nibBundleOrNil];
  11.    return self;
  12. }
  13. @end
  14. @interface MyImage : UIImageView
  15. @end
  16.  
  17. @implementation MyImage
  18. - (id)init
  19. {
  20.    // This doesn't get called 
  21.    self = [super init];
  22.    if (self) 
  23.    {
  24.       // do somethin
  25.    }
  26.    return self;
  27. }
  28. @end


 

舍得333 2011-11-21 00:49
樓主實在是太好了  支持

 

liliangwor 2011-11-21 09:32
不知道調用CGLayer能否調用GPU。

 

1ovekof 2011-11-21 10:14
感謝樓主,你前還真沒關注過CALayer。

 

hpfdm 2011-11-21 15:01
這么好的帖子,我應該頂,感覺中文的論壇有樓主這樣的人,以后有希望了!!!

 

sd4137838 2011-11-21 18:58
多謝樓主分享

 

goodluckfrank 2011-11-21 20:40
好貼,mark

 

scp306806106 2011-11-22 11:01
又見技術流!
收藏了好多技術貼,都還沒消化呢。

 

qq568997030 2011-11-22 14:27
謝謝樓主了

 

cg101100 2011-11-22 15:07
認真學習一下!!!!

 

haoxue 2011-11-28 09:49
核心動畫編程指南【中文完整翻譯版】


 核心動畫編程指南
原文:Core Animation Programming Guide
鏈接:http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreAnimation_guide/Introduction/Introduction.html


譯者感言:
之前一直在CocoaChina上面潛水,雖然做iOS開發也快2年了,但是總覺得缺少了點什么。以前查看英文API文檔,有些細節總是記不住,每次看完之后也沒什么印象。忽然有一天有人向我抱怨說查看官方英文API文檔太痛苦了,然后我就想如果我把一些常用的官方文檔翻譯為中文的話,或許可以幫助這批需要幫助的人,然后偶就心血來潮,開始了自娛自樂的翻譯過程。這是第一篇翻譯的文檔,耗時兩個禮拜的晚上。。。
本文在翻譯過程中發現很多地方直譯成中文比較晦澀,所以采用了意譯的方式,這不可避免的造成有一些地方可能和原文有一定的出入,所以如果你閱讀的時候發現有任何的錯誤都可以給我發郵件:xyl.layne@gmail.com
最后希望這篇文檔能幫上那些感覺看官方英文文檔困難的人。如果可以我推薦盡量查看英文原文檔,畢竟那是原汁原味,翻譯總無法避免有一定的疏漏。


[url=read.php?tid=84461]http://www.cocoachina.com/bbs/read.php?tid=84461[/url]

 

volcan1987 2011-11-28 13:37
好貼,收藏了

 

 

2006xg 2011-12-01 23:30
有時間看看,mark


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM