とりあえず動くものを作ってみる。動画を10分割してキャプチャー一覧を表示。選択されたところから再生します。
UICollectionViewは基本的にはUITbaleViewを使うのと同じような仕組みで動く。
//1
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
//2
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
//3
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
//cellの設定
}
最低上記3つの関数を実装すれば良い(と思う)
セルに関してはUITableViewのセルのようにフォーマットが用意されてるわけではなさそうなので、毎回UICollectionViewCellのサブクラスを用意するっぽいです。
class CustomCell : UICollectionViewCell {
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var timeLabel: UILabel!
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
//fatalError("init(coder:) has not been implemented")
}
override func awakeFromNib() {
let backgroundView = UIView(frame: frame)
backgroundView.backgroundColor = UIColor.whiteColor()
self.backgroundView = backgroundView
let selectedBGView = UIView(frame: frame)
selectedBGView.backgroundColor = UIColor.redColor()
self.selectedBackgroundView = selectedBGView
}
}
awakeFromNib内でセレクトされた時にCellの背景色を変えるロジックを入れてます。この場合、選択されたら赤くなる。他にも方法はあるみたいです。
動画を扱うプログラミングはなかなか奥が深いのですが、まず
AVFoundation
AssetsLibrary
上記2つのライブラリをプロジェクトに追加。
動画はiPhoneで撮った動画をプロジェクトに追加。
後はそれを読み込み、再生時間を10分割した時のキャプチャー画像とその時の読み込み時間を配列に保存。
import UIKit
import AVFoundation
import AssetsLibrary
class ViewController: UICollectionViewController {
struct Capture {
var picture : CGImageRef
var time : Float64
}
var generator : AVAssetImageGenerator!
var captureAry : [Capture]!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
if let path = NSBundle.mainBundle().URLForResource("IMG_0727", withExtension: "mp4") {
do {
let avAsset = AVURLAsset(URL: path, options: nil)
// assetから画像をキャプチャーする為のジュネレーターを生成.
generator = AVAssetImageGenerator(asset: avAsset)
let runningTime = Int64(CMTimeGetSeconds(avAsset.duration))
let time : CMTime = CMTimeMake(runningTime, 10)
var capturedTime : CMTime = kCMTimeZero
captureAry = []
for _ in 0...9 {
let capturedImage : CGImageRef! = try! generator.copyCGImageAtTime(capturedTime, actualTime: nil)
let capture = Capture(picture: capturedImage, time: CMTimeGetSeconds(capturedTime))
captureAry.append(capture)
capturedTime = CMTimeAdd(capturedTime, time)
}
}
}
}
セルを選択された際はstroyBoardでsegueを使う場合は以下のとおり
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
NSLog("segue")
let index : NSIndexPath = (self.collectionView?.indexPathForCell(sender as! UICollectionViewCell))!
let capture = captureAry[index.row]
let value : UInt64 = UInt64(capture.time*100)
NSUserDefaults.standardUserDefaults().setObject(NSNumber(unsignedLongLong: value), forKey: "time")
NSUserDefaults.standardUserDefaults().synchronize()
}
後はセルを選択された際に呼び出すDetailViewを作ればOK
import Foundation
import AVKit
import AVFoundation
class PlayerViewController: AVPlayerViewController {
override func viewDidLoad() {
super.viewDidLoad()
let item : Int64 = Int64(NSUserDefaults.standardUserDefaults().objectForKey("time") as! Int)
//let time = item * Int64(1)
let seektime = CMTimeMake(item, 100)
NSLog("%f", CMTimeGetSeconds(seektime))
if let url = NSBundle.mainBundle().URLForResource("IMG_0727", withExtension: "mp4") {
do {
player = AVPlayer(URL: url)
player?.seekToTime(seektime, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)
}
} else {
fatalError("error")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidAppear(animated: Bool) {
player?.play()
}
}
これでとりあえず動くものが出来ます。これをより汎用的に作り直すのは次回。
参考
UICollectionViewを実装する[swift&xcode6]
UICollectionViewの使い方だけでなく、選択されたデータの遷移方法としてNSUserDefaultsを使っているのも参考にさせて頂きました。
005 動画から静止画を取り出す
キャプター画像を作るやり方はこのページを参照
AVFoundation プログラミングガイド
選択されたセルの背景色を変えるとか・・・それ以外にも少しずつ。