同為菜逼,共同努力。
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 你們真的會了么?