iOS开发中一些"有趣"的问题

目录

  • 问题1: reloadData和reloadRowsAtIndexPaths:withRowAnimation不仅仅是一点不同

  • 问题2: 说好的category代码, 为什么不走!

  • 问题3: 代码跑到哪里去了?

  • 问题4: 可变参数没有想象的那么美好!

问题1: reloadData和reloadRowsAtIndexPaths:withRowAnimation不仅仅是一点不同

问题描述:

在View里添加两个UIButton和一个UITableView, 效果是这个样子的:

iOS开发中一些
ios_some_good_problems_01.png

核心代码如下:

@interface ViewController () 

@property (assign, nonatomic) NSInteger count;

@end

@implementation ViewController

# pragma mark - UITableViewDataSource

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 1;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *identifier = @"reuserIndentifier";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
        cell.textLabel.text = [NSString stringWithFormat:@"cell count: [%ld]", self.count++];
    }

    NSLog(@"cell = [%@] text = [%@]", cell, cell.textLabel.text);

    return cell;
}

@end

reloadData Button的处理是:

- (void)reloadDataButtonClicked {
    [_tableView reloadData];
}

reloadIndexPath Button的处理是:

- (void)reloadIndexPathButtonClicked {
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
    NSArray *reloadIndexPaths = [NSArray arrayWithObjects:indexPath, nil];
    [_tableView reloadRowsAtIndexPaths:reloadIndexPaths withRowAnimation:UITableViewRowAnimationNone];
}

那么问题来了, 请注意我问题的前提条件哦:

第一组问题:

在初始状态下, 按一次reloadData Button, cell的显示会变成:

A. cell count: 0

B. cell count: 1

C. cell count: 2

D. 上述答案都是忽悠人的

在初始状态下按了一次reloadData Button, 再按一次reloadData Button, cell的显示会变成:

A. cell count: 0

B. cell count: 1

C. cell count: 2

D. 上述答案都是忽悠人的

第二组问题:

在初始状态下, 按一次reloadIndexPath Button, cell的显示会变成:

A. cell count: 0

B. cell count: 1

C. cell count: 2

D. 上述答案都是忽悠人的

在初始状态下按了一次reloadIndexPath Button, 再按一次reloadIndexPath Button, cell的显示会变成:

A. cell count: 0

B. cell count: 1

C. cell count: 2

D. 上述答案都是忽悠人的

坦白讲这个题目不适合做第一题, 因为我感觉有点"难"那~

问题2: 说好的category代码, 为什么不走!

问题描述:

我们实现了NSString的Category如下:

#import "NSString+MyExtention.h"

@implementation NSString (MyExtention)

- (BOOL)isValidString {
    if (self == nil || self == NULL) {
        return YES;
    }

    if ([self isEqualToString:@""] || [self isEqualToString:@"null"] || [self isEqualToString:@"(null)"]) {
        return YES;
    } else if ([[self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] length] == 0) {
        return YES;
    } else if ([[self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] isEqualToString:@""]) {
        return YES;
    }

    return NO;
}

@end

接着我们在ViewController.m引用这个Category来判断NSString是否合法

#import "ViewController.h"
#import "NSString+MyExtention.h"

@interface ViewController ()

@property (nonatomic, strong) NSString *willBeCheckedString;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [self test1];
    [self test2];
}

- (void)test1 {
    if ([_willBeCheckedString isValidString]) {
        NSLog(@"Invalid String");
    } else {
        NSLog(@"Valid String");
    }
}

- (void)test2 {
    if (_willBeCheckedString == nil || [_willBeCheckedString isValidString]) {
        NSLog(@"Invalid String");
    } else {
        NSLog(@"Valid String");
    }
}

@end

问题来了, test1和test2的打印分别是什么呢?

test1的打印

A. Invalid String

B. Valid String

C. 上述答案都是忽悠人的

test2的打印

A. Invalid String

B. Valid String

C. 上述答案都是忽悠人的

鉴于问题1热身过后, 这题还是比较easy的吧?

问题3: 代码跑到哪里去了?

问题描述:

在ViewController的ViewDidLoad方法里, 我们加了三行打印如下

- (void)viewDidLoad {
    [super viewDidLoad];

    NSLog(@"1");
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"2");
    });
    NSLog(@"3");
}

问题来了(问题描述这么精简?是滴, 你没看错, 我也没写漏), 这行代码的打印是什么呢?

按照惯例不用怕, 还是选择题不是问答题哈(换行等额外的打印信息暂时忽略, 抓住主要问题即可)

A. 123

B. 132

C. 上述答案都是忽悠人的

问题4: 可变参数没有想象的那么美好!

可变参数的API, 看起来很强大, 因为一次可以传递多个参数, 而不受任何限制

但其实并没有想象的那么美好, 一不小心就引发调试"血案", 我们来看下面的实例化NSDictionary的例子

NSString *keyName = @"name";
NSString *keyAge = @"age";
NSString *keyNickname = @"nickname";

NSString *valueName = @"yuan";
NSString *valueAge = nil;
NSString *valueNickname = @"mumu";

NSDictionary *userInfo1 = [NSDictionary dictionaryWithObjectsAndKeys:valueName, keyName, valueAge, keyAge, valueNickname, keyNickname, nil];

NSMutableDictionary *userInfo2 = [NSMutableDictionary dictionary];
[userInfo2 setObject:valueName forKey:keyName];
[userInfo2 setObject:valueNickname forKey:keyNickname];

if ([[userInfo1 objectForKey:keyNickname] isEqualToString:[userInfo2 objectForKey:keyNickname]]) {
    NSLog(@"nickname value is equal");
} else {
    NSLog(@"nickname value is un-equal");
}

请问这里的打印信息是什么呢?

A. nickname value is equal

B. nickname value is un-equal

C. 你又在忽悠人了

小结

总结我遇到几个好玩问题就到这里了, 如果你也有遇到, 欢迎发给我, 我会持续更新的

提示

问题1:

reloadData会先将所有cell都先放到复用池中, 然后再从复用池中取可以复用的cell

reloadRowsAtIndexPaths:withRowAnimation因为有cell进入和移出的动画, 所以同时需要至少两个可用的的cell(包括复用池中的cell)

问题2:

Objective-C是的方法调用其实是基于消息的, nil是不会接收和处理消息的

问题3:

这是一个死锁问题, 原理详见iOS开发 之 Queue和Thread

问题4:

可变参数是以nil或null结尾的

更多文章, 请支持我的个人博客

你可能感兴趣的:(iOS开发中一些"有趣"的问题)