面試題
1)@property 能使用哪些關(guān)鍵字、作用是什么;下面這4種寫法的區(qū)別?
@property (nonatomic, strong) NSArray *array0;//mutableArray copy 成array0時(shí),如果array0種的值被改了,會(huì)出什么問題呢
@property (nonatomic, copy) NSArray *array1;//常規(guī)寫法
@property (nonatomic, strong) NSMutableArray *array2;//標(biāo)準(zhǔn)寫法
@property (nonatomic, copy) NSMutableArray *array3;// 把Array mutablecopy 成 array3后,array3其實(shí)還是 Array對(duì)象,如果向其中插入對(duì)象的話,則會(huì)造成crash
copy的深淺拷貝只說是不正確的。
copy 是相對(duì)于mutablecopy來說,Array mutablecopy可以變成MutableArry, MutableArry可以copy成Array。同理還有NSdiction。
一個(gè)Array mutablecopy 成一個(gè) MutableArray后,Array里面的東西還是原來的東西,里面的元素并沒有重新new一個(gè)新的東西申請(qǐng)新的內(nèi)存,這個(gè)是淺拷貝,并不是之前說的深拷貝。
2) 下邊對(duì)象分別都在什么時(shí)候釋放
- (void)ARCProblem{
id obj0 = @"sunnyxx"; //會(huì)一直在
__weak id obj1 = obj0; //__weak obj1的地址指向obj0的對(duì)象,所以只要obj0不釋放obj1就不會(huì)被釋放
__strong id obj2 = [NSObject new];//obj2 會(huì)在用完的時(shí)候,obj2被釋放
__weak id obj3 = [NSObject new]; //obj3 在賦值之后就會(huì)被釋放,因?yàn)闆]有人強(qiáng)引用obj3,所以在這行結(jié)束 obj3就會(huì)被釋放
{
id obj4 = [NSObject new];// 在{}區(qū)域結(jié)束的時(shí)候會(huì)被釋放
}
__autoreleasing id obj5 = [NSObject new];// obj5是個(gè)自動(dòng)釋放的對(duì)象,obj5會(huì)被加到自動(dòng)釋放池中,會(huì)在一個(gè)最近的自動(dòng)釋放池中被釋放,如果是ARC外面有個(gè)autoreleasPool 則會(huì)在那個(gè)時(shí)候被釋放,如果是在viewdidload中,則會(huì)在runloop的autoreleasPool中釋放。
__unsafe_unretained id obj6 = self;//相當(dāng)于retain,obj6不會(huì)對(duì)self進(jìn)行影響,理論上obj6在任何時(shí)候都會(huì)被釋放。 unsafe不保證對(duì)象時(shí)刻都有,可能隨時(shí)銷毀。
}
3) 會(huì)發(fā)生什么
- (void)viewDidLoad {
[super viewDidLoad];
self.view = nil;
//view Did Load 是在view被load的時(shí)候被調(diào)用,self.view 是個(gè)懶加載的屬性,第一次在.view的時(shí)候,會(huì)load一下view相關(guān)方法,在加載完成后悔通知VC執(zhí)行viewDidLoad方法
// 所以在self.view = nil 的時(shí)候
// 很有可能出現(xiàn)遞歸,但是如果沒有再次調(diào)用 self.view 也可能不會(huì)出現(xiàn)遞歸,出現(xiàn)黑屏現(xiàn)象
}
4) block 循環(huán)引用的三種解決方案
//如何解決下面代碼的問題
- (void)blockRetainCycleProblem{
self.block = ^{
NSLog(@"%@",@[self]);
};
}
// ===== 三種解決辦法
- (void)blockRetainCycleProbleAnswer0{
__weak typeof(self) weakSelf;
self.block = ^{
NSLog(@"%@",@[weakSelf]);
};
}
- (void)blockRetainCycleProbleAnswer1{
__weak typeof(self) weakSelf;
self.block = ^{
__weak typeof(weakSelf) strongSelf = weakSelf;
NSLog(@"%@", @[strongSelf]);
// 確保在 block塊內(nèi) self不會(huì)被釋放, 如果放倒數(shù)組里帶出block區(qū)域,則可能造成crash,self可能被釋放掉
};
}
- (void)blockRetainCycleProbleAnswer2{
__weak typeof(self) weakSelf;
self.block = ^{
__weak typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
NSLog(@"%@",@[strongSelf]);
}
};
}
5)Block內(nèi)存管理Extension
///下面的 self 用不用weak
- (void)blockRetainCycleProblemExt{
// 下面的 self 用不用weak
[UIView animateWithDuration:1 animations:^{
self.view.frame = CGRectMake(1, 2, 3, 4);
// 這行block 是瞬間執(zhí)行的,在這行代碼走完,會(huì)立即調(diào)用這個(gè)block方法
}];
//那這個(gè)呢
[UIView animateWithDuration:1 delay:1000 options:0 animations:^{
self.view.frame = CGRectMake(4, 1, 2, 3);
// 這個(gè)也是瞬間執(zhí)行
} completion:nil];
}
6)代碼規(guī)范
#pragma mark - 代碼規(guī)范 (問題)
typedef enum {
UserSex_Man,
UserSex_Womain
}UserSex;
@interface UserModel : NSObject
@property(nonatomic, strong) NSString *name;
@property(assign, nonatomic) int age;
@property (nonatomic, assign) UserSex sex;
-(id)initUserModelWithUserName: (NSString*)name withAge:(int)age;
-(void)doLogIn;
@end
#pragma mark - 正確的代碼規(guī)范
typedef NS_ENUM(NSUInteger, XXUserGender) {
XXUserGenderUndefined,
XXUserGenderMale,
XXUserGenderFemale
};
@interface XXUserModel : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) int age;
@property (nonatomic, assign) XXUserGender gender;
-(instancetype)initWithUsername:(NSString *)name age:(NSInteger)age;
-(void)login;
@end