今天参加了某公司的面试,答得感觉懵逼的,下面是面试题
1.@import跟#include的区别
(1)#import指令是Object-C针对#include的改进版本,#import确保引用的文件只会被引用一次,这样就不会陷入递归包含的问题中。
(2)#import与@class二者的区别在于:
#import会链入该头文件的全部信息,包括实体变量和方法等;而@class只是告诉编译器,其后面声明的名称是类的名称,至于这些类是如何定义的,暂时不用考虑。在头文件中, 一般只需要知道被引用的类的名称就可以了。
不需要知道其内部的实体变量和方法,所以在头文件中一般使用@class来声明这个名称是类的名称。 而在实现类里面,因为会用到这个引用类的内部的实体变量和方法,所以需要使用#import来包含这个被引用类的头文件。
2.如何向类别中添加属性?
static char*PersonNameKey ="PersonNameKey";
//name是你在头文件中的属性名称,PersonNameKey就相当于是一个keyId了
- (void)setName:(NSString*)name {
objc_setAssociatedObject(self,PersonNameKey, name,OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString*)name {
return objc_getAssociatedObject(self,PersonNameKey);
}
//demo可以参见https://github.com/miliPolo/CategoryAddPropertyByRuntime
3.关于mrc模式下block内存泄露的问题
先看下面这段代码
@autoreleasepool {
Person *p = [[Person alloc] init];
p.age = 30;
void (^block) () = ^{
NSLog(@"%d", p.age);
};
Block_copy(block);
block();
[p release];
}
此时此刻,有人想对block进行release,但是不管你是否对block进行release ,都无法释放d对象。为什么呢??
这个时候,我们就要对block进行分析了:
1.默认情况下, block的内存是在栈中
*它不会对所引用的对象进行任何操作
2.如果对block做一次copy操作, block的内存就会在堆中
*它会对所引用的对象做一次retain操作*非ARC : 如果所引用的对象用了__block修饰, 就不会做retain操作*ARC : 如果所引用的对象用了__unsafe_unretained\__weak修饰, 就不会做retain操作
所以,只需要在Dog类前面加上__block即可!
4.block实现原理详解
先来看下面两份代码
(1).int age = 10;
void (^block)() = ^{
NSLog(@"%d", age);
};
age = 30;
block();//10
(2).__block int age = 10;
void (^block)() = ^{
NSLog(@"%d", age);
};
age = 30;
block();//30
两个结果是不一样的,为何呢?关键在于第二段代码变量age 使用__block进行修饰,第一段代码的变量age其实是值传递,而第二份代码是引用传递
block内部是调用了一个结构体中的函数:
static struct main_block_desc_0 {
size_t reserved;
size_t Block_size;
void (copy)(struct __main_block_impl_0, structmain_block_impl_0);
void (dispose)(struct __main_block_impl_0*);
}
5.iOS安全
主要涉及到三个方面:网络通信,本地文件和数据,源代码安全
网络通信方面:
1).禁止使用明文传输密码,正确的做法应该是这样:事先生成一对用于加密的公私钥,客户端在登录时,使用公钥将用户的密码加密后,将密文传输到服务器。服务器使用私钥将密码解密,然后加盐(Salt,在密码学中是指,通过在密码任意固定位置插入特定的字符串,让散列后的结果和使用原始密码的散列结果不相符,这个过程称之为“加盐”),之后再多次求MD5,然后再和服务器原来存储的用同样方法处理过的密码匹配,如果一致,则登录成功。这样的做法,保证黑客即使截获了加密后的密文,由于没有私钥,也无法还原出原始的密码。而服务器即使被黑客攻陷,黑客除了暴力尝试,也无法从加盐和多次MD5后的密码中还原出原始的密码。这样就保证了用户密码的安全。
2).防止通信协议被轻易破解
3).验证应用内的支付凭证
ProtoBuf
本地文件和数据安全
程序文件的安全
本地数据的安全
源代码的安全
6.iOS使用的第三方通讯库
xmpp
7.支付宝的支付流程
8.viewController的生命周期
init->loadView->viewDidLoad->viewWillAppear->viewDidAppear->viewWillDisappear->viewDidDisappear->viewDidUnload->dealloc
9.二维码扫描,相册权限判断
NSString*mediaType =AVMediaTypeVideo;// Or AVMediaTypeAudio
AVAuthorizationStatusauthStatus = [AVCaptureDeviceauthorizationStatusForMediaType:mediaType];
if(authStatus ==AVAuthorizationStatusRestricted){
NSLog(@"Restricted");
}elseif(authStatus ==AVAuthorizationStatusDenied){
UIAlertView*alert =[[UIAlertViewalloc]initWithTitle:@"无法启动相机"message:@"请在iPhone的“设置”-“隐私”-“相机”功能中,找到“聪明屋”打开相机访问权限"delegate:nilcancelButtonTitle:@"确定"otherButtonTitles:nil];
[alertshow];
return;
}
elseif(authStatus ==AVAuthorizationStatusAuthorized){//允许访问
QRCodeReaderViewController*reader = [[QRCodeReaderViewControlleralloc]init];
if(reader) {
reader.modalPresentationStyle=UIModalPresentationFormSheet;
__weaktypeof(self) wSelf =self;
[readersetCompletionWithBlock:^(NSString*resultAsString) {
[wSelfdismissViewControllerAnimated:YEScompletion:NULL];
self.textField.text= resultAsString;
}];
[selfpresentViewController:readeranimated:YEScompletion:NULL];
}
}elseif(authStatus ==AVAuthorizationStatusNotDetermined){
[AVCaptureDevicerequestAccessForMediaType:mediaTypecompletionHandler:^(BOOLgranted) {
if(granted){//点击允许访问时调用
//用户明确许可与否,媒体需要捕获,但用户尚未授予或拒绝许可。
NSLog(@"Granted access to %@", mediaType);
QRCodeReaderViewController*reader = [[QRCodeReaderViewControlleralloc]init];
if(reader) {
reader.modalPresentationStyle=UIModalPresentationFormSheet;
__weaktypeof(self) wSelf =self;
[readersetCompletionWithBlock:^(NSString*resultAsString) {
[wSelfdismissViewControllerAnimated:YEScompletion:NULL];
self.textField.text= resultAsString;
}];
[selfpresentViewController:readeranimated:YEScompletion:NULL];
}
}
else{
NSLog(@"Not granted access to %@", mediaType);
}
}];
}else{
NSLog(@"Unknown authorization status");
}
10.最近遇到一个非常坑爹的问题,我在用Reachability的时候,编译老是会出现先的错误,Duplicate interface definition for class ,一开始以为合代码的时候配置文件除了问题,我删了pods的东西,重新更新了一遍,但是并没有什么用。想了下#import不会交叉编译头文件啊,可是还是出现了重定义错误,我在代码里面搜了头文件就只有一个啊?这是开什么国际玩笑啊,后来在Finder里面重新搜了一下,果然在我合代码的时候,有份代码没有删除只是去除引用了,悲伤~~~
11.UITabBar改变默认高度
1.继承UITabBarController
@interfaceALTabBarController:UITabBarController
2.重写UITabBarController的UITabBarController方法
- (void)viewWillLayoutSubviews{CGRecttabFrame =self.tabBar.frame;//self.TabBar is IBOutlet of your TabBartabFrame.size.height=80; tabFrame.origin.y=self.view.frame.size.height-80;self.tabBar.frame= tabFrame;}
如果想要添加的工具条点击事件生效请在viewWillLayoutSubviews添加此代码
[self.tabBarbringSubviewToFront:self.bottomToolView];
12.UITextField placeholder的使用
我们有时需要定制化UITextField对象的风格,可以添加许多不同的重写方法,来改变文本字段的显示行为。这些方法都会返回一个CGRect结构,制定了文本字段每个部件的边界范围,甚至修改placeHolder颜色,字体。
– textRectForBounds://重写来重置文字区域
– drawTextInRect://改变绘文字属性.重写时调用super可以按默认图形属性绘制,若自己完全重写绘制函数,就不用调用super了.
– placeholderRectForBounds://重写来重置占位符区域
– drawPlaceholderInRect://重写改变绘制占位符属性.重写时调用super可以按默认图形属性绘制,若自己完全重写绘制函数,就不用调用super了
– borderRectForBounds://重写来重置边缘区域
– editingRectForBounds://重写来重置编辑区域
– clearButtonRectForBounds://重写来重置clearButton位置,改变size可能导致button的图片失真
– leftViewRectForBounds:
– rightViewRectForBounds:
通过– drawPlaceholderInRect:方法可改变placeHolder颜色、字体,请看代码:
首先定义一个类CustomTextField让它继承UITextField实现以下方法即可:
//控制清除按钮的位置
-(CGRect)clearButtonRectForBounds:(CGRect)bounds
{
returnCGRectMake(bounds.origin.x+ bounds.size.width-50, bounds.origin.y+ bounds.size.height-20,16,16);
}
//控制placeHolder的位置,左右缩20
-(CGRect)placeholderRectForBounds:(CGRect)bounds
{
//return CGRectInset(bounds, 20, 0);
CGRectinset =CGRectMake(bounds.origin.x+100, bounds.origin.y, bounds.size.width-10, bounds.size.height);//更好理解些
returninset;
}
//控制显示文本的位置
-(CGRect)textRectForBounds:(CGRect)bounds
{
//return CGRectInset(bounds, 50, 0);
CGRectinset =CGRectMake(bounds.origin.x+190, bounds.origin.y, bounds.size.width-10, bounds.size.height);//更好理解些
returninset;
}
//控制编辑文本的位置
-(CGRect)editingRectForBounds:(CGRect)bounds
{
//return CGRectInset( bounds, 10 , 0 );
CGRectinset =CGRectMake(bounds.origin.x+10, bounds.origin.y, bounds.size.width-10, bounds.size.height);
returninset;
}
//控制左视图位置
- (CGRect)leftViewRectForBounds:(CGRect)bounds
{
CGRectinset =CGRectMake(bounds.origin.x+10, bounds.origin.y, bounds.size.width-250, bounds.size.height);
returninset;
//return CGRectInset(bounds,50,0);
}
//控制placeHolder的颜色、字体
- (void)drawPlaceholderInRect:(CGRect)rect
{
//CGContextRef context = UIGraphicsGetCurrentContext();
//CGContextSetFillColorWithColor(context, [UIColor yellowColor].CGColor);
[[UIColororangeColor]setFill];
[[selfplaceholder]drawInRect:rectwithFont:[UIFontsystemFontOfSize:20]];
}
//下面是使用CustomTextField的代码,可放在viewDidLoad等方法中
_textField= [[CustomTextFieldalloc]initWithFrame:CGRectMake(20,150,280,30)];
_textField.placeholder=@"请输入帐号信息";
_textField.borderStyle=UITextBorderStyleRoundedRect;
_textField.textAlignment=UITextAlignmentLeft;
_textField.delegate=self;
_textField.clearButtonMode=UITextFieldViewModeWhileEditing;
_textField.text=@"aa";
UIImageView*imgv = [[UIImageViewalloc]initWithImage:[UIImageimageNamed:@"icon-iwant-2.png"]];
_textField.leftView= imgv;
_textField.leftViewMode=UITextFieldViewModeAlways;
[self.viewaddSubview:_textField];
//设置NavigationController跳转动画
/*
NSString *types[4] = {kCATransitionMoveIn, kCATransitionPush, kCATransitionReveal, kCATransitionFade};
NSString *subtypes[4] = {kCATransitionFromLeft, kCATransitionFromRight, kCATransitionFromTop, kCATransitionFromBottom};
//立方 吸走 翻转 水波 翻页 翻页回
NSString *moreTypes[]={@"cube",@"suckEffect",@"oglFlip",@"rippleEffect",@"pageCurl",@"pageUnCurl",@"cameraIrisHollowOpen",@"cameraIrisHollowClose"};
*/
CATransition *animation = [CATransition animation];
[animation setDuration:0.4];
[animation setType: @"oglFlip"];
[animation setSubtype: kCATransitionFromLeft];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
[self.navigationController.view.layer addAnimation:animation forKey:nil];
[self.navigationController popViewControllerAnimated:NO];
//设置Frame失效问题
如果有AutoLayout或者SizeClass,在Xib上的控件无法通过Frame修改位置。如果是手工创建的View,是可以通过Frame移动的。
如果要移动SizeClass,可以映射它的Constraint,在代码中修改Constraint.constant.
12.enumeration value not handled in switch
use default and break;
13 pod 导入第三方库后,使用import 不提示第三方库头文件。
解决办法:
选择target -> BuildSettings -> search Paths 下的 User Header Search Paths, 添加$(PODS_ROOT)
持续更新中...