再談PhotoKit

PhotoKit作為iOS8新推出的照片庫(kù)命斧,相比較于之前的ALAssetsLibrary確實(shí)解決了不少問題辩块,那么結(jié)合我最近的使用,也借鑒了"TZImagePickerController"滞伟、"CTAssetsPickerController"等流行的開源框架腺阳,以及官方的SwiftDemo,來講講幾個(gè)難以察覺的點(diǎn)于置。

內(nèi)存問題

自定義相冊(cè)基本思路都是拿UICollectionView來展示各種列表茧吊,那么內(nèi)存主要就存在于對(duì)照片縮略圖的獲取以及滑動(dòng)卡頓的問題,我們來看看TZImagePickerController俱两,

__block UIImage *image;
        // 修復(fù)獲取圖片時(shí)出現(xiàn)的瞬間內(nèi)存過高問題
        // 下面兩行代碼饱狂,來自hsjcom曹步,他的github是:https://github.com/hsjcom 表示感謝
        PHImageRequestOptions *option = [[PHImageRequestOptions alloc] init];
        option.resizeMode = PHImageRequestOptionsResizeModeFast;
        int32_t imageRequestID = [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:imageSize contentMode:PHImageContentModeAspectFill options:option resultHandler:^(UIImage *result, NSDictionary *info) {
            if (result) {
                image = result;
            }
            BOOL downloadFinined = (![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey]);
            if (downloadFinined && result) {
                result = [self fixOrientation:result];
                if (completion) completion(result,info,[[info objectForKey:PHImageResultIsDegradedKey] boolValue]);
            }
            // Download image from iCloud / 從iCloud下載圖片
            if ([info objectForKey:PHImageResultIsInCloudKey] && !result && networkAccessAllowed) {
                PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
                options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        if (progressHandler) {
                            progressHandler(progress, error, stop, info);
                        }
                    });
                };
                options.networkAccessAllowed = YES;
                options.resizeMode = PHImageRequestOptionsResizeModeFast;
                [[PHImageManager defaultManager] requestImageDataForAsset:asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
                    UIImage *resultImage = [UIImage imageWithData:imageData scale:0.1];
                    resultImage = [self scaleImage:resultImage toSize:imageSize];
                    if (!resultImage) {
                        resultImage = image;
                    }
                    resultImage = [self fixOrientation:resultImage];
                    if (completion) completion(resultImage,info,NO);
                }];
            }
        }];

注釋有提到修復(fù)了瞬間內(nèi)存過高宪彩,但測(cè)試發(fā)現(xiàn)iPad mini上快速滑動(dòng)依然會(huì)有內(nèi)存警告最終導(dǎo)致Crash。(CTAssetsPickerController同樣如此)這里PHImageRequestOptionsResizeModeFast設(shè)置讲婚,會(huì)有兩次結(jié)果回調(diào)尿孔,一次模糊,一次清晰(如果有的話)筹麸,一般來說沒什么問題活合。有說可以通過requestImageDataForAsset解決,沒錯(cuò)這種方式內(nèi)存占用確實(shí)要小不少物赶,但Data到Image這一步需要做不少處理吧白指,并沒有之前的API那么方便。我的結(jié)論是將contentMode改為PHImageContentModeAspectFit酵紫,同時(shí)盡量利用PHCachingImageManager來做緩存告嘲,這樣效果會(huì)好很多。

iCloud問題

目前的系統(tǒng)設(shè)置有幾個(gè)選項(xiàng)奖地,針對(duì)用戶開啟了iCloud照片庫(kù)橄唬,并且選擇了“優(yōu)化iPhone/iPad存儲(chǔ)空間”或者選擇了“下載并保留原件”但原件還未加載出來,也就是說資源不在本地参歹。PHImageRequestOptions或者PHVideoRequestOptions在開啟了PHVideoRequestOptions仰楚,會(huì)試圖從iCloud去下載資源,這時(shí)候耗時(shí)可能會(huì)很長(zhǎng)犬庇,另外也可能載入不成功僧界,這兩點(diǎn)都必須有嚴(yán)格的過度處理。這兩點(diǎn)在之前的兩個(gè)開源庫(kù)中都有體現(xiàn)臭挽。而在我們開發(fā)中捂襟,大部分可能都忽視了這一點(diǎn)。

相冊(cè)變更

這個(gè)主要是系統(tǒng)相冊(cè)的增刪埋哟,或者iCloud的更新對(duì)自定義相冊(cè)的影響笆豁。原本是參考官方Swif版本來進(jìn)行處理郎汪,沒想到坑就在這里,同時(shí)更新和刪除會(huì)Crash闯狱,官方Demo也不例外煞赢。主要是在performBatchUpdates這個(gè)地方。造成了線上好些崩潰記錄哄孤。目前的處理如下

    if (changes == nil) {
        return;
    }
    
    dispatch_async(dispatch_get_main_queue(), ^{
        
        self.allVideos = changes.fetchResultAfterChanges;
        
        UICollectionView *collectionView = self.collectionView;
        
        if (!changes.hasIncrementalChanges || changes.hasMoves)
        {
            [collectionView reloadData];
            [self fixupSelection];
            [self resetCachedAssets];
        }
        else
        {
            NSArray *removedPaths;
            NSArray *insertedPaths;
            NSArray *changedPaths;
            
            NSIndexSet *removedIndexes = changes.removedIndexes;
            removedPaths = [removedIndexes vk_assetGridIndexPathsFromIndexesWithSection:0];
            
            NSIndexSet *insertedIndexes = changes.insertedIndexes;
            insertedPaths = [insertedIndexes vk_assetGridIndexPathsFromIndexesWithSection:0];
            
            NSIndexSet *changedIndexes = changes.changedIndexes;
            changedPaths = [changedIndexes vk_assetGridIndexPathsFromIndexesWithSection:0];
            
            BOOL shouldReload = NO;
            
            if (changedPaths != nil && removedPaths != nil)
            {
                for (NSIndexPath *changedPath in changedPaths)
                {
                    if ([removedPaths containsObject:changedPath])
                    {
                        shouldReload = YES;
                        break;
                    }
                }
            }
            
            if (removedPaths.lastObject && ((NSIndexPath *)removedPaths.lastObject).item >= self.allVideos.count)
            {
                shouldReload = YES;
            }
            
            if (shouldReload)
            {
                [collectionView reloadData];
                [self fixupSelection];
            }
            else
            {
                [collectionView performBatchUpdates:^{
                    if (removedPaths.count)
                    {
                        [collectionView deleteItemsAtIndexPaths:[removedIndexes vk_assetGridIndexPathsFromIndexesWithSection:0]];
                    }
                    
                    if (insertedPaths.count)
                    {
                        [collectionView insertItemsAtIndexPaths:[insertedIndexes vk_assetGridIndexPathsFromIndexesWithSection:0]];
                    }
                    
                    if (changedPaths.count)
                    {
                        [collectionView reloadItemsAtIndexPaths:[changedIndexes vk_assetGridIndexPathsFromIndexesWithSection:0] ];
                    }
                } completion:^(BOOL finished){
                    if (finished) {
                        [self resetCachedAssets];
                        [self fixupSelection];
                    }
                }];
            }
        }
        
        [self.emptyView setHidden:self.allVideos.count > 0];
        
    });

視頻封面截取幀

封面要求截取9張圖片照筑,之前有通過循環(huán)一次性截取9張圖片,但這個(gè)操作有些耗時(shí)瘦陈,看到系統(tǒng)有AVAssetImageGenerator凝危,所以采用了這種方案。但這個(gè)API有一個(gè)問題晨逝,傳入的Times數(shù)組是9個(gè)值蛾默,回調(diào)時(shí)并不一定給你回調(diào)9次,有可能更多捉貌,所以在回調(diào)時(shí)候最好做一些邊界處理支鸡。

以上就是這次使用遇到的一系列問題。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末趁窃,一起剝皮案震驚了整個(gè)濱河市牧挣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌醒陆,老刑警劉巖瀑构,帶你破解...
    沈念sama閱讀 221,548評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異刨摩,居然都是意外死亡寺晌,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門码邻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來折剃,“玉大人,你說我怎么就攤上這事像屋∨吕纾” “怎么了?”我有些...
    開封第一講書人閱讀 167,990評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵己莺,是天一觀的道長(zhǎng)奏甫。 經(jīng)常有香客問我,道長(zhǎng)凌受,這世上最難降的妖魔是什么阵子? 我笑而不...
    開封第一講書人閱讀 59,618評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮胜蛉,結(jié)果婚禮上挠进,老公的妹妹穿的比我還像新娘色乾。我一直安慰自己,他們只是感情好领突,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評(píng)論 6 397
  • 文/花漫 我一把揭開白布暖璧。 她就那樣靜靜地躺著,像睡著了一般君旦。 火紅的嫁衣襯著肌膚如雪澎办。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,246評(píng)論 1 308
  • 那天金砍,我揣著相機(jī)與錄音局蚀,去河邊找鬼。 笑死恕稠,一個(gè)胖子當(dāng)著我的面吹牛琅绅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播谱俭,決...
    沈念sama閱讀 40,819評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼奉件,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼宵蛀!你這毒婦竟也來了昆著?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,725評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤术陶,失蹤者是張志新(化名)和其女友劉穎凑懂,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體梧宫,經(jīng)...
    沈念sama閱讀 46,268評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡接谨,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了塘匣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片脓豪。...
    茶點(diǎn)故事閱讀 40,488評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖忌卤,靈堂內(nèi)的尸體忽然破棺而出扫夜,到底是詐尸還是另有隱情,我是刑警寧澤驰徊,帶...
    沈念sama閱讀 36,181評(píng)論 5 350
  • 正文 年R本政府宣布笤闯,位于F島的核電站,受9級(jí)特大地震影響棍厂,放射性物質(zhì)發(fā)生泄漏颗味。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評(píng)論 3 333
  • 文/蒙蒙 一牺弹、第九天 我趴在偏房一處隱蔽的房頂上張望浦马。 院中可真熱鬧时呀,春花似錦、人聲如沸晶默。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)荤胁。三九已至瞧预,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間仅政,已是汗流浹背垢油。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留圆丹,地道東北人滩愁。 一個(gè)月前我還...
    沈念sama閱讀 48,897評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像辫封,于是被迫代替她去往敵國(guó)和親硝枉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 1倦微、通過CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫(kù)組件 SD...
    陽(yáng)明先生_X自主閱讀 15,988評(píng)論 3 119
  • (七) 一條道路延伸到遠(yuǎn)方妻味,又消失在遠(yuǎn)方來往的人影和車輛之中,使得我看不清楚它的盡頭欣福。車輛來來往往责球,人們走走停停,...
    說魚之樂閱讀 344評(píng)論 0 0
  • 一條生活館 客服與訂單 福慶叔叔 明前龍井 | 不施農(nóng)藥化肥的杭州午潮山自然茶園 ¥369.00 ¥ 需要幫助拓劝?立...
    山丘工作室閱讀 286評(píng)論 0 0
  • 曹禺在【雷雨.序】 中寫的話: 我念起人類是怎樣可憐的動(dòng)物雏逾,帶著躊躇滿志的心情仿佛自己來主宰自己的...
    暗夜攖寧閱讀 412評(píng)論 0 0
  • 自己生活了三十幾年,但又目標(biāo)的活著的時(shí)候應(yīng)該不超過一年郑临,或者說沒有被別人逼著自己往前走的時(shí)候而有目標(biāo)往前走時(shí)應(yīng)該不...
    你好3306閱讀 203評(píng)論 0 0