程序员ios进阶面试

2020年iOS面试总结

2020-02-27  本文已影响0人  七秒记忆的鱼儿

🌸絮:2020年到来了,随着疫情的到来,我也失业了。一边忙着抵抗病毒,一边还得继续准备面试。又该准备“造火箭”了,去了继续“拧螺丝”,下面是自己最近的一些总结,也会在后面的面试中,遇到的面试问题,也一并记录一下。

如果招聘者看到了,感觉我还可以,欢迎您的私信一下
如果招聘者看到了,感觉我还可以,欢迎您的私信一下
如果招聘者看到了,感觉我还可以,欢迎您的私信一下

如有编写有问题,可以留言。不可避免的有错别字,望见谅!
如果您也是个面试者,碰到面问题,可以留言、私信交流一下。

如果你还想看其他面试题,可以移步到2017年面试题

1. ARC帮我们做了什么?

2.initializeload是如何调用的?它们会多次调用吗?

3.category属性是存储在那里?

void _object_set_associative_reference(id object, void *key, id value, uintptr_t policy) {
   // 一下为精简的代码
    id new_value = value ? acquireValue(value, policy) : nil;
    {
        AssociationsManager manager;
        AssociationsHashMap &associations(manager.associations());
        disguised_ptr_t disguised_object = DISGUISE(object);
        if (new_value) {
          ObjectAssociationMap *refs = new ObjectAssociationMap;
          associations[disguised_object] = refs;
          (*refs)[key] = ObjcAssociation(policy, new_value);
        }
    }
}
AssociationsManager.png

4.category方法是如何添加的?

category.png

5. OC 的消息机制

objc_msgSend.png

6.weak表是如何存储__weak指针的

id
objc_storeWeak(id *location, id newObj)
{
    return storeWeak<DoHaveOld, DoHaveNew, DoCrashIfDeallocating>
        (location, (objc_object *)newObj);
}
static id 
storeWeak(id *location, objc_object *newObj) {
  // 根据对象生成新的SideTable
  SideTable *newTable = &SideTables()[newObj];
  newObj = (objc_object *)
  weak_register_no_lock(&newTable->weak_table, (id)newObj, location,  crashIfDeallocating);
}
id 
weak_register_no_lock(weak_table_t *weak_table, id referent_id, 
                      id *referrer_id, bool crashIfDeallocating){
  objc_object *referent = (objc_object *)referent_id;
  objc_object **referrer = (objc_object **)referrer_id;
  
  // 根据对象和指针生成一个entry
  weak_entry_t new_entry(referent, referrer);
  // 检查是是否该去扩容
  weak_grow_maybe(weak_table);
  // 将新的entry 插入到表里面
  weak_entry_insert(weak_table, &new_entry);
}
static void weak_entry_insert(weak_table_t *weak_table, weak_entry_t *new_entry)
{
    weak_entry_t *weak_entries = weak_table->weak_entries;

    size_t begin = hash_pointer(new_entry->referent) & (weak_table->mask);
    size_t index = begin;
    size_t hash_displacement = 0;
    while (weak_entries[index].referent != nil) {
        index = (index+1) & weak_table->mask;
        if (index == begin) bad_weak_table(weak_entries);
        hash_displacement++;
    }
    weak_entries[index] = *new_entry;
    weak_table->num_entries++;
}

weak_table的扩容,根据存储条数 >= 最大存储条数的3/4时,就会按照两倍的方式进行扩容,并且会将已经有的条目再次生成新的index(因为扩容后,weak_table的mask发生了改变)。进行保存

static void weak_grow_maybe(weak_table_t *weak_table)
{
    size_t old_size = (weak_table->mask ? weak_table->mask + 1 : 0);
    if (weak_table->num_entries >= old_size * 3 / 4) {
        weak_resize(weak_table, old_size ? old_size*2 : 64);
    }
}
static void weak_resize(weak_table_t *weak_table, size_t new_size)
{
    size_t old_size = TABLE_SIZE(weak_table);
    weak_entry_t *old_entries = weak_table->weak_entries;
    // calloc 分配新的控件
    weak_entry_t *new_entries = (weak_entry_t *)
        calloc(new_size, sizeof(weak_entry_t));
    // mask 就是大小减一
    weak_table->mask = new_size - 1;
    weak_entry_t *entry;
    weak_entry_t *end = old_entries + old_size;
    for (entry = old_entries; entry < end; entry++) {
        if (entry->referent) {
           weak_entry_insert(weak_table, entry);
        }
    }
}

7. 方法catch表是如何存储方法的

static void cache_fill_nolock(Class cls, SEL sel, IMP imp, id receiver) {
  // 获取类对象的catch地址
  cache_t *cache = &cls->cache
  // 获取key
  cache_key_t key = (cache_key_t)sel;
  // 找到bucket
  bucket_t *bucket = cache->find(key, receiver);
}

bucket_t * cache_t::find(cache_key_t k, id receiver)
{
    // catch表的buckets属性
    bucket_t *b = buckets();
    // catch 表示的mask 最大值 - 1
    mask_t m = mask();
    
    mask_t begin = cache_hash(k, m);
    mask_t i = begin;
    do {
        if (b[i].key() == 0  ||  b[i].key() == k) {
            return &b[i];
        }
    } while ((i = cache_next(i, m)) != begin);
}
static inline mask_t cache_next(mask_t i, mask_t mask) {
    return (i+1) & mask;
}

注意:catch表的扩容,同样也是和weak_table一样按照2倍的方式进行扩容,但是注意:扩容后,以前缓存的方法则会被删除掉。

void cache_t::expand() {
    uint32_t oldCapacity = capacity();
    uint32_t newCapacity = oldCapacity ? oldCapacity*2 : INIT_CACHE_SIZE;
    reallocate(oldCapacity, newCapacity);
}

void cache_t::reallocate(mask_t oldCapacity, mask_t newCapacity)
{
    // 获取旧的oldBuckets
    bucket_t *oldBuckets = buckets();
    // 重新分配新的
    bucket_t *newBuckets = allocateBuckets(newCapacity);
    // free 掉旧的
    cache_collect_free(oldBuckets, oldCapacity);
}

8.优化后isa指针是什么样的?存储都有哪些内容?

isa.png

9.App启动流程,以及如何优化?

DYLD_PRINT_STATISTICS.png

10.App瘦身

Link Map.png

Link Map解析结果

LinkMap 解析结果.png

如果招聘者看到了,感觉我还可以,欢迎您的私信一下
如果招聘者看到了,感觉我还可以,欢迎您的私信一下
如果招聘者看到了,感觉我还可以,欢迎您的私信一下

持续更新中。。。。

上一篇下一篇

猜你喜欢

热点阅读