仿猎豹垃圾清理(实现原理+源码)

2023-11-05 13:38

本文主要是介绍仿猎豹垃圾清理(实现原理+源码),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

转载请注明出处: 仿猎豹垃圾清理(实现原理+源码)


前几天无意打开猎豹内存大师, 发现它的垃圾清理很强大, 效果也不错, 闲着就研究了下。 不过.. 结果貌似和我想象的不太一样。怎么说呢, 听我下文一一分析。

效果图: 
 

从效果图, 我们可以看出它有以下几个功能:

  1. 获取设备上已安装的所有App
  2. 获取App的信息, 包括图标和名称
  3. 获取当前已用存储和可用存储
  4. 扫描App动画效果
  5. 清除所有App垃圾文件

看到这里, 你是不是也觉得很强大?

然后然后, 感叹的同时, 我有几点疑惑。

  1. 获取到所有已安装的App, 这个功能能通过审核?(我是去年在App Store上下载的这个App)
  2. App的图标如何获取到的? (因为扫描到的App包括我自己没上架的demo, icon只能是本地获取, 从其他App沙盒拿?)
  3. 垃圾清理过程, 为什么会出现“存储容量已满”这个提示? 明明是清理垃圾, 中途还会出现存储满的情况?

困惑, 不解..~ 于是乎, 折腾呗。 花了两天时间。写了个小demo。

效果如下:

接下去, 我会介绍以下各个功能的实现过程, 包括:

  1. 获取设备已安装App列表已经App信息
  2. 扫描动画的实现
  3. 获取已用存储和可用存储
  4. 垃圾清理

不过, 分析之前, 说明一下, 该功能不能够上传到App Store上! 也就是说, 它通不过审核的。 
原因有二: 
1. 使用了私有API 
2. 苹果不允许App有处理内存相关功能

至于猎豹内存大师这个App、它也早已经被下架了。我怀疑它利用混淆代码通过的审核。至于功能的实现, 我觉得和猎豹的实现思路应该是一样的。

至此, 如果你还对这篇文章感兴趣, 欢迎继续往下阅读。

本文参考源码: CSDN下载_防猎豹垃圾清理


获取设备已安装App列表已经App信息

不越狱, 非私有API

没有越狱的设备,官方没有提供api,所以只能用一些技巧,但是获取内容不全。

这里主要有两种办法:

方法一:利用URL scheme,看对于某一应用特有的url scheme,有没有响应。如果有响应,就说明安装了这个特定的app。

说实在.. 这个办法比较傻。 App Store几百万的App, 如何枚举的过来? 并且, 也无法扫描到自己的demo。 不过, 还真有人这么干.. 
这是对应的demo, 感兴趣可以看看。 iHasApp

官方教程: iPhoneURLScheme_Reference

方法二:利用一些方法获得当前正在运行的进程信息,从进程信息中获得安装的app信息。

参考: UIDevice_Category_For_Processes

总的来说, 不越狱, 非私有API, 想获得完整列表, 基本没什么可能。

不越狱, 私有API。

这里就是我demo所采用的办法, 比较简单。

<code class="language-objc hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <objc/runtime.h></span>Class LSApplicationWorkspace_class = objc_getClass(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"LSApplicationWorkspace"</span>);  
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSObject</span>* workspace = [LSApplicationWorkspace_class performSelector:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@selector</span>(defaultWorkspace)];  
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"apps: %@"</span>, [workspace performSelector:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@selector</span>(allApplications)]);  </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>

返回结果

<code class="language-objc hljs bash has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"LSApplicationProxy: com.qunar.iphoneclient8"</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"LSApplicationProxy: com.apple.mobilemail"</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"LSApplicationProxy: com.apple.mobilenotes"</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"LSApplicationProxy: com.apple.compass"</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"LSApplicationProxy: com.tencent.happymj"</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"LSApplicationProxy: com.apple.mobilesafari"</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"LSApplicationProxy: com.apple.reminders"</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>

返回的是个数据, 每个元素都是LSApplicationProxy.它的description只返回了 它的bundle id。然而这并不是我们想要的。

接下去我们看 
LSApplicationProxy.h

形如:

<code class="language-objc hljs r has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">@class LSApplicationProxy, NSArray, NSDictionary, NSProgress, NSString, NSURL, NSUUID;@interface LSApplicationProxy : LSResourceProxy <NSSecureCoding> {NSArray *_UIBackgroundModes;NSString *_applicationType;NSArray *_audioComponents;unsigned int _bundleFlags;NSURL *_bundleURL;NSString *_bundleVersion;NSArray *_directionsModes;NSDictionary *_entitlements;NSDictionary *_envi<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li></ul>

这里列举了LSApplicationProxy对应的属性和方法。

我们可以用如下代码, 打印下每个属性的值, 找出我们想要的。

<code class="language-objc hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>、<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 获取对象的所有属性 以及属性值 */</span>
- (<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSDictionary</span> *)properties_aps
{<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSMutableDictionary</span> *props = [<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSMutableDictionary</span> dictionary];   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">unsigned</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> outCount, i;   objc_property_t *properties = class_copyPropertyList([<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> class], &outCount);   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; i<outCount; i++){objc_property_t property = properties[i];<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span>* char_f =property_getName(property);<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> *propertyName = [<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> stringWithUTF8String:char_f];<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">id</span> propertyValue = [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> valueForKey:(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> *)propertyName];   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (propertyValue) [props setObject:propertyValue forKey:propertyName];   }   free(properties);   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> props;   
} </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li></ul>

参考: IOS 遍历未知对象的属性和方法

然后我们提取出我们需要的, 图标和应用名。

<code class="language-objc hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">[appsInfoArr enumerateObjectsUsingBlock:^(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">id</span> obj, NSUInteger idx, <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">BOOL</span> *stop){<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSDictionary</span> *boundIconsDictionary = [obj performSelector:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@selector</span>(boundIconsDictionary)];<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> *iconPath = [<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> stringWithFormat:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"%@/%@.png"</span>, [[obj performSelector:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@selector</span>(resourcesDirectoryURL)] path], [[[boundIconsDictionary objectForKey:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"CFBundlePrimaryIcon"</span>] objectForKey:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"CFBundleIconFiles"</span>]lastObject]];<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIImage</span> *image = [[[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIImage</span> alloc]initWithContentsOfFile:iconPath] TransformtoSize:CGSizeMake(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">65</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">65</span>)];<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (image){[<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.appsIconArr</span> addObject:image];[<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.appsNameArr</span> addObject:[obj performSelector:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@selector</span>(localizedName)]];}}];</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul>

如此, _self.appsIconArr 和 _appsNameArr中存储的就是我们需要的App数据了。

越狱

.. 这里我也不懂, 也没去研究。 感兴趣的可以看看 MobileInstallation.framework


扫描动画的实现

这里主要有两个动画。

  1. 利用UIScrollView, 实现每个App自动滚动。
  2. Animation动画, 中间扫描线的往返运动。

至于动画, 这里我不想介绍太多。 源码里面都写清楚了。(当然, 写的比较粗糙…)

简单带一下扫描线的动画实现:

<code class="language-objc hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 向左移动 */</span>CABasicAnimation *animationLeft = [CABasicAnimation animationWithKeyPath:<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">@"transform.translation.x"</span>];<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 动画选项的设定</span>animationLeft.duration = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.5</span>f; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 持续时间</span>animationLeft.beginTime = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.0</span>f;animationLeft.autoreverses = YES; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 结束后执行逆动画</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 动画先加速后减速</span>animationLeft.timingFunction =[CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseInEaseOut];<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 终了帧</span>animationLeft.toValue = [NSNumber numberWithFloat:-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">40</span>];;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 向右移动 */</span>CABasicAnimation *animationRight = [CABasicAnimation animationWithKeyPath:<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">@"transform.translation.x"</span>];<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 动画选项的设定</span>animationRight.duration = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.5</span>f; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 持续时间</span>animationRight.beginTime = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.0</span>f;animationRight.autoreverses = YES; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 结束后执行逆动画</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 动画先加速后减速</span>animationRight.timingFunction =[CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseInEaseOut];<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 终了帧</span>animationRight.toValue = [NSNumber numberWithFloat:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">40</span>];;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 动画组 */</span>CAAnimationGroup *<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">group</span> = [CAAnimationGroup animation];<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">group</span>.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">delegate</span> = self;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">group</span>.duration = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2.0</span>;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">group</span>.repeatCount = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">15</span>;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 动画结束后不变回初始状态</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">group</span>.removedOnCompletion = NO;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">group</span>.fillMode = kCAFillModeForwards;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 添加动画</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">group</span>.animations = [NSArray arrayWithObjects:animationLeft, animationRight, nil];[mySL.layer addAnimation:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">group</span> forKey:<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">@"moveLeft-moveRight-layer"</span>];
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li></ul>

获取已用存储和可用存储

这个没什么好说的了.. Apple提供了API, 直接用就是了。

<code class="language-objc hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 获取占用内存</span>
-(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)usedSpaceAndfreeSpace
{<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span>* path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">YES</span>) objectAtIndex:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>] ;<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSFileManager</span>* fileManager = [[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSFileManager</span> alloc ]init];<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSDictionary</span> *fileSysAttributes = [fileManager attributesOfFileSystemForPath:path error:<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>];<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSNumber</span> *freeSpace = [fileSysAttributes objectForKey:NSFileSystemFreeSize];<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSNumber</span> *totalSpace = [fileSysAttributes objectForKey:NSFileSystemSize];<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span>  * str= [<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> stringWithFormat:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"已占用%0.1f G / 剩余%0.1f MB"</span>,([totalSpace longLongValue] - [freeSpace longLongValue])/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1024.0</span>/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1024.0</span>/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1024.0</span>,[freeSpace longLongValue]/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1024.0</span>/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1024.0</span>];<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"--------%@"</span>,str);
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li></ul>

垃圾清理

这里我本来是不想提的,毕竟这个功能,苹果是不能接受的。

之前提到了, 猎豹在清理过程中, 会出现“存储已满的提示”。然后我开始考虑了。

  1. 为什么要弹出提示?
  2. 存储真的在某一刻满了吗?
  3. 它清理的时候, QQ直接被杀死, 应用名变成”正在清理…”(和安装中一个状态)。 真有这么厉害? !!!!!!
  4. 这个好像在哪里见过…

最后, 我确定了猎豹的实现方式。它只不过是触发了Apple自己的垃圾回收机制而已。

当存储满的时候, 系统会自动帮我们进行垃圾清理, 并弹出提示说明存储已满。

所以, 猎豹只不过是计算了剩余多少存储, 然后制造了一个与之差不多大小的垃圾文件。 然后触发苹果的清理机制。清理完后, 删除之前生成的垃圾文件。再次统计当前可用存储, 差值即为本次清理的垃圾大小。

是吧, 其实也没那么神~

至于如何快速制造几百M, 甚至几G的垃圾文件?

<code class="language-objc hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 将文件的长度设定为offset </span>-(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)truncateFileAtOffset:offset </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

truncateFileAtOffset:offset就能搞定了。 感兴趣的可以自己研究下。


至此, 猎豹垃圾清理分析完毕。

当然, 这只是我个人的看法。如果有更好的方式, 或者文章中存在任何错误。 欢迎交流指正。

这篇关于仿猎豹垃圾清理(实现原理+源码)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/350219

相关文章

MyBatis-Plus逻辑删除实现过程

《MyBatis-Plus逻辑删除实现过程》本文介绍了MyBatis-Plus如何实现逻辑删除功能,包括自动填充字段、配置与实现步骤、常见应用场景,并展示了如何使用remove方法进行逻辑删除,逻辑删... 目录1. 逻辑删除的必要性编程1.1 逻辑删除的定义1.2 逻辑删php除的优点1.3 适用场景2.

C#借助Spire.XLS for .NET实现在Excel中添加文档属性

《C#借助Spire.XLSfor.NET实现在Excel中添加文档属性》在日常的数据处理和项目管理中,Excel文档扮演着举足轻重的角色,本文将深入探讨如何在C#中借助强大的第三方库Spire.... 目录为什么需要程序化添加Excel文档属性使用Spire.XLS for .NET库实现文档属性管理Sp

Python+FFmpeg实现视频自动化处理的完整指南

《Python+FFmpeg实现视频自动化处理的完整指南》本文总结了一套在Python中使用subprocess.run调用FFmpeg进行视频自动化处理的解决方案,涵盖了跨平台硬件加速、中间素材处理... 目录一、 跨平台硬件加速:统一接口设计1. 核心映射逻辑2. python 实现代码二、 中间素材处

Java数组动态扩容的实现示例

《Java数组动态扩容的实现示例》本文主要介绍了Java数组动态扩容的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1 问题2 方法3 结语1 问题实现动态的给数组添加元素效果,实现对数组扩容,原始数组使用静态分配

Spring Boot Interceptor的原理、配置、顺序控制及与Filter的关键区别对比分析

《SpringBootInterceptor的原理、配置、顺序控制及与Filter的关键区别对比分析》本文主要介绍了SpringBoot中的拦截器(Interceptor)及其与过滤器(Filt... 目录前言一、核心功能二、拦截器的实现2.1 定义自定义拦截器2.2 注册拦截器三、多拦截器的执行顺序四、过

Python实现快速扫描目标主机的开放端口和服务

《Python实现快速扫描目标主机的开放端口和服务》这篇文章主要为大家详细介绍了如何使用Python编写一个功能强大的端口扫描器脚本,实现快速扫描目标主机的开放端口和服务,感兴趣的小伙伴可以了解下... 目录功能介绍场景应用1. 网络安全审计2. 系统管理维护3. 网络故障排查4. 合规性检查报错处理1.

Python轻松实现Word到Markdown的转换

《Python轻松实现Word到Markdown的转换》在文档管理、内容发布等场景中,将Word转换为Markdown格式是常见需求,本文将介绍如何使用FreeSpire.DocforPython实现... 目录一、工具简介二、核心转换实现1. 基础单文件转换2. 批量转换Word文件三、工具特性分析优点局

Springboot3统一返回类设计全过程(从问题到实现)

《Springboot3统一返回类设计全过程(从问题到实现)》文章介绍了如何在SpringBoot3中设计一个统一返回类,以实现前后端接口返回格式的一致性,该类包含状态码、描述信息、业务数据和时间戳,... 目录Spring Boot 3 统一返回类设计:从问题到实现一、核心需求:统一返回类要解决什么问题?

Java使用Spire.Doc for Java实现Word自动化插入图片

《Java使用Spire.DocforJava实现Word自动化插入图片》在日常工作中,Word文档是不可或缺的工具,而图片作为信息传达的重要载体,其在文档中的插入与布局显得尤为关键,下面我们就来... 目录1. Spire.Doc for Java库介绍与安装2. 使用特定的环绕方式插入图片3. 在指定位

Java使用Spire.Barcode for Java实现条形码生成与识别

《Java使用Spire.BarcodeforJava实现条形码生成与识别》在现代商业和技术领域,条形码无处不在,本教程将引导您深入了解如何在您的Java项目中利用Spire.Barcodefor... 目录1. Spire.Barcode for Java 简介与环境配置2. 使用 Spire.Barco