1. assign vs weak, __block vs __weak
- strong 和 weak 是在arc后引入的关键字,strong类似于retain,引用时候会引用计算+1,weak相反,不会改变引用计数。
- weak和assign都是引用计算不变,两个的差别在于,weak用于object type,就是指针类型,而assign用于简单的数据类型,如int BOOL 等。
assign看起来跟weak一样,其实不能混用的,assign的变量在释放后并不设置为nil(和weak不同),当你再去引用时候就会发生错误,崩溃,EXC_BAD_ACCESS.- block 不能修改局部变量,如果需要修改需要加上__block.
block 会对对象强引用,引起retain-cycle,需要使用__weak
在block种使用weakSelf可避免这种强引用(两个指针,指向同一块地址(self))。
2. 如何用GCD同步若干个异步调用
- 必须是并发队列才起作用
- 需求分析
- 首先,分别异步执行2个耗时的操作
- 其次,等2个异步操作都执行完毕后,再回到主线程执行一些操作
使用队列组实现上面的需求
- 使用队列组实现上面的需求
// 创建队列组
dispatch_group_t group = dispatch_group_create();
// 获取全局并发队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 往队列组中添加耗时操作
dispatch_group_async(group, queue, ^{ // 执行耗时的异步操作1 });
dispatch_group_async(group, queue, ^{ // 执行耗时的异步操作2 });
// 当并发队列组中的任务执行完毕后才会执行这里的代码
dispatch_group_notify(group, queue, ^{
// 如果这里还有基于上面两个任务的结果继续执行一些代码,建议还是放到子线程中,等代码执行完毕后在回到主线程
// 回到主线程
dispatch_async(group, dispatch_get_main_queue(), ^{
// 执行相关代码...
});
});
3. 分类中添加属性
利用runtime实现setter、getter方法
@interface ClassName (CategoryName)
@property (nonatomic, strong) NSString *str;
@end
//实现文件
#import "ClassName + CategoryName.h"
#import <objc/runtime.h>
static void *strKey = &strKey;
@implementation ClassName (CategoryName)
-(void)setStr:(NSString *)str
{
objc_setAssociatedObject(self, & strKey, str, OBJC_ASSOCIATION_COPY);
}
-(NSString *)str
{
return objc_getAssociatedObject(self, &strKey);
}
@end
6. isKindOfClass和isMemberOfClass的区别
isKindOfClass来确定一个对象是否是一个类的成员,或者是派生自该类的成员
isMemberOfClass只能确定一个对象是否是当前类的成员
7. block里面的如何防止retain cycle
使用弱引用打断block里面的retain cycle
- MRC中 block 是不会引起retain;
- 但在ARC中 _block 则会引起retain。ARC中应该使用 _weak __或__unsafe_unretained弱引用
7. __block 在MRC、ARC环境下的作用
MRC 1. 说明变量可改 2.说明指针指向的对象不做这个隐式的retain操作
ARC 1. 说明变量可改
9. load和initialize的区别
| load | initialize | |
|---|---|---|
| 执行时机 | 程序运行后立即执行 | 在类的方法第一次被调用时执行 |
| 自身未定义时 | 不沿用父类的 | 沿用父类的 |
| 类别中的定义 | 全部执行,但后于类中的方法 | 覆盖类中的方法,只执行一个 |
8. 基本算法
二分查找 θ(logn)
递归方法
int binarySearch1(int a[] , int low , int high , int findNum)
{
int mid = ( low + high ) / 2;
if (low > high) {
return -1;
}
else {
if (a[mid] > findNum)
return binarySearch1(a, low, mid - 1, findNum);
else if (a[mid] < findNum)
return binarySearch1(a, mid + 1, high, findNum);
else
return mid;
}
}
非递归方法
int binarySearch2(int a[] , int low , int high , int findNum)
{
while (low <= high)
{
int mid = ( low + high) / 2; //此处一定要放在while里面
if (a[mid] < findNum)
low = mid + 1;
else if (a[mid] > findNum)
high = mid - 1;
else
return mid;
}
return -1;
}
冒泡排序 θ(n^2)
void bubble_sort(int a[], int n)
{
int i, j, temp;
for (j = 0; j < n - 1; j++)
for (i = 0; i < n - 1 - j; i++) //外层循环每循环一次就能确定出一个泡泡(最大或者最小),所以内层循环不用再计算已经排好的部分
{
if(a[i] > a[i + 1])
{
temp = a[i];
a[i] = a[i + 1];
a[i + 1] = temp;
}
}
}
快速排序 调用方法 quickSort(a,0,n); θ(nlogn)
void quickSort (int a[] , int low , int high)
{
if (high < low + 2)
return;
int start = low;
int end = high;
int temp;
while (start < end)
{
while ( ++start < high && a[start] <= a[low]);//找到第一个比a[low]数值大的位子start
while ( --end > low && a[end] >= a[low]);//找到第一个比a[low]数值小的位子end
//进行到此,a[end] < a[low] < a[start],但是物理位置上还是low < start < end,因此接下来交换a[start]和a[end],于是[low,start]这个区间里面全部比a[low]小的,[end,hight]这个区间里面全部都是比a[low]大的
if (start < end)
{
temp = a[start];
a[start]=a[end];
a[end]=temp;
}
//在GCC编译器下,该写法无法达到交换的目的,a[start] ^= a[end] ^= a[start] ^= a[end];编译器的问题
}
//进行到此,[low,end]区间里面的数都比a[low]小的,[end,higt]区间里面都是比a[low]大的,把a[low]放到中间即可
//在GCC编译器下,该写法无法达到交换的目的,a[low] ^= a[end] ^= a[low] ^= a[end];编译器的问题
temp = a[low];
a[low]=a[end];
a[end]=temp;
//现在就分成了3段了,由最初的a[low]枢纽分开的
quickSort(a, low, end);
quickSort(a, start, high);
}









网友评论