对于语句NSString *obj = [[NSData alloc] init]; obj在编译时和运行时分别是什么类型的对象?
编译时是NSString的类型;运行时是NSData类型的对象。
在一个对象的方法里面:self.name = @"object";和 _name = @"object"有什么不同吗?
self.name = @"object"; 是通过点语法修改属性name的值。
本质上使用的是name属性的setter方法进行的赋值操作,实际上执行的代码是
[self setName:@"object"];
例如:
@property(nonatomic, strong) NSString *name;
//根据@property关键词,系统自动生成setter方法。
- (void)setName:(NSString *)name{
//根据strong关键词
[name retain]; //内存计数+1
[_name release]; //把之前指针指向的内容内存计数-1
_name = name; //指向新内容
}
而 _name = @“object”; 只是单纯的把‘_name’指针指向‘@"object"’字符串对象所在的地址, 没有调用方法。
这段代码有什么问题吗?
-(void)setAge:(NSString *)age {
self.age = age;
}
在age属性的setter方法中,不能通过点语法给该属性赋值。
会造成setter方法的循环调用。最终导致程序崩溃.因为self.age = newAge; 本质上是在调用 [self setAge:newAge]; 方法。
解决循环调用的方法是方法体修改为 _age = age;
你对@interface中的成员变量和@property声明的属性的理解。
@interface AA: NSObject{
NSString *_name; //成员变量
}
@property NSString *age; //属性
如上所示:
属性拥有setter和getter方法 外加_age成员变量。
_name只是成员变量, 没有setter和getter方法。
以下代码运行结果如何?
-(void)viewDidLoad {
[super viewDidLoad];
NSLog(@"1");
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"2");
});
NSLog(@"3");
}
结果:只会打印1 然会就会线程卡死
因为dispatch_get_main_queue()得到的是一个串行队列,串行队列的特点: 一次只调度一个任务,队列中的任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)
同步(sync) 操作,它会阻塞当前线程并等待 Block 中的任务执行完毕,然后当前线程才会继续往下运行
dispatch_sync提交一个打印任务NSLog(@”2”)到主线程关联的串行队列中,主线程关联的串行队列现在有一个viewDidLoad任务,
打印任务NSLog(@”2”)排在viewDidLoad后面,队列FIFO(先进先出)的原则,打印任务NSLog(@”2”);
想要得到执行必须等到viewDidLoad执行完毕后才能得到执行,但是viewDidLoad想要执行完毕必须要等打印任务NSLog(@”2”)执行完毕,所以就卡死在这了。
然而实际开发中很少用到,当然注意下还是有必要的.
用预处理指令#define声明一个常数,用以表明一年中有多少秒
#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)_U_LONG
这个问题可以简单考察对于define的基本使用,
如果意识到这个表达式将使一个16位机的整型数溢出-要用到长整型符号,告诉编译器这个常数是的长整型数。
如果你在你的表达式中用到_U_LONG(表示无符号长整型),会更好.
另外如果是较早的答案会是UL,但是目前已经由_U_LONG代替
还有一个类似的题目:写一个”标准"宏MIN ,这个宏输入两个参数并返回较小的一个。
#define MIN(A,B) ((A) <= (B) ? (A) : (B)) 注意写法即可
下面的代码输出结果是什么?
@implementation Son : Father
- (id)init {
self = [super init];
if (self) {
NSLog(@"%@", NSStringFromClass([self class]));
NSLog(@"%@", NSStringFromClass([super class]));
}
return self;
}
@end
// 都是son。
self是类的隐藏参数,指向当前调用方法的这个类的实例。而 super 是一个 Magic Keyword, 它本质是一个编译器标示符,和 self 是指向的同一个消息接受者。
上面的例子不管调用[self class]还是[super class],接受消息的对象都是当前 Son *xxx 这个对象。
而不同的是,super是告诉编译器,调用 class 这个方法时,要去父类的方法,而不是本类里的。
当使用 self 调用方法时,会从当前类的方法列表中开始找,如果没有,就从父类中再找;
而当使用 super 时,则从父类的方法列表中开始找。然后调用父类的这个方法。
单例写法
+ (instancetype)sharedInstance {
static CJManage *manage = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manage = [[CJManage alloc] init];
});
return manage;
}
当然这种写法alloc,new,copy,mutableCopy方法不可以直接调用。个人认为没必要因为这就是单例就这样创建就好.
单例的问题:单例对象一旦建立,对象指针是保存在静态区的,单例对象在堆中分配的内存空间,会在应用程序终止后才会被释放。
单例类无法继承,因此很难进行类的扩展。另外还要注意循环引用问题.
下列代码输出什么
void test1() {
int a = 10;
void (^block)(void) = ^{
NSLog(@"a is %d", a);
};
a = 20;
block(); // 10
}
void test2(){
__block int a = 10;
void (^block)(void) = ^{
NSLog(@"a is %d", a);
};
a = 20;
block(); // 20
}
代码已给出答案,这是因为block所在函数中的,捕获自动变量。但是不能修改它,不然就是“编译错误”。
但是可以改变全局变量、静态变量、全局静态变量。
首先不能修改自动变量的值是因为:block捕获的是自动变量的const值,名字一样,不能修改
可以修改静态变量的值:静态变量属于类的,不是某一个变量。由于block内部不用调用self指针。所以block可以调用。
因此block不能修改自动变量的值,可以使用__block修饰符来解决。
网友评论