zoukankan      html  css  js  c++  java
  • 面试题

    1 如何实现一个图片加载控件(包括图片下载、缓存时效、加载)?

      参考链接:http://blog.csdn.net/tengxy_cloud/article/details/52869037 

    2 JavaScriptCore是做什么用的,客户端使用它可实现什么功能?

     

    3 程序中添加每3秒响应一次的NSTimer,当拖动tableView时timer可能无法响应,为什么,要怎么解决?

       scheduled开头和非schedule的开头方法的区别。系统框架提供了几种创建NSTimer的方法,其中以scheduled开头的方法会自动把timer加入当前run loop,到了设定的时间点就会触发指定的方法,而没有scheduled开头的方法则需要程序员自己手动添加到timer到一个run loop中才会有效。run loop在运行时一般有两个mode,一个defaultmode,一个trackingmode,正常情况下run loop使用defaultmode,scheduled生成的timer会默认添加到defaultmode中,当我们互动scrollview时,run loop切换到trackingmode运行,于是我们发现定时器失效了。为了使定时器在我们滑动scrollview时也能正常运行,我们需要确保defaultmode和trackingmode里都添加了我们生成的timer。如:

    NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(scrollPage) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];

    或者

    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(scrollPage) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];

      在使用NSTimer时应注意:

    (1)使用NSTimer时,timer会保持对target和userInfo参数的强引用。只有当调取了NSTimer的invalidate方法时,NSTimer才会释放target和userInfo。生成timer的方法中如果repeats参数为NO,则定时器触发后会自动调取invalidate方法。如果repeats参数为YES,则需要程序员手动调取invalidate方法才能释放timer对target和userIfo的强引用。

    (2)在使用repeats参数为YES的定时器时,如果在使用完定时器时后没有调取invalidate方法,导致target和userInfo没有被释放,则可能会形成循环引用情况,从而影响内存释放。

    4 客户端在解析服务端所下发的数据时,例如下面的代码片段:

    NSString *sku = dict[@"sku"];

    NSMutableArray *array = [NSMutableArray array];

    [array addObject:sku];

    可能@"sku"字段并不存在,sku对象将为nil,执行[array addObject:sku]时将会抛出异常导致Crash。项目中可能很多模块存在类似这样的问题,请从全局考虑,如何进行异常保护?

       注意:在类簇中实现Method Swizzling。 NSMutableArray-----@"__NSArrayM"(用Xcode调试时,在下方debug区域显示的__NSArrayM类型)

    #import "NSMutableArray+Swizzling.h"
    #import <objc/runtime.h>
    
    @implementation NSMutableArray (Swizzling)
    
    + (void)load {   
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            
            Class originClass = NSClassFromString(@"__NSArrayM");
            Class swizzledClass = [self class];
            
            SEL originalSelector = @selector(addObject:);
            SEL swizzledSelector = @selector(xxx_addObject:);
            
            Method originalMethod = class_getInstanceMethod(originClass, originalSelector);
            Method swizzledMethod = class_getInstanceMethod(swizzledClass, swizzledSelector);
            
            BOOL didAddMethod = class_addMethod(originClass,
                            originalSelector,
                            method_getImplementation(swizzledMethod),
                            method_getTypeEncoding(swizzledMethod));
            
            if (didAddMethod) {
                class_replaceMethod(originClass,
                                    swizzledSelector,
                                    method_getImplementation(originalMethod),
                                    method_getTypeEncoding(originalMethod));
            } else {
                method_exchangeImplementations(originalMethod, swizzledMethod);
            }
        }); 
    }
    
    - (void)xxx_addObject:(id)object {    
            if (object != nil) {
                [self xxx_addObject:object];
            }
    }
    
    @end

    5 当进入一个页面时添加任务到后台线程,例如下面的代码片段:

    - (void)viewDidLoad {

        [super viewDidLoad];

        self.queue = dispatch_queue_create("jd.test", DISPATCH_QUEUE_SERIAL);

        for (NSInteger i = 0; i < 10; i ++) {

            dispatch_async(self.queue, ^{

                NSLog(@"%ld", i);

            });

        }

    }

    在页面退出时,假如队列中执行到第3个任务,如何取消还没有执行的任务?

       设置一个全局标识Bool isStart = YES,在队列中异步执行任务时,判断这个标识isStart是否为YES,如果是YES再执行,否则不执行。当页面退出时,我们在dealooc方法中将这个标识设置为isStart = NO。则队列中的任务将不再会执行,也就相当于是取消了未执行的任务。

      __weak typeof(self) weakSelf = self;  

      dispatch_async(self.queue, ^{

        if (weakSelf.isStart) {

          NSLog(@"%ld", i);

        }     

            });

    6 有如下代码:

    -(void)dealloc {

    _weak _typeof(self) weak_self = self;

    NSLog(@“%@”, weak_self);

    }

    请问,当执行该方法时会出现审结果?为什么?

       崩溃。原因是不允许在dealloc中取weak self

      崩溃时在控制台打印出的信息时: 

     Cannot form weak reference to instance (0x160f6f890) of class MFChatRoomBoardController. It is possible that this object was over-released, or is in the process of deallocation.

    查看了一下 weak_register_no_lock 的函数代码,找到问题所在。
    id weak_register_no_lock(weak_table_t *weak_table, id referent_id, id *referrer_id)
    {
        objc_object *referent = (objc_object *)referent_id;
        objc_object **referrer = (objc_object **)referrer_id;
    
        if (!referent  ||  referent->isTaggedPointer()) return referent_id;
    
        // ensure that the referenced object is viable
        bool deallocating;
        if (!referent->ISA()->hasCustomRR()) {
            deallocating = referent->rootIsDeallocating();
        }
        else {
            BOOL (*allowsWeakReference)(objc_object *, SEL) = 
                (BOOL(*)(objc_object *, SEL))
                object_getMethodImplementation((id)referent, 
                                               SEL_allowsWeakReference);
            if ((IMP)allowsWeakReference == _objc_msgForward) {
                return nil;
            }
            deallocating =
                ! (*allowsWeakReference)(referent, SEL_allowsWeakReference);
        }
    
        if (deallocating) {
            _objc_fatal("Cannot form weak reference to instance (%p) of "
                        "class %s. It is possible that this object was "
                        "over-released, or is in the process of deallocation.",
                        (void*)referent, object_getClassName((id)referent));
        }
    
        // now remember it and where it is being stored
        weak_entry_t *entry;
        if ((entry = weak_entry_for_referent(weak_table, referent))) {
            append_referrer(entry, referrer);
        } 
        else {
            weak_entry_t new_entry;
            new_entry.referent = referent;
            new_entry.out_of_line = 0;
            new_entry.inline_referrers[0] = referrer;
            for (size_t i = 1; i < WEAK_INLINE_COUNT; i++) {
                new_entry.inline_referrers[i] = nil;
            }
    
            weak_grow_maybe(weak_table);
            weak_entry_insert(weak_table, &new_entry);
        }
    
        // Do not set *referrer. objc_storeWeak() requires that the 
        // value not change.
    
        return referent_id;
    }

      可以看出,runtime 是通过检查引用计数的个数来判断对象是否在 deallocting, 然后通iif (deallocating)使程序崩溃。

    7 有如下代码:

    typedef void (^TestBlock)(void);

    int main(int argc, char * argv[]) {

        @autoreleasepool {        

            NSString *test = @"test";

            TestBlock block = ^(void) {

                dispatch_sync(dispatch_queue_create("jd.test", DISPATCH_QUEUE_SERIAL), ^{

                    NSLog(@"%@", test);

                });

            };

            test = @"test1";

            block();

        }

    }

    请问,NSLog(@“%@”, test)的输出结果是什么?这条语句在哪个线程执行?为什么?

      输出结果:test  在主线程执行       同步执行

        

  • 相关阅读:
    最小生成树(Prim和Kruscal)
    SPFA(还是稍微写写吧,虽然没什么用)
    最短路径(随便写写)(Floyd,Bellman-Ford,Dijkstra)
    Just a Hook HDU
    数论逆元
    最长上升子序列(LIS)算法(附Codeforces Round #641 (Div. 2),B题题解)
    Educational Codeforces Round 86 (Rated for Div. 2)
    Codeforces Round #633 (Div. 2)
    Codeforces Round #631 (Div. 2)
    Mayor's posters(线段树离散化)
  • 原文地址:https://www.cnblogs.com/muzijie/p/6402340.html
Copyright © 2011-2022 走看看