前幾天在github上有一個叫30DaysofSwift比較火,作為一直也在關(guān)注Swift這塊的我,果斷下載下來學(xué)習(xí),發(fā)現(xiàn)確實簡單實用,所以自己也跟隨作者試著重寫,并將每一個Demo中的一些重點記錄了一下,特此也非常感謝Allen朝輝的開源精神。
另外作者在簡書上也有記錄,自學(xué) iOS - 三十天三十個 Swift 項目

一、 計時器的簡單使用(day01)
注意小數(shù)點的保留小數(shù)位,否則會出現(xiàn)異常。
timeLabel.text = String(format: "%.1f", Counter)
當(dāng)然NSTimer的基本使用也是需要OK的
Timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("UpdateTimer"), userInfo: nil, repeats: true)
二、 字體的轉(zhuǎn)換(day02)
了解 常用的字體
for family in UIFont.familyNames() {
for font in UIFont.fontNamesForFamilyName(family){
print(font)
}
}
然后通過這方法使用就OK了
public /*not inherited*/ init?(name fontName: String, size fontSize: CGFloat)
三、 TableView點擊詳情播放視頻(day03)
我覺的其中播放視頻這塊,路徑別寫錯了
let path = NSBundle.mainBundle().pathForResource("emoji zone", ofType: "mp4")
playerView = AVPlayer(URL: NSURL(fileURLWithPath: path!))
playViewController.player = playerView
self.presentViewController(playViewController, animated: true) {
self.playViewController.player?.play()
}
另外作者用MVC模式也是簡單經(jīng)典的。
四、 ScrollerView + 自定義拍照(day04)
首先作者使用
addChildViewController
didMoveToParentViewController
讓第一層永遠只有一個 Controller ,很多場景都是實用的
當(dāng)然自定義拍照這塊,需要學(xué)習(xí)了解下
// MARK:- 屬性
var captureSession : AVCaptureSession?
var stillImageOutput : AVCaptureStillImageOutput?
var previewLayer : AVCaptureVideoPreviewLayer?
@IBOutlet var cameraView: UIView!
//MARK:- CilcleLife
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
previewLayer?.frame = cameraView.bounds
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
// 初始化 session 對象來執(zhí)行輸入設(shè)備和輸出設(shè)備之間的數(shù)據(jù)傳遞
captureSession = AVCaptureSession()
// 設(shè)置session 的規(guī)格
captureSession?.sessionPreset = AVCaptureSessionPreset1920x1080
// 輸出設(shè)備的類型
let backCamera = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
var error : NSError?
// 輸入流
var input: AVCaptureDeviceInput!
do {
input = try AVCaptureDeviceInput(device: backCamera)
} catch let error1 as NSError {
error = error1
input = nil
}
if (error == nil && captureSession?.canAddInput(input) != nil){
// 加入輸入流
captureSession?.addInput(input)
// 初始化照片輸出流以及規(guī)格
stillImageOutput = AVCaptureStillImageOutput()
stillImageOutput?.outputSettings = [AVVideoCodecKey : AVVideoCodecJPEG]
if (captureSession?.canAddOutput(stillImageOutput) != nil){
// 加入輸出流
captureSession?.addOutput(stillImageOutput)
// 圖片預(yù)覽層的輸出
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
previewLayer?.videoGravity = AVLayerVideoGravityResizeAspect
previewLayer?.connection.videoOrientation = AVCaptureVideoOrientation.Portrait
// View 加上 預(yù)覽層
cameraView.layer.addSublayer(previewLayer!)
// 開始執(zhí)行
captureSession?.startRunning()
}
}
}
五、 CollectionView的簡單實用 (day05)
此處用的是IB 設(shè)置CollectionView,以前設(shè)置那個 UICollectionViewFlowLayout的地方就在這里啦

六、地理位置的確定(day06)
一定要記住iOS8之后,一定要在infoPlist 中加入
NSLocationAlwaysUsageDescription 和 NSLocationWhenInUseUsageDescription 才能正常使用地理位置。
七、簡單刷新 (day07)
這個Demo是作者用UITableViewController加UIRefreshControl實現(xiàn)刷新的
// 核心代碼
tableViewController.refreshControl = self.refreshControl
self.refreshControl.addTarget(self, action: "didRoadEmoji", forControlEvents: .ValueChanged)
self.refreshControl.backgroundColor = UIColor(red:0.113, green:0.113, blue:0.145, alpha:1)
let attributes = [NSForegroundColorAttributeName: UIColor.whiteColor()]
self.refreshControl.attributedTitle = NSAttributedString(string: "Last updated on \(NSDate())", attributes: attributes)
self.refreshControl.tintColor = UIColor.whiteColor()
而我是就是簡單用UITableView + UIRefreshControl 實現(xiàn)的
tableView.tableFooterView = UIView()
refreshControl.addTarget(self, action: Selector("refreshTheData"), forControlEvents: UIControlEvents.ValueChanged)
// 增加備注文字
let attributes = [NSForegroundColorAttributeName: UIColor.grayColor()]
refreshControl.attributedTitle = NSAttributedString(string: "上次刷新時間 \(NSDate())", attributes: attributes)
tableView.addSubview(refreshControl)
八、隨音樂漸變背景閃效果 (day08)
首先我們需要了解下CagradientLayer,它是用來生成兩種或更多顏色平滑漸變的。
整個流程:通過定時改變背景顏色,并在上面添加一個預(yù)覽顏色層。
// 隨機改變背景顏色
let redValue = CGFloat(drand48())
let blueValue = CGFloat(drand48())
let greenValue = CGFloat(drand48())
self.view.backgroundColor = UIColor(red: redValue, green: greenValue, blue: blueValue, alpha: 1.0)
// 制作預(yù)覽層
let gradientLayer = CAGradientLayer()
// 先設(shè)置的大小
gradientLayer.frame = self.view.frame
// 設(shè)置五個不同的顏色
let color1 = UIColor(white: 0.5, alpha: 0.2).CGColor as CGColorRef
let color2 = UIColor(red: 1.0, green: 0, blue: 0, alpha: 0.4).CGColor as CGColorRef
let color3 = UIColor(red: 0, green: 1, blue: 0, alpha: 0.3).CGColor as CGColorRef
let color4 = UIColor(red: 0, green: 0, blue: 1, alpha: 0.3).CGColor as CGColorRef
let color5 = UIColor(white: 0.4, alpha: 0.2).CGColor as CGColorRef
// 放入顏色層中
gradientLayer.colors = [color1, color2, color3, color4, color5]
// 并為這五個顏色確定 locations
gradientLayer.locations = [@0.10, @0.30, @0.50, @0.70, @0.90]
// 設(shè)置開始點 和 結(jié)束點
gradientLayer.startPoint = CGPointMake(0, 0)
gradientLayer.endPoint = CGPointMake(1, 1)
// 添加到上面
self.view.layer.addSublayer(gradientLayer)
九、放大縮小圖片(day09)
之前我的第一反應(yīng)是用UIPinchGestureRecognizer,但是縮放出來的效果不怎么好,還是按作者的思路,UIScrollerView添加UIImageView,通過UIScrollerView的代理來解決。
此時要注意ScrollView的以下幾個屬性和代理方法:
// 視圖在scrollView中的位置(UIEdgeInsetsZero) 也相當(dāng)于設(shè)置內(nèi)邊距
public var contentInset: UIEdgeInsets
// 設(shè)置縮放系數(shù)
public var minimumZoomScale: CGFloat
public var maximumZoomScale: CGFloat
// 返回將要縮放的UIView對象。要執(zhí)行多次
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
}
// 當(dāng)scrollView縮放時,調(diào)用該方法。在縮放過程中,回多次調(diào)用
func scrollViewDidZoom(scrollView: UIScrollView) {
}
十、 登錄界面后帶有視頻播放,唯美效果(day10)
這個主要是對于視頻播放的一個優(yōu)化,其中這里面作者引用的兩個類很有參考價值。
十一、漸變顏色的TableView (day11)
注意tableView中某個代理的使用
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
}
同事繼續(xù)使用CAGradientLayer,讓其cell有凸出的感覺
十二、登錄的動畫效果 (day12)
注意這兩個基本的動畫效果,以及調(diào)整 constant 后需要 self.view.layoutIfNeeded()
UIView.animateWithDuration(0.5, delay: 0.00, options: UIViewAnimationOptions.CurveEaseOut, animations: {
self.centerAlignUsername.constant += self.view.bounds.width
self.view.layoutIfNeeded()
}, completion: nil)
UIView.animateWithDuration(1.0, delay: 0.0, usingSpringWithDamping: 0.2, initialSpringVelocity: 10, options: UIViewAnimationOptions.CurveLinear, animations: {
self.loginButton.bounds = CGRect(x: bounds.origin.x - 20, y: bounds.origin.y, width: bounds.size.width + 60, height: bounds.size.height)
}, completion: nil)
后者是一個橫向變寬的View彈出的動畫效果,同時我們進一步了解下這個方法,通過Oc來看,更清楚一些。
+ (void)animateWithDuration:(NSTimeInterval)duration
delay:(NSTimeInterval)delay
usingSpringWithDamping:(CGFloat)dampingRatio
initialSpringVelocity:(CGFloat)velocity
options:(UIViewAnimationOptions)options
animations:(void (^)(void))animations
completion:(void (^)(BOOL finished))completion
-
dampingRatio:usingSpringWithDamping的范圍為0.0f到1.0f,數(shù)值越小「彈簧」的振動效果越明顯。 -
velocity:initialSpringVelocity則表示初始的速度,數(shù)值越大一開始移動越快。 -
options: 自然是動畫效果啦,看我們自己選擇吧
詳細可以看這篇使用 iOS 8 Spring Animation API 創(chuàng)建動畫
十三、cell的逐漸出現(xiàn)的動畫效果 (day13)
只要注意以下這個在viewWillAppear處理就OK了,以后我們的動畫cell思路確實可以這樣做。
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.tableView.reloadData()
// 該方法是獲取界面上能顯示出來了cell
let cells = tableView.visibleCells
// 獲取總的高度
let tableHeight: CGFloat = tableView.bounds.size.height
// 先讓每一cell 都在下面
for i in cells {
let cell: UITableViewCell = i as UITableViewCell
// 改變位置
cell.transform = CGAffineTransformMakeTranslation(0, tableHeight)
}
var index = 0
for a in cells {
let cell: UITableViewCell = a as UITableViewCell
UIView.animateWithDuration(1.5, delay: 0.05 * Double(index), usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: [], animations: {
// 回歸位置
cell.transform = CGAffineTransformMakeTranslation(0, 0);
}, completion: nil)
index += 1
}
}
十四、UIPickerView 的動畫選擇器效果(day14)
此處考查的可以說是UIPickerView的用法,常用的幾個代理方法以及下面這個方法:
//主動去選擇 改變的
public func selectRow(row: Int, inComponent component: Int, animated: Bool)
以及隨機數(shù)arc4random()的使用
通過arc4random()獲取0到x-1之間的整數(shù)的代碼如下
let value = (Int)arc4random()%x;
獲取1到x之間的整數(shù)的代碼如下
let value = (Int)(arc4random()%x )+1
十五: Twitter進入動畫的模仿 (day15)
我們得大致了解下CAKeyframeAnimation, keyframe顧名思義就是關(guān)鍵點的frame,你可以通過設(shè)定CALayer的始點、中間關(guān)鍵點、終點的frame,時間,動畫會沿你設(shè)定的軌跡進行移動。以及C?ALayer的基本使用。
CALayer
self.mask = CALayer()
self.mask?.contents = UIImage(named: "twitter")?.CGImage
// 縮放常量
self.mask?.contentsGravity = kCAGravityResizeAspect
// 大小
self.mask?.bounds = CGRect(x: 0, y: 0, width: 100, height: 80)
// 錨點
self.mask?.anchorPoint = CGPoint(x: 0.5, y: 0.5)
// 位置點
self.mask?.position = CGPoint(x: imageView.frame.size.width / 2, y: imageView.frame.size.height / 2)
// 真正將mask 賦值給 UIImageView上的mask
imageView.layer.mask = self.mask
CAKeyframeAnimation
let keyFrameAnimation = CAKeyframeAnimation(keyPath: "bounds")
keyFrameAnimation.delegate = self
// 持續(xù)的時間
keyFrameAnimation.duration = 0.6
// 開始的時間
keyFrameAnimation.beginTime = CACurrentMediaTime() + 0.5
// 這個屬性用以指定時間函數(shù),類似于運動的加速度,有以下幾種類型
/*
1 kCAMediaTimingFunctionLinear//線性
2 kCAMediaTimingFunctionEaseIn//淡入
3 kCAMediaTimingFunctionEaseOut//淡出
4 kCAMediaTimingFunctionEaseInEaseOut//淡入淡出
5 kCAMediaTimingFunctionDefault//默認
*/
keyFrameAnimation.timingFunctions = [CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut), CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)]
// 初始化大小
let initalBounds = NSValue(CGRect: mask!.bounds)
// 中間的大小
let secondBounds = NSValue(CGRect: CGRect(x: 0, y: 0, width: 90, height: 73))
// 最后的大小
let finalBounds = NSValue(CGRect: CGRect(x: 0, y: 0, width: 1600, height: 1300))
// values屬性指明整個動畫過程中的關(guān)鍵幀點,例如下面"initalBounds, secondBounds, finalBounds通過values指定的。需要注意的是,起點必須作為values的第一個值
keyFrameAnimation.values = [initalBounds, secondBounds, finalBounds]
// 該屬性是一個數(shù)組,用以指定每個子路徑(initalBounds, secondBounds, finalBounds)的時間
keyFrameAnimation.keyTimes = [0, 0.3, 1]
// 最后是看將其此效果放在哪里
self.mask!.addAnimation(keyFrameAnimation, forKey: "bounds")
總的來說,動畫這塊需要繼續(xù)學(xué)習(xí),暫時好多地方還不太熟。