前言
這是斯坦福大學(xué)在線課程-Developing iOS 9 Apps with Swift 的學(xué)習(xí)內(nèi)容胡桨,在iTunes上就可以搜到,有興趣的小伙伴可以一起學(xué)習(xí)一起進步哈盼樟!這里我將一些我認(rèn)為的關(guān)鍵知識點摘錄在我的學(xué)習(xí)筆記系列中贫贝。之前用英文寫了幾篇,感覺沒什么人看乐设,其實個人認(rèn)為用英文學(xué)再用英文寫其實更簡單方便一些。
Demo
首先绎巨,是一張萌蠢的笑臉近尚,你要是看著不舒服,你可以從我的github中下載相應(yīng)代碼场勤,或者自己敲哈戈锻,讓它哭也成。
Views
-
先亂入一條(別打我)和媳,swift的命名規(guī)范:在swift中格遭,所有類型的名稱的首字母大寫。
比如private enum Eye
,private struct Ratios
- 一個view(比如:UIView)表示的是一個矩形的區(qū)域留瞳,定義了一個坐標(biāo)空間拒迅。它可以用來畫圖(比如這個demo),也可以用來處理點擊事件她倘。
- view在swift中是分級的璧微,也就是說
- 一個view只能有一個superview,
var superview: UIView?
- 一個view可以有很多個subview,
var subviews: [UIView]
- subview的范圍甚至可以在他老爸view的范圍之外。
- view是有順序之分的硬梁,后來者居上前硫。
- UIWindow在view(分級)中處在非常高級的位置,在一個app中一般只有一個荧止。
初始化一個UIView
有兩種不同的方式:
- init(frame: CGRect) // 由代碼創(chuàng)建生成
- init(coder: NSCoder) // 由storyboard生成
如果你需要一個初始化程序屹电,那這兩種初始化都需要執(zhí)行:
func setup() { ... }
override init(frame: CGRect) { // a designed initializer
super.init(frame: frame)
setup()
}
required init(coder aDecoder: NSCoder) { // a required initializer
super.init(coder: aDecoder)
setup()
}
另一個初始化方式:使用awakeFromNib()
,這只能用于storyboard上創(chuàng)建的UIView罩息。注意這不是一個初始化器嗤详,它是“初始化完成之后立馬被調(diào)用”个扰。
坐標(biāo)系統(tǒng)數(shù)據(jù)結(jié)構(gòu)
- CGFloat
在UIView的坐標(biāo)系統(tǒng)中瓷炮,使用CGFloat類型的數(shù)據(jù)而不是Double或者Float。你可以將Double或者Float轉(zhuǎn)換成CGFloat, 比如:let cgf = CGFloat(aDouble)
- CGPoint
比如:var point = CGPoint(x: 37.0, y: 52.0)
其實就是由兩個CGFloat類型的數(shù)組成的一個簡單結(jié)構(gòu)递宅。 - CGSize
和CGPoint差不多娘香,也是由兩個CGFloat類型的數(shù)組成的簡單結(jié)構(gòu)苍狰。
比如:
var size = CGSize(width: 100.0, height: 50.0)
size.width += 10
size.height += 5
- CGRect
由CGPoint和CGSize組成的結(jié)構(gòu)
struct CGRect {
var origin: CGPoint
var size: CGSize
}
let rect = CGRect(origin: aCGPoint, size: aCGSize) //當(dāng)然可以用別的初始化方式
這結(jié)構(gòu)里自帶了很多好東西:
var minX: CGFloat //最小的x
var midY: CGFloat //中間點的y
intersects(CGRect) -> Bool //判斷和別的CGRect有沒有相交
intersect(CGRect) //返回相交的部分
contains(CGRect) -> Bool //判斷是否包含了另一個CGRect
View的坐標(biāo)系統(tǒng)
-
左上是初始點。如下圖:
烘绽!注意淋昭,單位是點,不是
像素安接,點不是像素翔忽,點等于幾個像素。比如在6 plus上盏檐,每個點有3個像素歇式;有些手機則是2個像素一個點。
你可以通過這條語句知道你的設(shè)備一個點有多少像素胡野,var contentScaleFactor: CGFloat
當(dāng)你需要畫圖的時候材失,使用
var bounds: CGRect
,這是一個包含了你自己的坐標(biāo)系統(tǒng)的畫圖空間的矩形硫豆,也就是說龙巨,它在你自己的畫圖空間里,由你在view中的代碼實現(xiàn)來定義bounds.origin熊响。那么UIView在哪里旨别?
var center: CGPoint // UIView的中心坐標(biāo)(在它的superview的坐標(biāo)系統(tǒng)中)
var frame: CGRect // 包含UIView的矩形(在它的superview的坐標(biāo)系統(tǒng)中)
。 frame指的是你的view在superview中的位置汗茄,也就是說這是放在superview的坐標(biāo)系統(tǒng)中的昼榛,而不是你的畫圖坐標(biāo)系統(tǒng)中。
剔难。 center相應(yīng)的胆屿,也是指的superview中的center,和你的畫圖空間并沒有毛線關(guān)系~當(dāng)你畫圖的時候用bounds就好啦偶宫》羌#看代碼理解也許會比較清晰一點,可以以上面提到的demo為例纯趋,
憎兽。 frame和bounds的寬高也不同,因為view可以旋轉(zhuǎn)吵冒。
創(chuàng)建一個view
在上面提到的demo中纯命,我們做的是一個笑臉,而iOS并沒有smileview這個東西痹栖,所以我們要自己建亿汞。我們使用的是一般view(generic view),就當(dāng)是一般類吧揪阿,可以拿來隨意發(fā)揮疗我。
你可以在object library里輕松找到它咆畏,或者搜“view“
e.g.
// 假設(shè)這段代碼在UIViewController中
let labelRect = CGRect(x: 20, y: 20, width: 10, height: 10)
let label = UILabel(frame: labelRect) // UILabel是UIView的子類,所以那些UILabel中的那些字也是一筆一畫畫出來的吴裤。旧找。
label.text = "hello"
view.addSubview(label)
自定義Views
何時需要自定義UIView的子類
我想自定義繪圖
我想以一些特殊的方式處理點擊事件(這里不同于button或者slider)
至于畫圖,只需要創(chuàng)建一個UIView的子類麦牺,然后override drawRect:
override func drawRect(regionThatNeedsToBeDrawn: CGRect)
如之前所說钮蛛,你可以畫在regionThatNeedsToBeDrawn的范圍之外。
- UIView的邊界定義了我們整個畫圖區(qū)域剖膳,region只是一個子區(qū)域!!!絕對不能直接調(diào)用drawRect愿卒,它是系統(tǒng)的專屬天使。但是當(dāng)你需要畫圖怎么辦呢潮秘?告訴系統(tǒng)琼开,你要用這個方法了,用以下的語句:
setNeedsDisplay()
setNeedsDisplayInRect(regionThatNeedsToBeRedrawn: CGRect)
iOS會在一個適當(dāng)?shù)臅r機調(diào)用drawRect枕荞,比如你的破事全部決定了之后柜候,一次性將要重畫(redraw)的東西全部drawRect。
那么我怎么實現(xiàn)drawRect呢躏精?
你可以使用一個類C的API(不是面向?qū)ο蟮模┰ⅲ蠧ore Graphics,swift是完全面相對象的矗烛,摻和進來這玩意應(yīng)該不是好事吧 ==
你還可以使用面向?qū)ο蟮念悾璘IBezierPath辅柴,這也是我們在demo中所使用的。
Core Graphics的一些基本概念
- 使用
UIGraphicsGetCurrentContext()
來獲取一些能在drawRect中使用的文本內(nèi)容(context瞭吃,打印的碌嘀,屏幕外的緩存中的, etc.) - 創(chuàng)建路徑(線,圓)
- 設(shè)定一些相關(guān)屬性歪架,比如顏色股冗,字體,線寬之類的和蚪。
-
stroke
或者fill
以上創(chuàng)建的路徑止状。
UIBezierPath
和上面那個家伙差不多,只是UIBezierPath自動知道context攒霹。定義一個路徑
創(chuàng)建一個UIBezierPath
let path = UIBezierPath()
- 加幾條線怯疤,或者圓弧
path.moveToPoint(CGPoint(x: 80, y: 50))
path.addLineToPoint(CGPoint(x:140, y: 150))
path.addLineToPoint(CGPoint(x: 10, y: 150))
- 可以閉合路徑
path.closePath()
此時就已經(jīng)得到了一個可愛的三角形。但是并沒有畫出來
-
注意催束, 你僅僅將上面創(chuàng)建的線條放在drawRect中集峦,并不會顯示什么。必須要設(shè)置相應(yīng)的屬性(顏色,線寬等等)少梁,然后
stroke
/fill
,才能在屏幕上顯示出來矫付。
UIColor.greenColor().setFill() // 注意這是UIColor中的方法
UIColor.redColor().setStroke() // 注意這是UIColor中的方法
path.lineWidth = 3.0 // 這是UIBezierPath中的屬性
path.fill() // UIBezierPath中的方法
path.stroke() // UIBezierPath中的方法
- 你也可以用UIBezierPath畫很多其它類型的圖凯沪,比如:
let roundRect = UIBezierPath(roundedRect: CGRect, cornerRadius: CGFloat)
let oval = UIBezierPath(ovalInRect: aCGRect)
- 也可以圓滑夾角,就是給每個角增加一個弧度买优。使用
addClip()
- 也可以進行碰撞監(jiān)測妨马,就是檢測一個點是不是在閉合路徑里面。
func containsPoint(CGPoint) -> Bool
UIColor
- 對于很多普通顏色來講杀赢,有很多類方法可以使用烘跺,比如
let green = UIColor.greenColor()
,可以用RGB, HSB, 甚至可以使用某些樣式(比如圖片)脂崔。 - UIView的背景色滤淳,
var backgroundColor: UIColor
- 顏色可以有alpha,可以設(shè)置透明度
let transparentYellow = UIColor.yellowColor().colorWithAlphaComponent(0.5) // 這是個instance method, 不是type method
alpha: 0.0(完全透明) - 1.0(完全不透明)
如果想要在程序中設(shè)置顏色的透明度砌左,必須設(shè)置
var opaque = false
脖咐, 來讓系統(tǒng)知道這些都不是不透明的,也就是你要開始設(shè)置透明度了汇歹。也可以設(shè)置整個UIView的透明度
var alpha: CGFloat
通過alpha屁擅,可是設(shè)計一個漸出(慢慢消失)的動畫。
- 也可以隱藏一個view产弹,通過
var hidden: Bool
顯示(畫)文本
- 一般我們使用UILabel來顯示文本派歌,但我們有時候還是需要在drawRect中直接顯示文本
- 在drawRect中,可以使用NSAttributedString
AttributedString就是每個string中的字符痰哨,都有一個字典存儲相應(yīng)的每個字符的屬性信息胶果,比如顏色,字體等斤斧。
let text = NSAttributedString("hello")
text.drawAtPoint(aCGPoint)
let textSize: CGSize = text.size //這個字符串需要多少空間
- NSAttributedString的兩個弊端
- 我們知道稽物,var具有可變性(mutability),let沒有折欠。但是在NSAttributedString中贝或,不管是var還是let,都是不可變的(immutable)锐秦。因為這是個objective-c的類咪奖,所以swift中還是有點缺陷。要想做到可變形酱床,你可以使用另一個類羊赵,NSMutableAttributedString,如下語句:
let mutableString = NSMutableAttributedString("some text")
注意,NSAttributedString不是String昧捷,也不是NSString.
- swift的string是unicode的闲昭,比oc的強大太多,所以它們的string也不一樣靡挥,在NSAttributedString中序矩,需要使用NSRange,注意這不是Range跋破,這是oc里的NSRange簸淀。所以在使用的時候,需要將range轉(zhuǎn)換成NSRange(可自動完成)毒返,然后才能在NSAttributedString中用NSRange租幕。
func setAttributes(attributes: Dictionary, range: NSRange)
func addAttributes(attributes: Dictionary, range: NSRange)
在Attributes中可以放以下這些dictionary:
NSForegroundColorAttributeName: UIColor
NSStrokeWidthAttributeName: UIFloat
NSFontAttributeName: UIFont
字體
字體在蘋果的產(chǎn)品中占有非常重要的地位,畢竟藝術(shù)品拧簸。
- 使用字體的最好的方式
- 對于文本內(nèi)容劲绪,采用preferred font
static func preferredFontForTextStyle(UIFontTextStyle) -> UIFont
UIFontTextStyle.Headline
UIFontTextStyle.Body
UIFontTextStyle.Footnote
- 對于按鈕之類的,使用系統(tǒng)字體(system fonts)
static func systemFontOfSize(pointSize: CGFloat) -> UIFont
static func boldSystemFontOfSize(pointSize: CGFloat) -> UIFont
在用戶的文本信息中盆赤,不要使用這些系統(tǒng)字體
- 其它方式:UIFont和UIFontDescriptor
顯示圖片
有個UILabel相類似的類珠叔,UIImageView,當(dāng)然你還是有可能想在drawRect中直接顯示圖片的弟劲,那么祷安。。兔乞。
- 創(chuàng)建UIImage -
let image: UIImage? = UIImage(named: "foo")
汇鞭,optional是因為有可能沒有圖片 - 從系統(tǒng)文件中創(chuàng)建(files in the file system)
let image: UIImage? = UIImage(contentsOfFile: aString)
let image: UIImage? = UIImage(data: anNSData) // jpg, png, tiff, etc.
- 開始畫
let image: UIImage = ...
image.drawAtPoint(aCGPoint) // 圖片的左上角
image.drawInRect(aCGRect) // 將圖片按比例擴充到aCGRect中
image.drawAsPatternInRect(aCGRect) //將圖片平鋪到aCGRect中
歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明出處庸追。訪問我的個人主頁霍骄,了解更多。