内卷吧! iOS开发君 -答案

当前的答案只是我自己的理解.(标题党来了).
完整答案请找👇🏻

题目出处
作者:Cooci_和谐学习_不急不躁
链接:https://www.jianshu.com/p/ec75262fc316
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

一、选择题(每题5分)

LGTeacher 继承于 LGPerson, 下面代码输出为什么 () 分值5分

LGTeacher *t = [[LGTeacher alloc] init];

- (instancetype)init{
    self = [super init];
    if (self) {
        NSLog(@"%@ - %@",[self class],[super class]);
    }
    return self;
}

A: LGTeacher - LGTeacher

B: LGTeacher - LGPerson

C: LGTeacher - NSObject

D: LGTeacher - 它爱输出啥就输出啥,我不清楚


A [super class] 只是从父类开始找. 接受者还是self


下面代码能否正常执行以及输出 () 分值5分

@interface LGPerson : NSObject
@property (nonatomic, retain) NSString *kc_name;
- (void)saySomething;
@end

@implementation LGPerson
- (void)saySomething{ 
    NSLog(@"%s - %@",__func__,self.kc_name);
}
@end
- (void)viewDidLoad {
    [super viewDidLoad] ;
    
    Class cls = [LGPerson class];
    void  *kc = &cls;
    [(__bridge id)kc saySomething];
}

A: 能 - ViewController

B: 能 - null

C: 能 - ViewController: 0x7ff8d240ad30

D: 能不能自己运行一下不就知道,非要问我 - 它爱输出啥就输出啥,我不清楚


C 假设有一个LGPerson 的实例对象的内存结构是
isa 8
kc_name 8
第一句获取到类对象. 然后 kc = &cls .可以理解为kc 是一个isa指针指向了LGPerson 的类对象.

调用实例方法.打印kc_name. 也就是 *kc 接下去的8个字符.所代表的是什么.打印的就是什么. 所以应该是C


下面代码执行,控制台输出结果是什么 () 分值5分

NSObject *objc = [NSObject new];
NSLog(@"a:%ld",CFGetRetainCount((__bridge CFTypeRef)(objc)));

void(^block1)(void) = ^{
    NSLog(@"b:%ld",CFGetRetainCount((__bridge CFTypeRef)(objc)));
};
block1();

void(^__weak block2)(void) = ^{
    NSLog(@"c:%ld",CFGetRetainCount((__bridge CFTypeRef)(objc)));
};
block2();

void(^block3)(void) = [block2 copy];
block3();

__block NSObject *obj = [NSObject new];
void(^block4)(void) = ^{
    NSLog(@"d:%ld",CFGetRetainCount((__bridge CFTypeRef)(obj)));
};
block4();

A: 1 2 2 2 2

B: 1 2 3 3 2

C: 1 3 3 4 1

D: 1 3 4 5 1


答案是D

a是1.
block1 执行下面的时候.

void(^block1)(void) = ^{
    NSLog(@"---%ld",CFGetRetainCount((__bridge CFTypeRef)(objc)));
};

//会生成结构体
struct __main_block_impl_0 {
           struct __block_impl impl;
           struct __main_block_desc_0* Desc;
           NSObject *__strong objc; 引用计数 +1
           __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, NSObject *__strong _objc, int flags=0) : objc(_objc) {
             impl.isa = &_NSConcreteStackBlock;
             impl.Flags = flags;
             impl.FuncPtr = fp;
             Desc = desc;
           }
         };
         
struct __block_impl {
  void *isa;
  int Flags;
  int Reserved;
  void *FuncPtr; // 方法的具体实现
};

在arc环境下.会自动给block 进行copy 操作.所以 b : 3

block2 执行

void(^__weak block2)(void) = ^{
    NSLog(@"c:%ld",CFGetRetainCount((__bridge CFTypeRef)(objc)));
};
block2();

跟b一样.生成strong指针指向objc +1.因为使用__weak 修饰.所以不会自动做copy操作. c:4

block3 执行

void(^block3)(void) = [block2 copy];
block3();

直接进行copy 操作 +1 . c 在打印一次 5

block4 执行

__block NSObject *obj = [NSObject new];
void(^block4)(void) = ^{
    NSLog(@"d:%ld",CFGetRetainCount((__bridge CFTypeRef)(obj)));
};
block4();

//会将obj 直接转成block结构体
struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  __Block_byref_obj_0 *obj; // by ref
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_obj_0 *_obj, int flags=0) : obj(_obj->__forwarding) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

struct __Block_byref_obj_0 {
  void *__isa;
__Block_byref_obj_0 *__forwarding;
 int __flags;
 int __size;
 void (*__Block_byref_id_object_copy)(void*, void*);
 void (*__Block_byref_id_object_dispose)(void*);
 NSObject *__strong obj; //数据存储在这里
};

// main调用变成
int main(int argc, const char * argv[]) {
        //会将对象转成block结构体的对象
         __Block_byref_obj_0 obj = {(void*)0,
             (__Block_byref_obj_0 *)&obj,
             33554432,
             sizeof(__Block_byref_obj_0),
             __Block_byref_id_object_copy_131,
             __Block_byref_id_object_dispose_131,
             ((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSObject"), sel_registerName("new"))
         };
        void(*block4)(void) = &__main_block_impl_0(__main_block_func_0,
                                                   &__main_block_desc_0_DATA,
                                                   (__Block_byref_obj_0 *)&obj,
                                                   570425344));
        ((__block_impl *))((__block_impl *)block4)->FuncPtr)((__block_impl *)block4);
    }
    return 0;
}

会将对象转成block 的对象.所以d : 1


下面代码执行,控制台输出结果是什么 () 分值5分

- (void)MTDemo{
    while (self.num < 5) {
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            self.num++;
        });
    }
    NSLog(@"KC : %d",self.num);
}

- (void)KSDemo{
   
    for (int i= 0; i<10000; i++) {
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            self.num++;
        });
    }
    NSLog(@"Cooci : %d",self.num);
}

A: 0 , 10000

B: 0 , <10000

C: <=5 , <10000

D: >=5 , <10000


D


下面代码执行,控制台输出结果是什么 () 分值5分

- (void)textDemo2{
    dispatch_queue_t queue = dispatch_queue_create("cooci", DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"1");
    dispatch_async(queue, ^{
        NSLog(@"2");
        dispatch_sync(queue, ^{
            NSLog(@"3");
        });
        NSLog(@"4");
    });
    NSLog(@"5");
}

- (void)textDemo1{
    
    dispatch_queue_t queue = dispatch_queue_create("cooci", NULL);
    NSLog(@"1");
    dispatch_async(queue, ^{
        NSLog(@"2");
        dispatch_sync(queue, ^{
            NSLog(@"3");
        });
        NSLog(@"4");
    });
    NSLog(@"5");
}

A: 1 5 2 3 4 , 1 5 2

B: 1 5 2 4 3 , 死锁奔溃

C: 1 5 2 3 4 , 死锁奔溃

D: 1 5 2 3 , 死锁奔溃


C 15234 152死锁
题目问的是终端打印什么 .所以应该是A (手动捂脸)


下面代码执行,控制台输出结果是什么 () 分值5分

@property (nonatomic, strong) NSMutableArray      *mArray;

- (NSMutableArray *)mArray{
    if (!_mArray) _mArray = [NSMutableArray arrayWithCapacity:1];
    return _mArray;
}
- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSMutableArray *arr = [NSMutableArray arrayWithObjects:@"1",@"2", nil];
    self.mArray = arr;

    void (^kcBlock)(void) = ^{
        [arr addObject:@"3"];
        [self.mArray addObject:@"a"];
        NSLog(@"KC %@",arr);
        NSLog(@"Cooci: %@",self.mArray);
    };
    [arr addObject:@"4"];
    [self.mArray addObject:@"5"];
    
    arr = nil;
    self.mArray = nil;
    
    kcBlock();
}

A: 1 2 4 5 3 , nil

B: 1 2 4 5 3 , a

C: 1 2 4 5 3 , 1 2 4 5 3 a

D: 1 2 4 5 3 a , 1 2 4 5 3 a


B


二、判断题 (每题5分)

可变数组线程是安全 () 分值5分




主队列搭配同步函数就会产生死锁 () 分值5分




下面代码执行不会报错 () 分值5分

int a = 0;
void(^ __weak weakBlock)(void) = ^{
    NSLog(@"-----%d", a);
};

struct _LGBlock *blc = (__bridge struct _LGBlock *)weakBlock;
id __strong strongBlock = [weakBlock copy];
blc->invoke = nil;
void(^strongBlock1)(void) = strongBlock;
strongBlock1();




下面代码执行不会报错 () 分值5分

NSObject *a = [NSObject alloc];
void(^__weak block1)(void) = nil;
{
    void(^block2)(void) = ^{
        NSLog(@"---%@", a);
    };
    block1 = block2;
    NSLog(@"1 - %@ - %@",block1,block2);
}
block1();



错.会报错


下面代码会产生循环引用 () 分值5分

__weak typeof(self) weakSelf = self;
self.doWork = ^{
    __strong typeof(self) strongSelf = weakSelf;
    weakSelf.doStudent = ^{
        NSLog(@"%@", strongSelf);
    };
   weakSelf.doStudent();
};
self.doWork();



会产生循环引用


下面代码是否有问题 () 分值5分

- (void)demo3{
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(0, 0);
    
    for (int i = 0; i<5000; i++) {
        dispatch_async(concurrentQueue, ^{
            NSString *imageName = [NSString stringWithFormat:@"%d.jpg", (i % 10)];
            NSURL *url = [[NSBundle mainBundle] URLForResource:imageName withExtension:nil];
            NSData *data = [NSData dataWithContentsOfURL:url];
            UIImage *image = [UIImage imageWithData:data];
            
            dispatch_barrier_async(concurrentQueue, ^{
                [self.mArray addObject:image];
            });

        });
    }
}



对.有问题.
dispatch_barrier_async 没有效果.在全局并发队列 barrier 无法生效


下面代码不会产生循环引用 () 分值5分

static ViewController *staticSelf_;

- (void)blockWeak_static {
    __weak typeof(self) weakSelf = self;
    staticSelf_ = weakSelf;
}



不会


三、简单题 (每题 10分 合计 120分)

请把它当成一场面试,认真对待 希望大家耐心 切忌浮躁 (和谐学习 不急不躁)

1、请用GCD实现读写锁 , 解释为什么这么设计 分值10分

其实就是多读单写.使用自己创建的并发队列.然后使用barrier进行写入的操作.就好.

2、@synchronized 为什么应用频次最多 分值10分

最根本原因肯定是因为写法简单粗暴.
本质是一个递归锁.

3、block 的种类有几种 是符合区分的? 分值10分

global 全局
malloc 堆
stack 栈

4、KVC 普通对象 setter 过程 分值10分

5、KVO 底层原理机制分析 分值10分

创建当前类的子类.然后将当前类的isa 指向子类.重写监听的对象的set 方法

willchanggevalueforkey
super set
didchangevalueforkey

6、下面代码的栈帧入栈情况是什么的? 分值10分

- (void)viewDidLoad { 
    [super viewDidLoad] ; 
    
    
    Class cls = [LGPersonP class];
    void  *kc = &cls;
    [(__bridge id)kc saySomething]; 
    
    LGPersonP *person = [LGPersonP alloc];
}
  • LGPersonP
  • Viewcontroller : 内存地址
  • 其他接下去的地址

7、iOS 线程如何保活, 为什么要线程保活 分值10分

线程如何保活.通过给runloop 添加source0/source1/timer/observer 都可以.一般的做法就是给source1添加一个port.然后在当前线程进行run.
为什么线程保活: 主要是考虑业务上的问题.用空间换时间.比如网络请求.可能需要频繁的进行网络请求.这时候.我们创建一个子线程.然后需要用的时候.直接调用就行

8、循环引用,为什么要在block中加strong,不加会怎样 分值10分

保证在block运行的时候.内部的对象不要释放

9、你使用过 dispatch_once 吗?了解底层吗?让你实现一个应该怎么操作? 分值10分

10、iOS 多线程原理和线程生命周期是什么样的 分值10分

11、请简述信号量和调度组的原理 分值10分

12、请简述 __block 修饰变量被 block 捕获之后的情况 分值10分

被__block修饰的对象.最后本质会变成一个X_block_impl_X结构体.

四、拓展满分题 (15分)

作为一名iOS中高级开发人员, 你的加分项和优势是什么?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容