forked from truongminhthang/CodeSnippets
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path51B687E1-A036-47EC-9893-67D4C78FFD76.codesnippet
315 lines (257 loc) · 13.2 KB
/
51B687E1-A036-47EC-9893-67D4C78FFD76.codesnippet
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDECodeSnippetCompletionScopes</key>
<array>
<string>StringOrComment</string>
</array>
<key>IDECodeSnippetContents</key>
<string>//
// AssetGridViewController.swift
// PhotoLib
//
// Created by Admin on 5/3/16.
// Copyright © 2016 Admin. All rights reserved.
//
import UIKit
import Photos
import PhotosUI
private let reuseIdentifier = "AssetCollectionViewCell"
class AssetGridViewController: UICollectionViewController {
@IBOutlet var addButton: UIBarButtonItem!
var assetsFetchResults : PHFetchResult!
var assetCollection : PHAssetCollection!
var imageManager : PHCachingImageManager!
/*
Một đối tượng PHCachingImageManager lấy về hoặc tạo ra các dữ liệu cho các nội dung hình ảnh hoặc video. Để đạt hiệu quả về mặt hiệu năng khi làm việc với nhiều nội dung. Một bộ quản lý hình ảnh bộ nhớ đẹm (PHCachingImageManager) có thể chuẩn bị những hình ảnh ở background theo thứ tự để loại bỏ sự chậm trễ khi bạn yêu cầu những ảnh riêng biệt. Ví dụ, khi bạn muốn duyệt một collectionView hoặc một UI đơn giản với ảnh thumbnails của các nội dung photo và video
*/
var previousPreheatRect : CGRect!
private let kMinInteritemSpacing : CGFloat = 0
private let kMinimumLineSpacing : CGFloat = 0
private let kEdgeInset = UIEdgeInsets(top: 4, left: 0, bottom: 0, right: 0)
private var isPortrait : Bool = true
private var numberOfItemInRow : CGFloat {
return isPortrait ? 4 : 6
}
private var itemSize : CGSize {
let width = UIScreen.mainScreen().bounds.width
let itemWidth = (width - kEdgeInset.left - kEdgeInset.right - (numberOfItemInRow - 1) * kMinInteritemSpacing ) / numberOfItemInRow
let itemHeight = itemWidth
return CGSize(width: itemWidth, height: itemHeight)
}
private var assetGridThumbnailSize : CGSize {
let scale = UIScreen.mainScreen().scale
return itemSize * scale
}
override func awakeFromNib() {
assert(assetsFetchResults == nil, "assetFetchResults phải có trước khi sử dụng")
imageManager = PHCachingImageManager()
resetCachedAssets()
PHPhotoLibrary.sharedPhotoLibrary().registerChangeObserver(self)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(deviceDidRotate), name: UIDeviceOrientationDidChangeNotification, object: nil)
}
func deviceDidRotate(notification: NSNotification) {
let orientation = UIDevice.currentDevice().orientation
if orientation == UIDeviceOrientation.Portrait || orientation == UIDeviceOrientation.PortraitUpsideDown {
isPortrait = true
collectionView?.reloadData()
} else {
isPortrait = false
collectionView?.reloadData()
}
}
deinit {
PHPhotoLibrary.sharedPhotoLibrary().unregisterChangeObserver(self)
NSNotificationCenter.defaultCenter().removeObserver(self)
}
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
if (assetCollection == nil) || assetCollection.canPerformEditOperation(PHCollectionEditOperation.AddContent) {
navigationItem.rightBarButtonItem = addButton
} else {
navigationItem.rightBarButtonItem = nil
}
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
updateCachedAssets()
}
func resetCachedAssets() {
imageManager.stopCachingImagesForAllAssets()
previousPreheatRect = CGRectZero
}
func updateCachedAssets() {
let isViewVisible = isViewLoaded() && view.window == nil
guard isViewVisible else {
return
}
var collectionViewBounds = self.collectionView?.bounds ?? CGRectZero
let preheatRect = CGRectInset(collectionViewBounds, 0 , -0.5 * collectionViewBounds.height)
let delta = abs(CGRectGetMidY(preheatRect) - CGRectGetMidY(previousPreheatRect))
if delta > collectionViewBounds.height / 3.0 {
var addedIndexPaths : [NSIndexPath] = []
var removedIndexPaths : [NSIndexPath] = []
computeDifferenceBetweenRect(previousPreheatRect, andRect: preheatRect, removedHandler: {
(removedRect) in
let indexpaths = self.collectionView!.mt_getIndexPathsForElementsInRect(removedRect)
removedIndexPaths += indexpaths
}, addedHandler: { (addedRect) in
let indexPaths = self.collectionView!.mt_getIndexPathsForElementsInRect(addedRect)
addedIndexPaths += indexPaths
})
let assetToStartCaching = getAssetsAtIndexPaths(addedIndexPaths)
let assetToStopCaching = getAssetsAtIndexPaths(removedIndexPaths)
imageManager.startCachingImagesForAssets(assetToStartCaching, targetSize: assetGridThumbnailSize, contentMode: PHImageContentMode.AspectFill, options: nil)
imageManager.stopCachingImagesForAssets(assetToStopCaching, targetSize: assetGridThumbnailSize, contentMode: PHImageContentMode.AspectFill, options: nil)
self.previousPreheatRect = preheatRect;
}
}
func getAssetsAtIndexPaths (indexPaths: [NSIndexPath]) -> [PHAsset] {
guard indexPaths.count != 0 else {
return []
}
var assets : [PHAsset] = []
for indexPath in indexPaths {
let asset = self.assetsFetchResults[indexPath.item] as! PHAsset
assets.append(asset)
}
return assets;
}
func computeDifferenceBetweenRect (oldRect: CGRect, andRect newRect: CGRect, removedHandler: (removedRect: CGRect) -> Void, addedHandler: (addedRect: CGRect) -> Void) {
if (CGRectIntersectsRect(newRect, oldRect)) {
let oldMaxY = CGRectGetMaxY(oldRect)
let oldMinY = CGRectGetMinY(oldRect)
let newMaxY = CGRectGetMaxY(newRect)
let newMinY = CGRectGetMinY(newRect)
if (newMaxY > oldMaxY) {
let rectToAdd = CGRectMake(newRect.origin.x, oldMaxY, newRect.size.width, (newMaxY - oldMaxY));
addedHandler(addedRect: rectToAdd);
}
if (oldMinY > newMinY) {
let rectToAdd = CGRectMake(newRect.origin.x, newMinY, newRect.size.width, (oldMinY - newMinY));
addedHandler(addedRect: rectToAdd);
}
if (newMaxY < oldMaxY) {
let rectToRemove = CGRectMake(newRect.origin.x, newMaxY, newRect.size.width, (oldMaxY - newMaxY));
removedHandler(removedRect: rectToRemove);
}
if (oldMinY < newMinY) {
let rectToRemove = CGRectMake(newRect.origin.x, oldMinY, newRect.size.width, (newMinY - oldMinY));
removedHandler(removedRect: rectToRemove);
}
} else {
addedHandler(addedRect: newRect);
removedHandler(removedRect: oldRect);
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
// MARK: UICollectionViewDataSource
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of items
return assetsFetchResults.count
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let asset = assetsFetchResults[indexPath.item] as! PHAsset
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! AssetCollectionViewCell
cell.representedAssetIdentifier = asset.localIdentifier
if asset.mediaType == .Video {
cell.livePhotoBadgeImage = UIImage(named: "video_call")
}
if asset.mediaSubtypes == .PhotoLive {
let bagdeImage = PHLivePhotoView.livePhotoBadgeImageWithOptions(PHLivePhotoBadgeOptions.OverContent)
cell.livePhotoBadgeImage = bagdeImage
}
// request an image for the asset from the PHCachingImageManager
imageManager.requestImageForAsset(asset, targetSize: assetGridThumbnailSize, contentMode: PHImageContentMode.AspectFill , options: nil) { (result, info) in
if cell.representedAssetIdentifier == asset.localIdentifier {
cell.thumbnailImage = result
}
}
return cell
}
}
// MARK: - UIScrollViewDelegate
extension AssetGridViewController {
override func scrollViewDidZoom(scrollView: UIScrollView) {
updateCachedAssets()
}
}
// MARK: - UICollectionViewDelegateFlowLayout
extension AssetGridViewController: UICollectionViewDelegateFlowLayout {
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {
return kEdgeInset
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return itemSize
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat {
return kMinInteritemSpacing
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
return kMinimumLineSpacing
}
}
// MARK: - PHPhotoLibraryChangeObserver
extension AssetGridViewController: PHPhotoLibraryChangeObserver {
func photoLibraryDidChange(changeInstance: PHChange) {
let collectionChanges: PHFetchResultChangeDetails! = changeInstance.changeDetailsForFetchResult(self.assetsFetchResults)
guard collectionChanges != nil else {
return
}
dispatch_async(dispatch_get_main_queue()) {
self.assetsFetchResults = collectionChanges.fetchResultAfterChanges
weak var collectionview = self.collectionView
if (!collectionChanges.hasIncrementalChanges||collectionChanges.hasMoves) {
collectionview!.reloadData()
} else {
/*
Thông báo với collectionView để hoạt hình hóa việc thêm và xóa nếu chúng ta có những sự thay đổi
*/
collectionview!.performBatchUpdates({
if let removedIndexes = collectionChanges.removedIndexes where removedIndexes.count > 0 {
collectionview!.deleteItemsAtIndexPaths(removedIndexes.getIndexPathsFromIndexesWithSection(0))
}
if let insertedIndexes = collectionChanges.insertedIndexes where insertedIndexes.count > 0 {
collectionview!.insertItemsAtIndexPaths(insertedIndexes.getIndexPathsFromIndexesWithSection(0))
}
if let changedIndexes = collectionChanges.changedIndexes where changedIndexes.count > 0 {
collectionview!.reloadItemsAtIndexPaths(changedIndexes.getIndexPathsFromIndexesWithSection(0))
}
}, completion: nil)
}
self.resetCachedAssets()
}
}
}
func * (left: CGSize, right: CGFloat) -> CGSize {
return CGSize (width: left.width * right , height: left.height * right)
}</string>
<key>IDECodeSnippetIdentifier</key>
<string>51B687E1-A036-47EC-9893-67D4C78FFD76</string>
<key>IDECodeSnippetLanguage</key>
<string>Xcode.SourceCodeLanguage.Swift</string>
<key>IDECodeSnippetTitle</key>
<string>Swift: Gallary photos</string>
<key>IDECodeSnippetUserSnippet</key>
<true/>
<key>IDECodeSnippetVersion</key>
<integer>2</integer>
</dict>
</plist>