iOS 每天一道面試題
同為菜逼,共同努力。
1.nil Nil NULL NSNull 區別。
nil:指向oc中物件的空指標,針對物件。
Nil:指向oc中類的空指標,針對類。
NULL:指向其他型別的空指標,如一個c型別的記憶體指標,基本資料型別為空,基本型別。
NSNull:在集合物件中,表示空值的物件。
參考部落格這是我發現寫的比較詳細的部落格.
2.你是否接觸過oc中的反射機制?簡單聊一下概念和使用.
// • class反射
// • 通過類名的字串形式例項化物件
Class class1 = NSClassFromString(@"UILabel");
id label = [[class1 alloc ]init];
NSLog(@"label = %@",label);
// • 將類名變為字串
Class class2 =[UILabel class];
NSString *className = NSStringFromClass(class2);
NSLog(@"className = %@",className);
Student *stu = [[Student alloc] init];
// • SEL的反射
// • 通過方法的字串形式例項化方法
SEL selector = NSSelectorFromString(@"setName:");
[stu performSelector:selector withObject:@"GanMaoShen"]; //注意如果有兩個引數,使用兩個withObject:引數;
NSLog(@"stu.name =%@",stu.name);
// • 將方法變成字串
NSString *select = NSStringFromSelector(@selector(testVoidFuncWithTestParam:));
NSString *select2 = NSStringFromSelector(_cmd);
NSLog(@"select =%@ select2 = %@",select,select2);
2017-03-27 20:19:07.658 test[10559:3059755] label = <UILabel: 0x7fdcae00fed0; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = <_UILabelLayer: 0x6000002834d0>>
2017-03-27 20:19:07.659 test[10559:3059755] className = UILabel
2017-03-27 20:19:07.659 test[10559:3059755] stu.name =GanMaoShen
2017-03-27 20:19:07.659 test[10559:3059755] select =testVoidFuncWithTestParam: select2 = viewDidLoad
3.Block的傳值,傳址,記憶體管理,迴圈引用(retain cycle)。(狠補了一下block的知識,發現block中很多知識點,所以還是要弄透)
兩篇很好的block基礎部落格
block的用法,定義.
block兩個介面的傳值.
void test1()
{
int a = 10;
}
void test2()
{
__block int a = 10;
}
void test3()
{
static int a = 10;
}
int a = 10;
void test4()
{
}
總結:block中只有普通區域性變數(test1)是傳值,其他情況(test2,test3,test4)都是傳址。
#block的記憶體管理
ARC下:
- block可以使用copy和strong,並且是一個物件。
#Block如果沒有引用外部變數
儲存在全域性區(MRC/ARC一樣)
#Block如果引用外部變數
ARC儲存在 堆區; MRC儲存在 棧區必須用copy修飾block;
block迴圈引用
1.如果block程式碼塊的內部,使用了外面的強引用物件,block程式碼塊的內部會自動產生一個強引用,引用著該物件,不會銷燬,造成迴圈引用.
解決:下面程式碼在block外部實現.
__weak typeof(self) weakSelf = self;
#define WeakSelf(type) __weak typeof(type) weak##type = type;
2.但是如果在block內部使用延時操作的還使用弱指標的話會取不到該弱指標,需要在block內部再將弱指標強引用一下.
__strong typeof(self) strongSelf = weakSelf;
#define StrongSelf(type) __strong typeof(type) strong##type = weak##type;
關於迴圈引用很好的部落格Swift與OC真正去理解Block解決迴圈引用的技巧
4.如何在@category和@protocol中新增@property
首先你要知道category和protocol和作用和區別,同時回顧這道題的同時,同時回顧extension 和category。
extension看起來很像一個匿名的category,但是extension和有名字的category幾乎完全是兩個東西。 extension在編譯期決議,它就是類的一部分,在編譯期和標頭檔案裡的@interface以及實現檔案裡的@implement一起形成一個完整的類,它伴隨類的產生而產生,亦隨之一起消亡。extension一般用來隱藏類的私有資訊,你必須有一個類的原始碼才能為一個類新增extension,所以你無法為系統的類比如NSString新增extension。
更深入一點的話我推薦這個帖子。iOS 類別不能新增屬性原理?
@dynamic 和 @synthesize的區別:
在@implementation 中通過@dynamic xxx 告訴編譯器、xxx屬性的setter、getter方法由開發者自己來生成
@ synthesize xxx = _xxx; 告訴編譯器、xxx屬性的setter、getter方法由編譯器來生成、同時用_xxx 來合成 成員變數
好,步入正題。
4.1@protocol中新增property
在protocol中新增property時,其實就是宣告瞭 getter 和 setter 方法,在實現這個protocol協議的類中,我們要自己手動新增例項變數,並且需要實現setter/getter方法,實現setter/getter方法有兩種方式,一種是自動生成(@synthesize) ,另一種是手動生成(@dynamic)此時又有了擴充問題(@synthesize和@dynamic的作用 見 題5)
@protocol PersonDelegate <NSObject>
@property (nonatomic, copy) NSString *name;
@end
//personn類
@interface Person : NSObject
@end
#import "Person.h"
@interface Student : NSObject <PersonDelegate>
- (void)testLog;
@end
#import "Student.h"
@implementation Student
//自動實現setter和getter方法
@synthesize name;
- (void)testLog {
NSLog(@"self.name=%@",self.name);
}
@end
手動實現setter和getter
#import "Person.h"
@interface Student2 : NSObject <PersonDelegate>
{
//宣告一個例項變數
NSString *_name;
}
- (void)testLog;
@end
#import "Student2.h"
@implementation Student2
@dynamic name;
- (void)testLog {
NSLog(@"self.name=%@",self.name);
}
- (void)setName:(NSString *)name
{
_name = name;
}
- (NSString *)name
{
return _name;
}
@end
Student *stu1 = [Student new];
stu1.name = @"testName";
[stu1 testLog];
Student2 *stu2 = [Student2 new];
stu2.name = @"testName";
[stu2 testLog];
關於category實現property主要是利用runtime的關聯方法(mjrefresh中也有用到)。
objc_setAssociatedObject objc_getAssociatedObject
@interface Person (Test)
@property (nonatomic, copy) NSString *tmpName;
- (void)testLog;
@end
#import "Person+Test.h"
#import <objc/runtime.h>
@implementation Person (Test)
- (void)setTmpName:(NSString *)tmpName
{
objc_setAssociatedObject(self, @selector(tmpName), tmpName, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)tmpName
{
return objc_getAssociatedObject(self, @selector(tmpName));
}
- (void)testLog {
NSLog(@"self.name=%@",self.tmpName);
}
@end
Person *p1 = [Person new];
p1.tmpName = @"tmpName";
[p1 testLog];
當然還有一種利用臨時變數的方法完成新增屬性的方法。參考部落格
iOS Category 和 Protocol 中的 Property 你們真的會了麼?
相關文章
- 一道高階iOS面試題(runtime方向)iOS面試題
- 一道面試題面試題
- mysql一道面試題MySql面試題
- 每天一道程式設計題(Javascript)程式設計JavaScript
- 「每天一道面試題」sleep方法和wait方法有什麼區別?面試題AI
- 【理解】一道 JS 面試題JS面試題
- 一道面試題的分析面試題
- 一道騷面試題目面試題
- 解析一道JS面試題JS面試題
- 從一道 iOS 面試題到 Swift 物件模型和執行時細節——「iOS 面試之道」勘誤iOS面試題Swift物件模型
- 一道面試題:去重排序面試題排序
- 一道面試題引起的思考面試題
- 分享一道昨天的面試題面試題
- 一道柯里化面試題面試題
- 一道java面試基礎題Java面試
- 一道hibernate面試題,求解?面試題
- 一道sql面試題的解答SQL面試題
- 幫忙解答一道面試題面試題
- 每天一道演算法題:顛倒整數演算法
- 每天一道演算法題:Z字形轉換演算法
- iOS面試題iOS面試題
- 一道遞迴陣列面試題遞迴陣列面試題
- 分享一道Go面試必考的題Go面試
- 一道面試題引發的“血案”面試題
- 一道面試題引發的思考面試題
- [js]一道快取類面試題JS快取面試題
- 重做一道Java面試題(Fork/Join)Java面試題
- 一道java面試題分析及思考Java面試題
- 一道sql面試題的求解方法SQL面試題
- 一道以前看過的面試題面試題
- 從一道面試題說開來面試題
- LeetCode演算法簡單題--JavaScript(每天一道題)LeetCode演算法JavaScript
- 一道與 for 相關的字串面試題字串面試題
- 關於PHP字串的一道面試題PHP字串面試題
- 聊聊一道簡單的javascript面試題JavaScript面試題
- 從 Google 的一道面試題說起·Go面試題
- 從一道前端面試題談起前端面試題
- 來聊一道前端面試題吧前端面試題