內(nèi)存優(yōu)化

為什么要減少內(nèi)存

更好的用戶體驗橘蜜,增加app流暢性剩蟀,更快的啟動速度并思,不會因為內(nèi)存過大而Crash兴喂,即便進入后臺也會活得更久

查看內(nèi)存占用高的對象或內(nèi)存飆升的操作針對性進行優(yōu)化

借助工具如圖
Persistent:該對象存在于內(nèi)存中的個數(shù)
Transient:存在過已經(jīng)被回收的對象的個數(shù)
Persistent Byte:該類對象在內(nèi)存中占得總內(nèi)存
也可以進行搜索 也可對單類對象進行分析 具體使用可搜索詳細使用教程


image.png
海量json數(shù)據(jù)處理

先說網(wǎng)絡請求执桌,多數(shù)像我一樣的野生程序員都會使用有名的第三方庫,比如AFNetworking奸笤、Alamofire, (因為我們寫的不夠好痕檬,我們多數(shù)時間都在造輪子、模仿輪子歹苦、實現(xiàn)功能青伤,可能內(nèi)存優(yōu)化的很多事情都跟我們沒有關(guān)系,因為我們根本用不到殴瘦。)通常我們會對第三方庫進行一層包裝狠角、對我們應用程序來說可以隨時替換、減少與第三庫的耦合度蚪腋。 然后開始發(fā)起請求->拿到數(shù)據(jù)json解析->數(shù)據(jù)發(fā)送到M層丰歌、M層進行model轉(zhuǎn)換->數(shù)據(jù)發(fā)送到C、C通知V數(shù)據(jù)更新屉凯,仿佛一連串的事情沒問題立帖,像我一樣。

/**
 POST請求
 只是一個簡簡單單的封裝悠砚、實現(xiàn)里將AF的結(jié)果通過block回調(diào)
 @param control viewController 對象
 @param parameters 請求參數(shù)
 @param completeBlock 成功
 @return 請求hash值
 */
+ (NSNumber *)PostWithControl:(NSObject *)control parameters:(NSDictionary *)parameters completeHandler:(IZQResponseBlock)completeBlock;
[IZQAPIClient PostWithControl:self parameters:[IZQInterfaceList updateTaskContentOfModel:_md] completeHandler:^(NSNumber *requestID, id data, BOOL success) {
            // do something 
           // 數(shù)據(jù)賦值
          // 刷新UI
}];

除網(wǎng)絡請求外一切的操作都在主線程晓勇。當遇上海量數(shù)據(jù),內(nèi)存飆升灌旧,(5W條60key值)json解析內(nèi)存增加150M绑咱,在讀取json中的key 拿到list 數(shù)據(jù)在次飆升、數(shù)據(jù)傳遞枢泰、遍歷描融、轉(zhuǎn)model數(shù)據(jù)會一份一份的復制,在主線程的runloop中它沒有時間釋放衡蚂、可以飚到300M 500M

解決:

多線程處理 數(shù)據(jù)處理放在子線程中去操作
1窿克、可以利用多核CPU骏庸、數(shù)據(jù)處理速度增加
2、數(shù)據(jù)處理完成只發(fā)出有效數(shù)據(jù)让歼、臨時變量敞恋、臨時指針都會被及時釋放。
3谋右、對于更多的數(shù)據(jù)可與服務器配合分段更新硬猫、分段處理
自動釋放池
關(guān)于自動釋放池看這篇文章AutoreleasePool

圖片內(nèi)存優(yōu)化

1、加載圖片資源方式
不常用的圖片 一次性渲染顯示的圖片 contentsOfFile 直接讀取渲染 不常駐內(nèi)存
對于常用的圖片 比如cell 中的小圖標 named

加載圖片 不會常駐內(nèi)存
let image = UIImage(contentsOfFile: url.path)
加載圖片到內(nèi)存 會常駐內(nèi)存 named 可以增加渲染速度 避免影響卡頓
let image = UIImage(named: name)!

2改执、圖片尺寸大小
資源圖片應該有他正確的大小啸蜜、避免小View加載大圖片,比直接加載大圖還要吃內(nèi)存辈挂。
網(wǎng)絡圖片要服務器配合返回適中的圖片衬横,雖然App可以將圖片尺寸大小進行壓縮,還是要盡量減少圖片轉(zhuǎn)換帶來的時間消耗终蒂、內(nèi)存消耗
3蜂林、適當時機清理緩存
比如SDWebImage 在app進入后臺、收到內(nèi)存警告等或需要釋放圖片的時機 clearMemory拇泣,清除圖片在內(nèi)存中的占用噪叙。設置大圖片不常駐緩存,比如特大原圖霉翔,要及時釋放內(nèi)存睁蕾。
4、圖片壓縮
這也使用最多的一種方式 例如在圖片上傳前重繪壓縮在上傳 主要是去掉一些不必要的參數(shù) 改變圖片尺寸大小

- (UIImage*)scaleToSize:(UIImage*)img size:(CGSize)size
{
    // 創(chuàng)建一個bitmap的context
    // 并把它設置成為當前正在使用的context
    UIGraphicsBeginImageContext(size);
    // 繪制改變大小的圖片
    [img drawInRect:CGRectMake(0, 0, size.width, size.height)];
    // 從當前context中創(chuàng)建一個改變大小后的圖片
    UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();
    // 使當前的context出堆棧
    UIGraphicsEndImageContext();
    // 返回新的改變大小后的圖片
    return scaledImage;
}

iOS10新增UIGraphicsImageRenderer來代替UIGraphicsBeginImageContext
UIGraphicsImageRenderer官方文檔的解釋:一個支持創(chuàng)建核心圖像的渲染器债朵。

//繪制UIImage
- (UIImage*)resiImage:(NSURL*)url size:(CGSize)size{
    UIImage *testIm = [UIImage imageWithContentsOfFile:url.path];
    UIGraphicsImageRenderer *re = [[UIGraphicsImageRenderer alloc]initWithSize:size];
    return [re imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull rendererContext) {
        [testIm drawInRect:CGRectMake(0, 0, size.width, size.height)];
    }];
}

5子眶、使用ImageIO加載大圖
蘋果給出的新方法

    func downsample(imageAt imageURL: URL, to pointSize: CGSize, scale: CGFloat) -> UIImage
    {
        let sourceOpt = [kCGImageSourceShouldCache : false] as CFDictionary
        // 其他場景可以用createwithdata (data并未decode,所占內(nèi)存沒那么大),
        let source = CGImageSourceCreateWithURL(imageURL as CFURL, sourceOpt)!
        
        let maxDimension = max(pointSize.width, pointSize.height) * scale
        let downsampleOpt = [kCGImageSourceCreateThumbnailFromImageAlways : true,
                             kCGImageSourceShouldCacheImmediately : true ,
                             kCGImageSourceCreateThumbnailWithTransform : true,
                             kCGImageSourceThumbnailMaxPixelSize : maxDimension] as CFDictionary
        let downsampleImage = CGImageSourceCreateThumbnailAtIndex(source, 0, downsampleOpt)!
        return UIImage(cgImage: downsampleImage)
    }
內(nèi)存泄漏

內(nèi)存管理 誰創(chuàng)建誰釋放 誰添加誰釋放 現(xiàn)在都使用ARC 引用計數(shù)由系統(tǒng)自動管理
內(nèi)存泄漏幾個主要原因
1、你中有我 我中有你 循環(huán)引用 使用[weak self]解決
2序芦、Timer未釋放 未設置失效時間 未置為nil timer中循環(huán)引用
3臭杰、常駐對象中強引用某對象 delegate強持有
4、C語言創(chuàng)建的對象未手動釋放
5谚中、網(wǎng)絡請求對self的強持有(延遲釋放)
6硅卢、子線程死鎖 資源不釋放
排查方法
使用Instrument工具 Leaks
MLeaksFinder 具體使用看介紹

UI

1、懶加載藏杖,延遲創(chuàng)建對象,需要的時候才創(chuàng)建節(jié)省內(nèi)存開銷
2脉顿、UI復用蝌麸,避免浪費節(jié)約開銷
3、Cell中不要臨時創(chuàng)建對象艾疟、更不要在循環(huán)中創(chuàng)建臨時對象
4来吩、對于經(jīng)常訪問的大頁面可以強引用 或 單例模式 避免重復的創(chuàng)建釋放創(chuàng)建釋放
5敢辩、圓角可以圖片重繪、CALayer重繪
6弟疆、隱藏顯示戚长、添加移除看需求選擇使用
7、宗旨:需要的時候創(chuàng)建 能重用的盡量重用 不需要的不創(chuàng)建

CoreData

CoreData中批零插入數(shù)據(jù)怠苔,在key值較多情況下 插入一條保存一條會比較慢同廉,等插入完成之后再保存會造成大量對象一直未釋放,內(nèi)存增加 我的數(shù)據(jù)有5萬條 每條60+key 每100條一保存會慢幾秒 內(nèi)存較低 每1000-5000保存一次內(nèi)存增加不多柑司,時間與完全插入在保存相當迫肖,上萬條插入在保存內(nèi)存會驟增,速度相對較快 海量數(shù)據(jù)應該在合適的時機選擇保存一次 避免達到內(nèi)存峰值 也可使系統(tǒng)更流暢

    func insertPersons(persons: [Any])  {
        let semaphore =  DispatchSemaphore(value: 0)
        persistentContainer.performBackgroundTask { [weak self](context) in
            for item in 0..<persons.count {
                //            print(item)
                let person: IZQPerson = NSEntityDescription.insertNewObject(forEntityName: "IZQPerson", into: context) as! IZQPerson
                person.mapping(map: persons[item] as! [String : Any])
                if item%5000 == 0 && item > 0 {
                    self?.saveContext(context: context)
                }
            }
            self?.saveContext(context: context)
            print(NSPersistentContainer.defaultDirectoryURL())
            print("插入完成", Date.init().timeIntervalSince1970)
            semaphore.signal()
        }
        semaphore.wait()
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末攒驰,一起剝皮案震驚了整個濱河市蟆湖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌玻粪,老刑警劉巖隅津,帶你破解...
    沈念sama閱讀 212,599評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異劲室,居然都是意外死亡伦仍,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評論 3 385
  • 文/潘曉璐 我一進店門痹籍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來呢铆,“玉大人,你說我怎么就攤上這事蹲缠」卓耍” “怎么了?”我有些...
    開封第一講書人閱讀 158,084評論 0 348
  • 文/不壞的土叔 我叫張陵线定,是天一觀的道長娜谊。 經(jīng)常有香客問我,道長斤讥,這世上最難降的妖魔是什么纱皆? 我笑而不...
    開封第一講書人閱讀 56,708評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮芭商,結(jié)果婚禮上派草,老公的妹妹穿的比我還像新娘。我一直安慰自己铛楣,他們只是感情好近迁,可當我...
    茶點故事閱讀 65,813評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著簸州,像睡著了一般鉴竭。 火紅的嫁衣襯著肌膚如雪歧譬。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,021評論 1 291
  • 那天搏存,我揣著相機與錄音瑰步,去河邊找鬼。 笑死璧眠,一個胖子當著我的面吹牛缩焦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蛆橡,決...
    沈念sama閱讀 39,120評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼舌界,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了泰演?” 一聲冷哼從身側(cè)響起呻拌,我...
    開封第一講書人閱讀 37,866評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎睦焕,沒想到半個月后藐握,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,308評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡垃喊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,633評論 2 327
  • 正文 我和宋清朗相戀三年猾普,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片本谜。...
    茶點故事閱讀 38,768評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡初家,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出乌助,到底是詐尸還是另有隱情溜在,我是刑警寧澤,帶...
    沈念sama閱讀 34,461評論 4 333
  • 正文 年R本政府宣布他托,位于F島的核電站掖肋,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏赏参。R本人自食惡果不足惜志笼,卻給世界環(huán)境...
    茶點故事閱讀 40,094評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望把篓。 院中可真熱鬧纫溃,春花似錦、人聲如沸韧掩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,850評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至郎楼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間窒悔,已是汗流浹背呜袁。 一陣腳步聲響...
    開封第一講書人閱讀 32,082評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留简珠,地道東北人阶界。 一個月前我還...
    沈念sama閱讀 46,571評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像聋庵,于是被迫代替她去往敵國和親膘融。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,666評論 2 350