第一部分views 簡介
A view is a unit of your app that knows how to draw itself.// app 的基本單位贩汉,知道怎么繪制自己.
view能夠感覺到用戶點(diǎn)擊它.能夠被點(diǎn)擊的表現(xiàn).
- Chapter 1
討論views的最主要的方面 - 他們的層級(jí)躬厌,可見性惜姐,position剪撬,和自動(dòng)布局(autolayout) - Chapter 2
描述drawing.一個(gè)view知道怎么draw(繪制)它自己.告訴view 杨帽,想要他draw成什么樣子.
From displaying an existingimage to constructing a drawing in code - Chapter 3
解釋layer. The drawing power of a view comes ultimately from its layer.To put it another way, a layer is effectively the aspect of a view thatknows how to draw — with even more power. - Chapter 4
講解Animation. 動(dòng)畫的力量起源于layer. - Chapter 5
講解touches. iOS 基于view 對(duì)于touches的感覺和反應(yīng).
with details on howtouches
are routed to the appropriate view and how you can customize that routing.
第一章
views 簡介
a view 知道怎么繪制自己在一個(gè)矩形區(qū)域中.你的app能夠看見歸結(jié)于views.
view很簡單就能被創(chuàng)建.
view 也是responder(UIView is a subclass of UIResponder).view是服從于用戶交互.such as: taps and swipes.因此漓穿,view基于的是用戶看到的和用戶touches的.
window
view最頂級(jí)的層級(jí)是app的window.是UIWindow的實(shí)例.UIWindow是UIView的一個(gè)子類.你的app應(yīng)該只有一個(gè)主要的window.在啟動(dòng)的時(shí)候,被創(chuàng)建睦尽,不會(huì)被銷毀也不會(huì)被替換.
最底層的bacground器净,也是最基礎(chǔ)的superview.
app最終是由構(gòu)成的.UIApplicationMain
.
- UIApplicationMain 實(shí)例化
UIApplication
并且持有這個(gè)實(shí)例.所以能夠使用UIApplication.shared
去訪問.It retains the app delegate instance and assigns it as the application instance’sdelegate. - UIApplecationMain looks to see whether your app uses a main storyboard, by looking at the
Info.plist
keyMain storyboard file base name
,一般不要去修改main.storyboard. - 如果你的app使用一個(gè)main storyboard.UIApplicationMain實(shí)例化UIWindow并且分配這個(gè)window實(shí)例給app delegate的window屬性.這個(gè)window屬性持有它.
- when a view controller becomes the main window's rootViewController, its main view(its view ) is made the one and only immediate subview of your main window--
the main window’s root view.
all other views in your main window will be subviews of the root view.
thus, the root view is the highest object in the view hierarchy that the user will catch a glimpse of the window.
In generalyou’ll have no reason to change anything else about the window itself. - UIApplicationMain calls the app delegate’s application(_:didFinishLaunching-WithOptions:).
- 你的app的界面不能被看見,除非window包含了它.is made the app's key window.因此当凡,if your app uses a main storyboard, UIApplication-Main calls the window’s instance method
makeKeyAndVisible
.(就調(diào)用了makeKeyAndVisible)
subview and superview
- 如果一個(gè)view 被移除山害,他的子view也就全部被移除
- 一個(gè)view的alpha 為多少,那么他的子view的alpha也為多少.
- 一個(gè)view能夠選擇性的限制他的子views沿量,因此所有在父view的邊界之外的view都不會(huì)被顯示.叫做clipping, 使用view的
clipsToBounds
屬性. - 一個(gè)父view擁有他的子views.在內(nèi)存管理來說浪慌,就像一個(gè)數(shù)組擁有他的所有的元素;他持有他們并且當(dāng)這個(gè)subview被銷毀或者從子views中移除的時(shí)候.
- 一個(gè)view的size被改變朴则,他的subviews會(huì)自動(dòng)改變size.
一個(gè)UIView有一個(gè)superview的屬性和一個(gè)subviews的屬性(一個(gè)UIView objects的數(shù)組权纤,從后到前的排列次序).
isDescendant(of:)
讓你檢測是否一個(gè)view是否是另外的view的subview.
移除自己的子views的正確方法:
<font color=red>(!)</font>
myView.subviews.forEach {$0.removeFromSuperview()}
奇怪的是沒有一個(gè)一次性移除完的方法.
Visibility and Opacity
a view can be made invisible by setting its isHidden
property to true
. hidding a view takes it(and its subviews) out of the visible interface without the overhead of actually removing it from the view hierarchy.
a view can be assigned a background color throught its background Color
property. a color is a UIColor. a view whose background color is nil
(the default) is clear color.
a view's alpha
property. 1.0 means opaqye, 0.0 means transparent. 如果一個(gè)view 是完全透明的,或者接近于透明(< 0.01).是不能被交互的乌妒, 不能被touche.
a view 的 alpha
屬性會(huì)影響他的backgroundColor和他的內(nèi)容汹想。a view 的 alpha
為0.5, 那么它的子類的alpha 也是相應(yīng)的0.5.
(Just to make matters more complicated, colors have an alpha value as well. So, forexample, a view can have an alpha of 1.0 but still have a transparent backgroundbecause its backgroundColor has an alpha less than 1.0.)
Frame Bounds Center
略 因?yàn)榇蠹叶级?/p>
Window Coordinates and Screen Coordinates window的坐標(biāo)和Screen的坐標(biāo)
The device的屏幕沒有frame,但是他有bounds. the main window沒有superview撤蚊,但是他的frame is set with respect to the screen's bounds.
let w = UIWindow(frame: UIScreen.main.bounds)
在iOS9之后可以這樣寫:
let w = UIWindow()
在iOS7 和iOS7之前古掏,screent's 坐標(biāo)是不變的.iOS8 介紹了一個(gè)主要的改變:當(dāng)app旋轉(zhuǎn)去補(bǔ)償device的旋轉(zhuǎn),the screen(and with it, the window) is waht rotates.因此這里有一個(gè)變換.Thus there is a transposition of the size components of the screen’s bounds, and a corresponding transposition of the size components of windows's bounds.
The screen therefore reports its coordinates through 2 different properties; their values are typed as UICoordinateSpace
, a protocal(also adopted by UIView) that provides a bounds
property:
這里有一篇關(guān)于Coordinate的文章:http://www.tuicool.com/articles/EvmEn2B
UIScreen 在 iOS8中也是旋轉(zhuǎn)的.
有幾點(diǎn)改變:
[UIScreen bounds] -> interface-oriented
[UIScreen applicationFrame] -> interface-oriented
status bar frame notifications -> interface-oriented
-
keyboard frame notificaitons -> interface-oriented ()
在iOS8中蘋果認(rèn)為設(shè)備的旋轉(zhuǎn)就是當(dāng)前Screen的Bounds噶生了變化.因此引入了Size Class的概念.蘋果使用UITraitCollection來描述不同的Size Class的信息.當(dāng)UITraitColelction發(fā)生了改變(設(shè)備發(fā)生了旋轉(zhuǎn))- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection
就會(huì)被調(diào)用.首先被處罰的是UIScreen
侦啸,然后逐級(jí)向下傳遞:UIScreen -> UIWindow -> UIViewController -> ChildViewControllers -> View -> Subviews
UICoordinateSpace protocol
iOS 8之前槽唾,window和screen的坐標(biāo)是不變的。它們不會(huì)進(jìn)行旋轉(zhuǎn)光涂,而是一直處于豎屏?xí)r的坐標(biāo)體系庞萍。我們是在View Controller旋轉(zhuǎn)方法中做對(duì)應(yīng)的處理。
iOS8之后忘闻,像上文描述的那樣钝计,window和screen的坐標(biāo)會(huì)隨著app旋轉(zhuǎn)而改變。 也不總是這樣的情況齐佳,因?yàn)閂iew Controller仍然決定了App在當(dāng)前視圖下支持哪幾個(gè)方向葵蒂。 在某些時(shí)候,我們需要一些修正之后的frame(比如需要存儲(chǔ)touch事件在屏幕上的坐標(biāo))重虑,這個(gè)時(shí)候新的 UICoordinateSpace 就登場了践付。
在iOS 8上UIScreen提供了兩個(gè)新的屬性:
@property (readonly) id <UICoordinateSpace> coordinateSpace NS_AVAILABLE_IOS(8_0);
@property (readonly) id <UICoordinateSpace> fixedCoordinateSpace NS_AVAILABLE_IOS(8_0);
(?) 1. UIScreen's coordinateSpace property
this coordinate space rorates.
(?) 2.UIScreen's fixedCoordinateSpace property
this coordinate space is invariant.(不變的)
(?)
To help you convert between coordinate space.UICoordinateSpace
提供了2個(gè)方法:
- convert(_:from:)
- convert(_:to:)
第一個(gè)參數(shù)不是CGPoint就是CGRect.第二個(gè)參數(shù)是UICoordinateSpace
, 可能是一個(gè)UIView或者是UIScreen.
So,for example, suppose we have a UIView v in our interface, and we wish to learn its position in fixed device coordinates. we could do it like this:
let screen = UIScreen.main.fixedCoordinateSpace
let r = v.superview!.convert(v.frame, to: screen)
Transform
一個(gè)view的transform
屬性改變這個(gè)這個(gè)view怎么繪制(drawn).
它可以在不影響bounds和center的情況下改變view的表面的size和方向.
一個(gè)transformed
的button還是可以正常使用缺厉,可以被點(diǎn)擊在他的transformed的情況下.
transform 的值是CGAffineTransform
永高,CGAffineTransform
是一個(gè)struct.
CGAffineTransform簡介:
transform一般稱之為形變屬性隧土,其本質(zhì)是通過矩形變化改變控件的大小,位置命爬,角度等.
self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, M_PI_4); // 旋轉(zhuǎn)
self.imageView.transform = CGAffineTransformScale(self.imageView.transform, 0.9, 0.9); // 縮放
_imageView.transform = CGAffineTransformTranslate(self.imageView.transform, 0, 10); // 移動(dòng)
上面這三個(gè)方法是在transform的基礎(chǔ)上進(jìn)行改變的.
CGAffineTransformMakeRotation(旋轉(zhuǎn))曹傀、CGAffineTransformMakeScale(縮放)、CGAffineTransformMakeTranslation(移動(dòng))饲宛;
這三個(gè)方法是直接設(shè)置的.
/* transfrom */
let v1 = UIView.init(frame:CGRect(113, 111, 132, 194))
v1.backgroundColor = UIColor(red: 1, green: 0.4, blue: 1, alpha: 1)
let v2 = UIView(frame:v1.bounds.insetBy(dx: 10, dy: 10)) // 可以insetBy來設(shè)置相對(duì)的frame
v2.backgroundColor = UIColor(red: 0.5, green: 1, blue: 0, alpha: 1)
self.view.addSubview(v1)
v1.addSubview(v2)
v1.transform = CGAffineTransform(rotationAngle:45 * .pi/180) // 旋轉(zhuǎn)45°
print(v1.frame) // 可以注意就是transform的旋轉(zhuǎn)皆愉,它的frame 改變了:(63.7415946665928, 92.7415946665928, 230.516810666815, 230.516810666815)
//注意: 這個(gè)旋轉(zhuǎn),
- center并沒有改變
- view的bounds也沒有改變
- 內(nèi)部的坐標(biāo)系統(tǒng)也沒有改變艇抠,所以它的子view還是相對(duì)于它位置沒有變的.
所以如果view的transform不是它的identity transform(初始的時(shí)候的transform幕庐,沒有任何改變過的)的時(shí)候,你不能設(shè)置它的frame.
以后旋轉(zhuǎn)多少度可以這樣寫:
45 * .pi/180 // 45°
Trait Collections and Size Classes
traitCollection
UITraitEnvironment protocol
參考王巍的博客:https://onevcat.com/2014/07/ios-ui-unique/
iOS8強(qiáng)調(diào)多次的主題就是大統(tǒng)一家淤,包括界面的大統(tǒng)一.
iOS 8 SDK 最重要的關(guān)鍵字就是自適應(yīng).iOS8著重解決的就是apple設(shè)備開始碎片化的這個(gè)問題异剥,6 , 6plus等等.
Size Classes
iOS8在界面設(shè)計(jì)迎來一個(gè)革命性的變化-Size Classes.
iOS6引入了AutoLayout,來幫助開發(fā)者使用約束進(jìn)行布局絮重,這樣使得在某些情況下我們不在需要考慮尺寸.而可以使用約束來規(guī)定位置.
(!)
注意:Universal指的是iphone 和ipad 通用.
AutoLayout只是一個(gè)更具約束來進(jìn)行布局的方案. 而在對(duì)應(yīng)不同設(shè)備的具體情況下的體驗(yàn)上還有欠缺冤寿。一個(gè)最明顯的問題是它不能根據(jù)設(shè)備類型來確定不同的交互體驗(yàn)。很多時(shí)候你還是需要判斷設(shè)備到底是 iPhone 還是 iPad青伤,以及現(xiàn)在的設(shè)備方向究竟是豎直還是水平來做出判斷督怜。這樣的話我們還是難以徹底擺脫對(duì)于設(shè)備的判斷和依賴,而之后如果有新的尺寸和設(shè)備出現(xiàn)的話狠角,這種依賴關(guān)系顯然顯得十分脆弱的(想想要是有 iWatch 的話..) -- 摘抄自王巍博客.
所以在 iOS 8 里亮蛔,Apple 從最初的設(shè)計(jì)哲學(xué)上將原來的方式推翻了,并引入了一整套新的理念擎厢,來適應(yīng)設(shè)備不斷的發(fā)展。這就是 Size Classes
辣吃。
不再根據(jù)設(shè)備屏幕的具體尺寸來進(jìn)行區(qū)分,而是通過它們的感官表現(xiàn)动遭,將其分為普通 (Regular) 和緊密 (Compact) 兩個(gè)種類 (class)。開發(fā)者便可以無視具體的尺寸神得,而是對(duì)這這兩類和它們的組合進(jìn)行適配厘惦。這樣不論在設(shè)計(jì)時(shí)還是代碼上,我們都可以不再受限于具體的尺寸哩簿,而是變成遵循尺寸的視覺感官來進(jìn)行適配宵蕉。
簡單來說,現(xiàn)在的 iPad 不論橫屏還是豎屏节榜,兩個(gè)方向均是 Regular 的;
而對(duì)于 iPhone羡玛,豎屏?xí)r豎直方向?yàn)?Regular,水平方向是 Compact宗苍,而在橫屏?xí)r兩個(gè)方向都是 Compact稼稿。
要注意的是薄榛,這里和談到的設(shè)備和方向,都僅僅只是為了給大家一個(gè)直觀的印象让歼。相信隨著設(shè)備的變化敞恋,這個(gè)分類也會(huì)發(fā)生變動(dòng)和更新。Size Classes 的設(shè)計(jì)哲學(xué)就是尺寸無關(guān)谋右,在實(shí)際中我們也應(yīng)該盡量把具體的尺寸拋開腦后硬猫,而去盡快習(xí)慣和適應(yīng)新的體系。
** UITraitCollection 和 UITraitEnvironment**
為了表征 Size Classes改执,Apple 在 iOS 8 中引入了一個(gè)新的類啸蜜,UITraitCollection。
這個(gè)類封裝了像水平和豎直方向的 Size Class 等信息.
iOS 8 的 UIKit 中大多數(shù) UI 的基礎(chǔ)類 (包括 UIScreen天梧,UIWindow盔性,UIViewController 和 UIView) 都實(shí)現(xiàn)了 UITraitEnvironment 這個(gè)接口,通過其中的 traitCollection 這個(gè)屬性呢岗,我們可以拿到對(duì)應(yīng)的 UITraitCollection 對(duì)象冕香,從而得知當(dāng)前的 Size Class,并進(jìn)一步確定界面的布局后豫。
和 UIKit 中的響應(yīng)者鏈正好相反悉尾,traitCollection 將會(huì)在 view hierarchy 中自上而下地進(jìn)行傳遞。對(duì)于沒有指定 traitCollection 的 UI 部件挫酿,將使用其父節(jié)點(diǎn)的 traitCollection构眯。這在布局包含 childViewController 的界面的時(shí)候會(huì)相當(dāng)有用。在 UITraitEnvironment 這個(gè)接口中另一個(gè)非常有用的是 -traitCollectionDidChange:早龟。在 traitCollection 發(fā)生變化時(shí)惫霸,這個(gè)方法將被調(diào)用。在實(shí)際操作時(shí)葱弟,我們往往會(huì)在 ViewController 中重寫 -traitCollectionDidChange: 或者 -willTransitionToTraitCollection:withTransitionCoordinator: 方法 (對(duì)于 ViewController 來說的話壹店,后者也許是更好的選擇,因?yàn)樘峁┝宿D(zhuǎn)場上下文方便進(jìn)行動(dòng)畫芝加;但是對(duì)于普通的 View 來說就只有前面一個(gè)方法了)硅卢,然后在其中對(duì)當(dāng)前的 traitCollection 進(jìn)行判斷,并進(jìn)行重新布局以及動(dòng)畫藏杖。代碼看起來大概會(huì)是這個(gè)樣子:
- (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection
withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator
{
[super willTransitionToTraitCollection:newCollection
withTransitionCoordinator:coordinator];
[coordinator animateAlongsideTransition:^(id <UIViewControllerTransitionCoordinatorContext> context) {
if (newCollection.verticalSizeClass == UIUserInterfaceSizeClassCompact) {
//To Do: modify something for compact vertical size
} else {
//To Do: modify something for other vertical size
}
[self.view setNeedsLayout];
} completion:nil];
}
在兩個(gè) To Do 中将塑,我們應(yīng)該刪除或者添加或者更改不同條件下的 Auto Layout 約束 (當(dāng)然,你也可以干其他任何你想做的事情)蝌麸,然后調(diào)用 -setNeedsLayout 來在上下文中觸發(fā)轉(zhuǎn)移動(dòng)畫点寥。如果你堅(jiān)持用代碼來處理的話,可能需要面臨對(duì)于不同 Size Classes 來做移除舊的約束和添加新的約束這樣的事情来吩,可以說是很麻煩 (至少我覺得是麻煩的要死)开财。
但是如果我們使用 IB 的話汉柒,這些事情和代碼都可以省掉,我們可以非常方便地在 IB 中指定各種 Size Classes 的約束 (稍后會(huì)介紹如何使用 IB 來對(duì)應(yīng) Size Classes)责鳍。另外使用 IB 不僅可以節(jié)約成百上千行的布局代碼碾褂,更可以從新的 Xcode 和 IB 中得到很多設(shè)計(jì)時(shí)就可以實(shí)時(shí)監(jiān)視,查看并且調(diào)試的特性历葛≌可以說手寫 UI 和使用 IB 設(shè)計(jì)的時(shí)間消耗和成本差距被進(jìn)一步拉大,并且出現(xiàn)了很多手寫 UI 無法實(shí)現(xiàn)恤溶,但是 IB 可以不假思索地完成的任務(wù)乓诽。從這個(gè)意義上來說,新的 IB 和 Size Classes 系統(tǒng)可以說無情地給手寫代碼判了個(gè)死緩咒程。
另外鸠天,新的 API 和體系的引入也同時(shí)給很多我們熟悉的 UIViewController 的有關(guān)旋轉(zhuǎn)的老朋友判了死刑,比如下面這些 API 都棄用了:
@property(nonatomic, readonly) UIInterfaceOrientation interfaceOrientation
- willRotateToInterfaceOrientation:duration:
- willAnimateRotationToInterfaceOrientation:duration:
- didRotateFromInterfaceOrientation:
- shouldAutomaticallyForwardRotationMethods
現(xiàn)在全部統(tǒng)一到了 viewWillTransitionToSize:withTransitionCoordinator:
帐姻,旋轉(zhuǎn)的概念不再被提倡使用稠集。其實(shí)仔細(xì)想想,所謂旋轉(zhuǎn)饥瓷,不過就是一種 Size 的改變而已
在 Interface Builder 中使用 Size Classes
IB的畫布是正方形剥纷,這是Size Classes
對(duì)應(yīng)的編輯方式.
IB 界面的正下方,你可以看到一個(gè) wAny hAny 的按鈕 呢铆,
代表現(xiàn)在的 IB 是對(duì)應(yīng)任意高度和任意寬度的晦鞋。
這樣我們就很容易在同一個(gè) storyboard 文件里對(duì)不同的設(shè)備進(jìn)行適配:按照設(shè)備需要添加或者編輯某些約束,或者是在特定尺寸下隱藏某些 view (使用 Attribute Inspector 里的 Installed 選框的加號(hào)添加)棺克。這使得使用 IB 制作通用程序變簡單了悠垛,我們不再需要為 iPhone 和 iPad 準(zhǔn)備兩套 storyboard 了。
Size Classes 和 Image Asset 及 UIAppearence
Image Asset 里也加入了對(duì) Size Classes 的支持娜谊,也就是說确买,我們可以對(duì)不同的 Size Class 指定不同的圖片了。
在 Image Asset 的編輯面板中選擇某張圖片因俐,Inspector 里現(xiàn)在多了一個(gè) Width 和 Height 的組合.
alpha hidden opaque的區(qū)別
http://blog.csdn.net/wzzvictory/article/details/10076323
opaque屬性:
該屬性用于決定改接受者(UIView的實(shí)例)是否然其視圖不透明.
用處:
- 給繪圖系統(tǒng)提供一個(gè)性能優(yōu)化開關(guān).如果該值為YES,那么繪圖在繪制改視圖的時(shí)候吧整個(gè)視圖當(dāng)做不透明(相當(dāng)于alpha=1)對(duì)待周偎。這樣抹剩,繪圖系統(tǒng)在執(zhí)行繪圖過程中會(huì)優(yōu)化一些操作并且提升系統(tǒng)性能;如果是NO蓉坎,那么繪圖系統(tǒng)將其和其他內(nèi)容平等對(duì)待澳眷,不去做優(yōu)化操作。為了性能方面的考量蛉艾,默認(rèn)被設(shè)置為YES(也就是優(yōu)化).
- 這個(gè)消息和alpha是有關(guān)系的.
一個(gè)不透明的視圖需要整個(gè)邊界的內(nèi)容都是不透明的.基于這個(gè)原因.opaque設(shè)置為YES.要求對(duì)應(yīng)的alpha必須為1.0钳踊,如果一個(gè)UIView實(shí)例opaque被設(shè)置為YES衷敌,而同事它又沒有完全填充它的邊界(bounds),或者它包好了整個(gè)或者部分的透明的內(nèi)容視圖拓瞪,那么將會(huì)導(dǎo)致未知的結(jié)果.
所以缴罗,如果視圖部分或者全部支持透明,那么你必須把opaque這個(gè)值設(shè)置為NO.
**draw **
draw 就是 oc中的 drawRect.參考:http://blog.csdn.net/liliangchw/article/details/8448381
oc中 -(void)drawRect:(CGRect)aRect;
祭埂,
它的參數(shù)是一個(gè)rect面氓,也就是一個(gè)矩形,是我們需要重繪的區(qū)域.可以忽略參數(shù)蛆橡,它只是為了性能優(yōu)化舌界,只在固定的區(qū)域繪圖.
注意:不能主動(dòng)去調(diào)用drawRect,因?yàn)樗怯上到y(tǒng)去調(diào)用的.
我們告訴系統(tǒng)需要重繪的話泰演,需要發(fā)送2個(gè)消息:
1. (void)setNeedsDisplay;
2. (void)setNeedsDisplayInRect:(CGRect)aRect;
可以認(rèn)為初始化的時(shí)候設(shè)置的是一個(gè)點(diǎn)呻拌,然后晚些系統(tǒng)查看所有需要重繪的東西.
然后把它們按照順序排列,因?yàn)橛行〇|西可能會(huì)重疊睦焕,然后再非常高效的吧需要的東西繪制出來.
這樣做有2個(gè)好處:
- 讓系統(tǒng)依據(jù)層的情況最優(yōu)化性能.
- 如果你的property有一些setter藐握,當(dāng)你設(shè)置的時(shí)候需要重繪,這種情況也優(yōu)化了复亏。
所以你所有的setter都會(huì)調(diào)用self的setNeedsDisplay來重繪.
如果有人用了你的view,然后調(diào)用了好幾個(gè)這樣的setter趾娃,只需要重繪一次.每隔=個(gè)setNeedsDisplay都會(huì)被一起傳遞過去,然后一次性畫出來.而不是每次都重繪.
環(huán)境缔御,上下問(context
)決定了你在哪兒繪圖抬闷,所以你創(chuàng)建環(huán)境的方法決定了要在哪兒繪圖.
關(guān)于這個(gè)環(huán)境要注意的有一點(diǎn),每次調(diào)用drawRect
環(huán)境都是不一樣的耕突,所以不要把它保存起來笤成,而是每次都去獲取新的.
CGContextRef context = UIGraphicsGetCurrentContext();
這個(gè)幾乎也是每個(gè)drawRect
的第一行.
CGContextRef
是一個(gè)coockie
,上下文,不是一個(gè)對(duì)象眷茁。當(dāng)你有了上下文(環(huán)境炕泳,context),就可以用來創(chuàng)建軌跡了.