前言:
前段时间项目需要做一个自定义的相册,分别显示图片和视频,并且可以局域网传输,由此我做了这么一个相册,这是纯UI部分,配合一个本地的FTP服务器进行传输。
代码列表:
屏幕快照 2018-04-11 14.25.08.png~首先~获取数据~Source~
Part 1、导入需要的库
import Photos
Part 2、建立数据类
enum SourceType: String {//文件类型
case image = "image"
case video = "video"
}
//这里许多是没有用的,我这里是都列出来了,自行取舍
class AlbumInfo {//文件类
var id: Int? //文件的id,唯一标识
var name: String? //文件名称
var imageData: Data?
var thumbnail: UIImage? //缩略图
var info: [AnyHashable : Any]? //这里面获取的value都只能做字符串使用
var video: AVAsset?
var url: URL? //只有video的URL是可以用的
var path: String? //只能做字符串使用
var mix: AVAudioMix?
var sourceType: SourceType?
var isSelect: Bool? //是否被选中
init(_ id: Int?,
_ name: String?,
_ imageData: Data?,
_ thumbnail: UIImage?,
_ info: [AnyHashable : Any]?,
_ video: AVAsset?,
_ url: URL?,
_ path: String?,
_ mix: AVAudioMix?,
_ sourceType: SourceType?) {
self.id = id
self.name = name
self.imageData = imageData
self.thumbnail = thumbnail
self.info = info
self.video = video
self.url = url
self.path = path
self.mix = mix
self.sourceType = sourceType
self.isSelect = false
}
func isEqual(_ other: AlbumInfo) -> Bool {//比较是否一样
return self.id == other.id && self.thumbnail == other.thumbnail
}
//info里包含的key值,
static let key_id = "PHImageResultRequestIDKey"
static let key_url = "PHImageFileURLKey"
static let key_path = "PHImageFileSandboxExtensionTokenKey"
}
Part 3、相册资源
final class AlbumSource {
static let share = AlbumSource()
init() {
self.step()
}
//资源结果
var imagesSource: [AlbumInfo]?
var videosSource: [AlbumInfo]?
func getAlbumSource() {
self.getImageSet()
self.getVideoSet()
}
//缩略图大小
private var thumbnail: CGSize = CGSize(width: 50, height: 50)
//图片管理(带缓存)
private let manager = PHCachingImageManager()
//所有系统的智能相册
private var sys_Options: PHFetchOptions!
//所有用户创建的相册
private var user_Options: PHFetchResult<PHCollection>!
private func step() {
self.sys_Options = PHFetchOptions()
self.sys_Options.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
//user_Options没有用到
self.user_Options = PHCollectionList.fetchTopLevelUserCollections(with: nil)
}
private func getImageSet() {
// guard !AlbumSource.isAuthorized() else {
// print("没有权限")
// return
// }
//获取图片
self.sys_Options.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.image.rawValue)
let result: PHFetchResult = PHAsset.fetchAssets(with: .image, options: PHFetchOptions())
guard result.count > 0 else {return}
var images: [AlbumInfo] = []
for i in 0..<result.count {
self.manager.requestImageData(for: result[i], options: nil, resultHandler: {[weak self] (data, text, orientation, info) in
guard let sself = self else {return}
// print("================", data, text, orientation, info)
let id = sself.analysisInfoId(with: info)
let thum = UIImage(data: data!)?.resize(toSize: sself.thumbnail)
let url = sself.getImageUrl(with: info)
let path = sself.getSourcePath(info)
let name = sself.getName(path)
images.append(AlbumInfo(id, name, data, thum, info, nil, url, path, nil, .image))
sself.imagesSource = images
})
}
self.manager.stopCachingImagesForAllAssets()
}
private func getVideoSet() {
//获取视频
self.sys_Options.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.video.rawValue)
let result: PHFetchResult = PHAsset.fetchAssets(with: .video, options: PHFetchOptions())
guard result.count > 0 else {return}
var videos: [AlbumInfo] = []
for i in 0..<result.count {
self.manager.requestAVAsset(forVideo: result[i], options: nil) {[weak self] (asset, mix, info) in
guard let sself = self else {return}
// print("asset:", asset, "mix:", mix, "info:", info)
let id = sself.analysisInfoId(with: info)
let image = AlbumSource.getAVAssetImage(asset)
let url = sself.getVideoUrl(asset)
let path = sself.getSourcePath(info)
let name = sself.getName(path)
videos.append(AlbumInfo(id, name, nil, image, info, asset, url, path, mix, .video))
sself.videosSource = videos
}
}
self.manager.stopCachingImagesForAllAssets()
}
//获取path和url
private func getVideoUrl(_ asset: AVAsset?) -> URL? {
guard let urlAsset = asset as? AVURLAsset else {return nil}
return urlAsset.url
}
private func getImageUrl(with sourceInfo: [AnyHashable : Any]?) -> URL? {
guard let info = sourceInfo as? [String : Any] else {return nil}
if let url = info[AlbumInfo.key_url] as? URL {
return url
}
return nil
}
private func getSourcePath(_ info: [AnyHashable : Any]?) -> String? {
guard let info = info as? [String : Any] else {return nil}
if let value = info[AlbumInfo.key_path] as? String {
let array = value.components(separatedBy: ";")
if array.count > 0 {
for string in array {
if string.first == "/" {
return "file://" + string
}
}
}
}
return nil
}
//PHImageResultRequestIDKey ==== id 图片标识
private func analysisInfoId(with sourceInfo: [AnyHashable : Any]?) -> Int? {
guard let info = sourceInfo as? [String : Any] else {return nil}
if let id = info[AlbumInfo.key_id] as? Int {
return id
}
return nil
}
//判断是否授权
class func isAuthorized() -> Bool {
return PHPhotoLibrary.authorizationStatus() == .authorized ||
PHPhotoLibrary.authorizationStatus() == .notDetermined
}
//获取视频截图(默认:开始)
class func getAVAssetImage(_ video: AVAsset?,
_ time: CMTime? = CMTimeMakeWithSeconds(0.0,600)) -> UIImage? {
guard let asset = video else {return nil}
let generator = AVAssetImageGenerator(asset: asset)
var actualTime:CMTime = CMTimeMake(0,0)
do{
let cgimage: CGImage = try generator.copyCGImage(at: time!, actualTime: &actualTime)
return UIImage(cgImage: cgimage)
}catch {
print(error)
}
return nil
}
//获取文件名称
func getName(_ path: String?) -> String? {
if let p = path {
return p.components(separatedBy: "/").last
}
return nil
}
}
其中,user_Options没有用到,如果有需要的,可以自行解决。
网友评论