iOS随笔
获取CPU占用量
#import <mach/mach.h> kern_return_t kr; thread_array_t thread_list; mach_msg_type_number_t thread_count; thread_info_data_t thinfo; mach_msg_type_number_t thread_info_count; thread_basic_info_t basic_info_th; // get threads in the task // 获取当前进程中 线程列表 kr = task_threads(mach_task_self(), &thread_list, &thread_count); float tot_cpu = 0; for (int j = 0; j < thread_count; j++) { thread_info_count = THREAD_INFO_MAX; //获取每一个线程信息 kr = thread_info(thread_list[j], THREAD_BASIC_INFO, (thread_info_t)thinfo, &thread_info_count); basic_info_th = (thread_basic_info_t)thinfo; if (!(basic_info_th->flags & TH_FLAGS_IDLE)) { // cpu_usage : Scaled cpu usage percentage. The scale factor is TH_USAGE_SCALE. //宏定义TH_USAGE_SCALE返回CPU处理总频率: tot_cpu += basic_info_th->cpu_usage / (float)TH_USAGE_SCALE; } } // 注意方法最后要调用 vm_deallocate,防止出现内存泄漏 kr = vm_deallocate(mach_task_self(), (vm_offset_t)thread_list, thread_count *sizeof(thread_t)); return tot_cpu;
内存占用
task_vm_info_data_t vmInfo; mach_msg_type_number_t count = TASK_VM_INFO_COUNT; kern_return_t kernelReturn = task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &vmInfo, &count); int64_t memoryUsageInByte = (int64_t) vmInfo.phys_footprint; return (NSInteger)(memoryUsageInByte/1024/1024);
@property
sythesize:自动生成setter和getter方法,且可指定名称的成员变量
dynamic: 需手动生成setter和getter方法
KVC底层实现原理
1、首先搜索setKey:方法.(key指成员变量名, 首字母大写)
2、上面的setter方法没找到, 如果类方法accessInstanceVariablesDirectly返回YES. 那么按 _key, _isKey,key, iskey的顺序搜索成员名.(NSKeyValueCodingCatogery中实现的类方法, 默认实现为返回YES)
3、如果没有找到成员变量, 调用setValue:forUnderfinedKey:
GET&POST
对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);
而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。
UIScrollView滚动:
向上滚动scrollview,我们就不断增加scrollview的bounds的y值,也就是不断把scrollview的本地坐标系原点向下偏移(相对于scrollview的父view的坐标系,y值越大,越向下偏移)。那么此时scrollview的子控件的frame设置的(0,0)就是不断向上偏移
开发证书签名加密过程:
主要涉及以下几个关键步骤:
生成密钥对(生成电脑本地公钥, 私钥在电脑keychain中)
• 开发者使用钥匙串访问工具在本地生成一对密钥,即公钥和私钥。私钥会被安全地存储在开发者的本地设备钥匙串中,公钥则用于后续的证书申请等操作。
获取证书(用apple私钥加密 电脑公钥, 生成证书)
• 开发者在苹果开发者中心创建证书请求,将公钥等信息包含在证书请求文件(.certSigningRequest)中上传。苹果服务器验证开发者身份等信息后,用苹果的根证书私钥对开发者的公钥等信息进行签名,生成开发证书,其中包含开发者公钥、证书有效期、证书用途等信息。
签名过程(用电脑本地私钥加密ipa文件,哈希,再加密)
• 当开发者使用Xcode构建并归档应用时,Xcode会使用开发者的私钥对应用中的可执行文件、资源等进行签名。计算这些内容的哈希值,再用私钥对哈希值进行加密,生成签名数据,将签名数据与应用程序包一起存储。
验证过程(用apple公钥解密证书文件,获取电脑本地公钥,用公钥解密验证ipa包)
• 设备在安装和运行应用时,系统会获取应用的签名数据和开发者证书。用苹果根证书的公钥验证开发者证书的签名,确认证书是否由苹果颁发且未被篡改。
• 系统从开发者证书中获取开发者公钥,用此公钥解密应用的签名数据,得到原始的哈希值。同时,系统再次计算应用内可执行文件和资源的哈希值,将两个哈希值进行对比,若一致则说明应用未被篡改且来源可靠,可安全运行。
load & initialize
load:
当类被引用进项目的时候(类文件加载到系统中)就会执行load函数(在main函数开始执行之前),与这个类是否被用到无关,每个类的load函数只会自动调用一次.由于load函数是系统自动加载的,因此不需要调用父类的load函数,否则父类的load函数会多次执行。
- 1.当父类和子类都实现load函数时,父类的load方法执行顺序要优先于子类
- 2.当子类未实现load方法时,不会调用父类load方法
- 3.类中的load方法执行顺序要优先于类别(Category)
- 4.当有多个类别(Category)都实现了load方法,这几个load方法都会执行,但执行顺序不确定(其执行顺序与类别在Compile Sources中出现的顺序一致)
- 5.当然当有多个不同的类的时候,每个类load 执行顺序与其在Compile Sources出现的顺序一致
- 1.父类的initialize方法会比子类先执行
- 2.当子类未实现initialize方法时,会调用父类initialize方法,子类实现initialize方法时,会覆盖父类initialize方法.
- 3.当有多个Category都实现了initialize方法,会覆盖类中的方法,只执行一个(会执行Compile Sources 列表中最后一个Category 的initialize方法)
instrument:
Time Profiler:CPU分析工具分析代码的执行时间。
Core Animation:离屏渲染,图层混合等GPU耗时。
1、"Color Blended Layers":图层混合
2、"Color Hits Green and Misses Red":图层缓存
3、"Color Offscreen-Rendered Yellow":离屏渲染
Leaks:内存检测,内存泄漏检测工具。
Allocation: 内存分配情况
Zombie: 野指针检测
NSHashTable:
NSSet/NSMutableSet对其对象是强引用,使用isEqual方法去检查对象是否相等,使用方法hash去获取hash值。
NSHashTable是可变的,没有一个不变的和其对应。
NSHashTable可以对其对象是weak引用。当对象被销毁的时候自动将其从集合中移除。
NSHashTable可以在输入(加入)的时候copy对象。
NSHashTable可以包含任意指针,NSHashTableObjectPointerPersonality:和NSPointerFunctionsObjectPointerPersonality相同,此选项是直接使用指针进行isEqual:和hash。
NSMapTabel:
NSMapTable是可变的,没有一个不变的类与其对应。
NSMapTable可以对其key和value弱引用,在这种情况下当key或者value被释放的时候,此entry会自动从NSMapTable中移除。
NSMapTable在加入一个(key,value)的时候,可以对其value设置为copy。
yycache:
异步释放缓存对象:把对象捕获到 block 中,然后扔到后台队列去随便发送个消息以避免编译器警告,就可以让对象在后台线程销毁了。
锁的选择,memorycache使用互斥锁,diskCache使用信号量
使用 NSMapTable 单例管理的 YYDiskCache:
YYKVStorage 中的 _dbStmtCache:省去一些重复生成 sqlite3_stmt 的开销
甚至使用 CoreFoundation 来换取微乎其微的性能提升
memoryCache中使用双链表的结构存储数据,并用dictionary保证了查找速度
采用LRU来优化内存空间
diskCache中根据数据大小,对于大数据采用文件缓存,并将文件名存入到sql中。小数据直接存入到sql中
锁:
self.intSource = 0; dispatch_async(queue1, ^{ for (int i = 0; i < 10000; i++) { self.intSource = self.intSource + 1; } }); dispatch_async(queue2, ^{ for (int i = 0; i < 10000; i++) { self.intSource = self.intSource + 1; } });
if (obj) {
SyncData* data = id2data(obj, ACQUIRE);// 一个简单的Hash算法,然后将传入的对象地址,通过地址找到下标映射到不同的SyncList上。而SyncList是一个维护SyncData的链表,每个SyncList都单独维护操作自己的散列锁lock。
assert(data);
data->mutex.lock();
}
typedef struct SyncData {
struct SyncData* nextData;
DisguisedPtr<objc_object> object;
int32_t threadCount; // number of THREADS using this block
recursive_mutex_t mutex;// 一把递归锁
} SyncData;