前言
很多人都說(shuō)熟悉UIKit复濒,那對(duì)于常見(jiàn)的API是否熟悉筷弦?
多線(xiàn)程是前端經(jīng)久不衰的考點(diǎn)幔妨。
大家對(duì)于Block的weak-strong dance都耳熟能詳闻镶,是否清楚知道每一個(gè)引用背后的持有者斥滤,以及對(duì)象的具體釋放時(shí)機(jī)将鸵?
來(lái)試試這4道精挑細(xì)選的題目。
正文
題目1佑颇、UIImage相關(guān)
看下面一段代碼顶掉,
保存到相冊(cè)的是什么?(從格式挑胸、形狀去描述)
- (void)testUIImage {
UIImage *testImage;
UIGraphicsBeginImageContext(CGSizeMake(50, 50));
UIView *testView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
testView.backgroundColor = [UIColor redColor];
testView.layer.cornerRadius = 25;
testView.layer.masksToBounds = YES;
[testView.layer renderInContext:UIGraphicsGetCurrentContext()];
testImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[[[ALAssetsLibrary alloc] init] writeImageToSavedPhotosAlbum:testImage.CGImage metadata:nil completionBlock:nil];
}
題目2痒筒、URL相關(guān)
看下面一段代碼,
寫(xiě)下三行Log的輸出茬贵,并解釋下URL是什么簿透。
- (void)testUrl {
NSString *path = @"https://www.baidu.com/";
NSString *path2 = @"http://fanyi.baidu.com/translate?query=#auto/zh/";
NSString *path3 = @"http://fanyi.baidu.com/translate?query=#zh/en/測(cè)試";
NSURL *url = [NSURL URLWithString:path];
NSURL *url2 = [NSURL URLWithString:path2];
NSURL *url3 = [NSURL URLWithString:path3];
NSLog(@"%@", url);
NSLog(@"%@", url2);
NSLog(@"%@", url3);
}
題目3、線(xiàn)程相關(guān)
看下面一段代碼解藻,
寫(xiě)下Log的輸出老充,并解釋為什么。
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"before perform");
[self performSelector:@selector(printLog) withObject:nil afterDelay:0];
NSLog(@"after perform");
});
}
- (void)printLog {
NSLog(@"printLog");
}
題目4螟左、內(nèi)存相關(guān)(簡(jiǎn)友們提醒啡浊,不要用系統(tǒng)的addSubview
、removeFromSuperView
路狮,減少干擾項(xiàng))
看下面兩段代碼虫啥,
ViewController的代碼如下
@interface ViewController () <LYButtonDelegate>
@end
@implementation ViewController
{
LYButton *testBtn;
LYButton *testBtn2;
}
- (void)viewDidLoad {
[super viewDidLoad];
testBtn = [[LYButton alloc] init];
testBtn.delegate = self;
[testBtn test];
testBtn2 = [[LYButton alloc] init];
testBtn2.delegate = self;
[testBtn2 test2];
}
- (void)onRemove:(LYButton *)btn {
if (testBtn == btn) {
testBtn = nil;
}
if (testBtn2 == btn) {
testBtn2 = nil;
}
}
LYButton的代碼如下
@class LYButton;
@protocol LYButtonDelegate
- (void)onRemove:(LYButton *)btn;
@end
@implementation LYButton
- (void)test {
[self.delegate onRemove:self];
NSLog(@"%@", (self == nil) ? @"YES" : @"NO");
}
- (void)test2 {
__weak typeof (LYButton *) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.delegate onRemove:weakSelf];
NSLog(@"%@", (weakSelf == nil) ? @"YES" : @"NO");
NSLog(@"end");
});
}
@end
寫(xiě)下Log的輸出蔚约,并解釋為什么奄妨。
答案
題目1
考察點(diǎn):對(duì)常見(jiàn)UI操作、圖片格式的了解苹祟。
內(nèi)存中的testImage是非壓縮的格式砸抛,保存到相冊(cè)可以使用png或者jpeg格式。
-writeImageToSavedPhotosAlbum:
接口默認(rèn)用的jpeg的格式树枫,如果保存png直焙,需要將圖片轉(zhuǎn)成NSData,然后再保存砂轻。
testView的操作是繪制圓角按鈕奔誓,然后用layer的renderInContext
繪制到Context中;
題目2
考察點(diǎn):對(duì)API的-URLWithString:
了解,本質(zhì)的知識(shí)點(diǎn)是URL encode厨喂。
常見(jiàn)的錯(cuò)誤是在get參數(shù)添加中文和措,但是沒(méi)有重新編碼(也叫轉(zhuǎn)義),導(dǎo)致NSURL初始化失敗蜕煌。
正確的做法是調(diào)用NSString的(NSString *)stringByAddingPercentEscapesUsingEncoding:(NSStringEncoding)encoding
方法派阱。
URL:Uniform Resource Locator,統(tǒng)一資源定位符斜纪,用的是ASCII編碼贫母。
題目3
考察點(diǎn):GCD并發(fā)隊(duì)列實(shí)現(xiàn)機(jī)制,以及performSelector
的實(shí)現(xiàn)原理以及runloop了解盒刚。
上面這段代碼腺劣,只會(huì)打印before perform
和after perform
,不會(huì)打印printLog因块。
原因:
1誓酒、GCD默認(rèn)的全局并發(fā)隊(duì)列,在并發(fā)執(zhí)行任務(wù)的時(shí)候贮聂,會(huì)從線(xiàn)程池獲取可執(zhí)行任務(wù)的線(xiàn)程(如果沒(méi)有就阻塞)靠柑。
2、performSelector的原理是設(shè)置一個(gè)timer到當(dāng)前線(xiàn)程Runloop吓懈,并且是NSDefaultRunLoopMode歼冰;
3、非主線(xiàn)程的runloop默認(rèn)是不啟用耻警;
進(jìn)階問(wèn)題:加一行代碼使得
printLog
能正常打印隔嫡。
題目4
考察點(diǎn):內(nèi)存的引用計(jì)數(shù)。
test1中甘穿,onRemove執(zhí)行之前腮恩,有-testBtn
、-test1
温兼、self.view三個(gè)地方持有強(qiáng)引用秸滴,到打印log的時(shí)候兩個(gè)地方的強(qiáng)引用;
test2中募判,在block中強(qiáng)引用了weakSelf荡含,當(dāng)block執(zhí)行的時(shí)候,testBtn和test2的兩個(gè)引用都已經(jīng)釋放届垫,當(dāng)執(zhí)行完onRemove之后释液,最后一個(gè)引用也釋放,會(huì)立刻執(zhí)行dealloc
方法装处,weakSelf被置為nil(weak指針的用法就是在對(duì)象被回收后變成nil)误债,故而Log輸出YES;
類(lèi)似,在UIButton的onClick:
回調(diào)方法中寝蹈,button類(lèi)的self不僅會(huì)被StackThread持有糟袁,還會(huì)被main thread dispatch持有(系統(tǒng)分發(fā)點(diǎn)擊事件)。
總結(jié)
做題是一個(gè)有意思的過(guò)程躺盛,短時(shí)間的思考并得到對(duì)or錯(cuò)的回饋项戴,非常適合人腦的學(xué)習(xí)模式。
希望這幾道題能有所幫助槽惫。如果錯(cuò)誤周叮,請(qǐng)斧正。