同为菜逼,共同努力。
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 你们真的会了么?