`
java-mans
  • 浏览: 11415007 次
文章分类
社区版块
存档分类
最新评论

-- iphone--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方法进行调用。
代码如下:
voidMyDrawColoredPattern(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是一个自定义函数:
staticinlinedoubleradians(doubledegrees){returndegrees*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方法进行调用。
代码如下:

voidMyDrawColoredPattern(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
staticinlinedoubleradians(doubledegrees){returndegrees*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. @implementation MyView
  5. @synthesize image;

  6. - (id)init
  7. {
  8. self = [super initWithNibName:@"MyView" bundle:nibBundleOrNil];
  9. return self;
  10. }
  11. @end
  12. @interface MyImage : UIImageView
  13. @end

  14. @implementation MyImage
  15. - (id)init
  16. {
  17. // This doesn't get called
  18. self = [super init];
  19. if (self)
  20. {
  21. // do somethin
  22. }
  23. return self;
  24. }
  25. @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


查看完整版本: [--iphone--UIViewController与UIView的关系--] [--top--]


Powered byPHPWindv7.5 SP3Code ©2003-2010PHPWind
Gzip disabled

You cancontact us

分享到:
评论

相关推荐

    iphone开发笔记

    UIViewController内建Table View 7 将plist文件中的数据赋给数组 8 UITouch 8 Get the Location of Touches 9 Getting Touch Attributes 9 Touch Phase 9 从Plist里读内容 10 获取Documents目录 10 获取tmp目录 10 ...

    iOS7 Day-by-Day

    iOS7 is probably the most significant change to Apple's mobile operating system since the launch of the iPhone3G. Not only does it completely revamp the UI, but it also introduces loads of really ...

    iOS SDK Programming A Beginners Guide

    7 UIView and UIViewController 8 UITabBar and UITabBarController 9 UINavigationBar and UINavigationController 10 Tables Using UITableView and UITableViewController 11 Activity Progress and Alerting ...

    iPhone开发秘籍

    3.2 使用interface builder为uiview-controller构建视图 66 3.2.1 温度转换器示例 66 3.2.2 直接加载xib文件 73 3.3 导航控制器 73 3.3.1 设置导航控制器 74 3.3.2 推入和弹出视图控制器 74 3.3.3 导航项类 75...

    iPhone开发秘籍.part2.rar

    3.2 使用Interface Builder 为UIView- Controller 构建视图.....66 3.2.1 温度转换器示例.....66 3.2.2 直接加载XIB 文件.....73 3.3 导航控制器.....73 3.3.1 设置导航控制器.....74 3.3.2 推入和弹出视图控制器......

    iPhone开发秘籍.part4.rar

    3.2 使用Interface Builder 为UIView- Controller 构建视图.....66 3.2.1 温度转换器示例.....66 3.2.2 直接加载XIB 文件.....73 3.3 导航控制器.....73 3.3.1 设置导航控制器.....74 3.3.2 推入和弹出视图控制器......

    iPhone开发秘籍.part1.rar

    3.2 使用Interface Builder 为UIView- Controller 构建视图.....66 3.2.1 温度转换器示例.....66 3.2.2 直接加载XIB 文件.....73 3.3 导航控制器.....73 3.3.1 设置导航控制器.....74 3.3.2 推入和弹出视图控制器......

    LitePopover:在 iPhone 的弹出窗口中显示 UIViewControllerUIView

    精简版在 iPhone 的弹出窗口中显示 UIViewController/UIView如何使用有 4 种方法可以显示弹出菜单显示内容并指向 FromView // Pop from this Buttonlet fromBtn = UIButton. buttonWithType (UIButtonType. ...

    IOS自适配利器Masonry使用指南

    关于iOS布局自动iPhone6之后就是AutoLayOut,AutoLayOut固然非常好用,不过有时候我们需要在页面手动进行页面布局,VFL算是一种选择,而且VFL不复杂,理解起来很容易,实际开发中用的特别熟还好,要是第一次看估计要...

    ScrollingContentViewController:一个Swift库,简化了使视图控制器的视图可滚动的过程

    例如,考虑以下适用于iPhone Xs但不适合使用键盘的iPhone SE的注册屏幕: 可以通过将视图嵌套在滚动视图中来处理这种情况。 如Apple的“使用滚动视图”文档所述,您可以在Interface Builder中手动执行此操作,但是...

Global site tag (gtag.js) - Google Analytics