1、weak的底层实现
Runtime维护了一个weak表,用于存储指向某个对象的所有weak指针。
weak表其实是一个hash(哈希)表,
Key是所指对象的地址,Value是weak指针的地址(这个地址的值是所指对象的地址)数组。
weak 的实现原理可以概括一下三步:
1、初始化时:
runtime会调用objc_initWeak函数,初始化一个新的weak指针指向对象的地址。
2、添加引用时:
objc_initWeak函数会调用 objc_storeWeak() 函数,
objc_storeWeak() 的作用是更新指针指向,创建对应的弱引用表。
3、释放时:
调用clearDeallocating函数。
clearDeallocating函数首先根据对象地址获取所有weak指针地址的数组,
然后遍历这个数组把其中的数据设为nil,
最后把这个entry从weak表中删除,最后清理对象的记录。
http://www.cocoachina.com/ios/20170328/18962.html
2、autoreleasepool
Tagged Pointer
伪对象,小于10位数的数字,值直接存放在指针中,解决64位系统,内存占用问题
类函数方法返回对象为unretained return value,生命周期被延长,不一定会使用 autorelease
http://www.cocoachina.com/ios/20170303/18829.html
3、dispatch_onec synchronized nonatomic atomic
synchronized 递归互斥锁
dispatch_onec 原子性 信号量完成线程同步 参数要是静态全局参数
atomic 自旋锁 循环等待直到解锁 自旋锁效率高于互斥锁
https://www.jianshu.com/p/ef3f77c8b320
4、copy mutableCopy
不可变对象
copy 浅拷贝 内存地址不变 结果对象不可变 只改变指针地址
mutableCopy 深拷贝 内存地址变化 结果为可变
可变对象
copy mutableCopy 都为深拷贝 内存地址变化
容器类对象,copy mutableCopy 内部对象地址不变
copy修饰属性时 不管声明类型为什么 赋值后都变成不可变
自定义对象 实现copy 要重写 copyWithZone
[[NSMutableArray alloc] initWithArray:arr1 copyItems:YES] 元素深拷贝
http://www.cocoachina.com/ios/20170601/19402.html
5、hit-test 响应链
1、扩大UIButton的响应热区
重载UIButton的-(BOOL)pointInside: withEvent:方法,让Point即使落在Button的Frame外围也返回YES
2、子view超出了父view的bounds响应事件
重载父view的-(UIView *)hitTest: withEvent:方法,去掉点击必须在父view内的判断,
然后子view就能成为 hit-test view,用于响应事件
https://www.jianshu.com/p/d8512dff2b3e
6、多线程
http://www.360doc.com/content/15/0618/17/19663521_479024177.shtml
http://www.cocoachina.com/ios/20180313/22573.html
7、单项链表
1、判断环,找出节点
*********************************************************************
* 函数名称:linklist *IsLoop(linklist *head)
* 函数功能:判断链表是否含有环,并找出环的入口
* 参 数:head----链表的头结点
* 返 回 值:若有环,则返回链表中环的入口结点;否则返回NULL
* 说 明:程序参考定理:碰撞点p到连接点的距离=头指针到连接点的距离
*********************************************************************
extern linklist *IsLoop(linklist *head)
{
linklist *p1=head, *p2=head;
int IsLoopFlag=0;
if (head==NULL)
return NULL;
while (p2->next!=NULL && p2->next->next!=NULL)
{
p1 = p1->next;
p2 = p2->next->next;
if (p1==p2)
{
IsLoopFlag = 1;
break;
}
}
if (!IsLoopFlag)
return NULL;
else
{
// p2指向头结点,p1在第一次相遇点。
// 之后利用定理,当p1再次等于p2时,相遇点即为环的入口结点
p2 = head;
while (p1!=p2)
{
p1 = p1->next;
p2 = p2->next;
}
return p1;
}
}
2、反转
迭代:
linkList reverse(linkList head) {
linkList p,q,pr;
p = head->next;
q = NULL;
head->next = NULL;
while(p) {
pr = p->next;
p->next = q;
q = p;
p = pr;
}
head->next = q;
return head;
}
Node * Node_reverse_v2(Node* node) {
if (node == NULL) return NULL;
if (node->next == NULL) return node;
Node *first = node; //总是指向新链表的首部。
Node *now = node->next;
Node *next = now->next;
first->next = NULL; //首节点变成尾节点,尾节点的下一个节点置空,防止环路。
do {
next = now->next;
now->next = first;
first = now;
now = next;
} while (next != NULL);
return first;
}
递归:
Node * Node_reverse(Node *node) {
if (node == NULL) return NULL;
if (node->next == NULL) return node;
Node * n = Node_reverse(node->next);
if (n != NULL) {
n->next = node;
node->next = NULL;
}
return node;
}
8、Bounds Frame
frame 针对父视坐标系图计算
bounds 针对自身坐标系,改变bounds的x、y,影响子视图位置
scrollView 滚动和边距原理,都是改变bounds的,x、y
改变bounds的大小,参照点是center,frame随之改变
https://blog.csdn.net/chenyufeng1991/article/details/51764303
9、锁 性能
1、OSSpinLock 自旋锁,最快,消耗大量 CPU 资源
不绝对安全,线程高低优先级,造成优先级反转
2、dispatch_semaphore pthread_mutex 性能好
3、synchronized 慢
http://www.cocoachina.com/ios/20160707/16957.html
https://blog.ibireme.com/2016/01/16/spinlock_is_unsafe_in_ios/
10、setValue和setObject的区别
1、 setObject:forkey:中value是不能够为nil的,不然会报错。
setValue:forKey:中value能够为nil,但是当value为nil的时候,会自动调用removeObject:forKey方法
2、setValue:forKey:中key的参数只能够是NSString类型,而setObject:forKey:的可以是任何类型
https://blog.csdn.net/itianyi/article/details/8661997
11、NSArray NSMutableArray 线程安全
NSMutableArray本身是线程不安全的,NSArray安全
不使用atomic修饰属性
1 、atomic 的内存管理语义是原子性的,仅保证了属性的setter和getter方法是原子性的,是线程安全的,但是属性的其他方法,
如数组添加/移除元素等并不是原子操作,所以不能保证属性是线程安全的。
2 、atomic虽然保证了getter、setter方法线程安全,但是付出的代价很大,执行效率要比nonatomic慢很多倍(有说法是慢10-20倍)
3、使用nonatomic修饰NSMutableArray对象就可以了,而使用锁、dispatch_queue来保证NSMutableArray对象的线程安全
实现:GCD用同步并行队列读操作,barrier(按照插入队列顺序,执行完才执行后边)写操作
https://blog.csdn.net/kangguang/article/details/79194563
12、算法 两个升序数组找相同元素
- (NSArray *)sameFromTwoArray:(NSArray *)arr1 array2:(NSArray *)arr2 {
NSMutableArray *resultArr = [NSMutableArray array];
for (int i=0, j=0; i<arr1.count && j< arr2.count;) {
if (arr1[i] == arr2[j]) {
[resultArr addObject:arr1[i]];
i++;
j++
} else if (arr1[i] > arr2[j]) {
j++;
} else {
i++;
}
}
return resultArr;
}
13、二分查找
int binarySearch(int arr[], int len, int key)
{
int left = 0;
int right = len - 1;
int mid;
while (left <= right) {
mid = (left + right) / 2;
if (key < arr[mid]) {//key在左边
right = mid - 1;
} else if (arr[mid] < key) {//key在右边
left = mid + 1;
} else {
return mid;
}
}
return -1;
}
https://www.cnblogs.com/bofengyu/p/6761389.html
14、_ _block _ _weak
1.__block不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型。
2.__weak只能在ARC模式下使用,也只能修饰对象(NSString),不能修饰基本数据类型(int)。
3.__block对象可以在block中被重新赋值,__weak不可以。
4.__block对象在ARC下可能会导致循环引用,非ARC下会避免循环引用,__weak只在ARC下使用,可以避免循环引用,
__block避免循环引用需要在block内部把__block修饰的obj置为nil
5.__weak 本身是可以避免循环引用的问题的,但是其会导致外部对象释放了之后,
block内部也访问不到这个对象的问题,可以通过在 block 内部声明一个__strong 的变量来指向 weakObj,
使外部对象既能在 block 内部保持住,又能避免循环引用的问题
https://www.cnblogs.com/xu-antong/p/6503344.html
https://www.cnblogs.com/yajunLi/p/6203222.html?utm_source=itdadao&utm_medium=referral