您的位置:首页 > 移动开发 > IOS开发

iOS笔试题之杭州卓健科技有限公司

2016-07-18 19:58 671 查看

前言:

前两天在杭州东站附近参加了这家公司的笔试题,面试题有7面,题目都是蛮基础性的东西,但是有部分自己也忘了,所以就把题目整理一下,为下一次的笔试做准备。

一 选择题(共14题,每题3分)

1.以下变量名合法的是(A) A. it_is_OK B. a4 C. flag-type D. a/b/c

注释: 数字、字母、下划线,都可以为变量命名。做为变量名的开头不能为数字。

2.一下选项中,合法的赋值语句是 (C)

A. a == 1; B. int a = b = c = 5; C. int a = 3; D. a++;-

A == 为判断语句,值返回为0或1
B
在变量说明中,不允许连续给多个变量赋初值。必须写为: int a = 5; b = 5; c = 5;

D 自加加和自减减只能是常量
C语言赋值语句详解

3. int a = 27,b = 5,c = 10, d = 4;则 a/d*d+a%d+a/d 的值为(C)

A. 38 B. 36.75 C. 33 D. 37

4. #define SQUAKE(a) ((a++)*(++a))

int a= 5; int b = SQUAKE(a); 则b的值为 (C)

A. 25 B. 30 C.35 D.42

注释:程序是按照步骤来的,如果是a++的话,在那一行代码中,a的值是不变的,下一行才发生变化,++a则是在那一行已经发生了变化。

5. 若进栈序列为1,2,3,4,进栈过程中可以出栈,则下列不可能的一个出栈序列是(C)。

A 1.2.3.4 //长度为1,进一个,出一个

B 4.3.2.1 //长度为4,4个全部进,再一个个出

C 3.4.1.2 //长度为2,则为2,3,4,1

D 2.4.3.1 //长度为3,先进1,2出2,再进3,4之后出4,3最后出1

注释:栈是先进后出。

6. 关于Object-C内存管理机制错误的是 (C)

A. 当使用alloc方法创建对象,其计数器的值为1;

B. 调用retain方法时,其计数器的值增加1;

C. 使用copy方法创建对象时,其计数器的值减少1;

D. 当计数器为0时,系统自动调用dealloc方法来释放内存中的对象

7. Object-C声明一个类所用到的编译指令是(A)

A. @interface SomeClass B @protocol SomeClass C @implementation SomeClass D. @autorelease SomeClass

8. 使用protocol,声明一组可选择实现与否的函数时,需要在声明的前一行加上(B)

A. @required B. @optional C. @interface D. @protocol

9. 在UIKit中,frame与bounds的区别是(C)

A. frame 是 bounds 的别名 B. frame是bounds的继承类

C. frame的参考系是父视图坐标,bounds的参考系是自身的坐标

D. frame的参考系是自身的坐标,bounds的参考系是父视图的坐标

注释:bounds的原点是(0,0)点(就是view本身的坐标系统,默认永远都是0,0点,除非认为setbounds),而frame的原点却是任意的(相对于父视图中的坐标位置)。

10. 在一个UIViewController中,函数(A)

-(instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil; //----(1)

-(void)viewDidLoad; //----(2)

-(void)viewWillAppear:(BOOL)animated; //----(3)

-(void)viewDidAppear:(BOOL)animated; //----(4)

A. (1) (2) (3) (4) B. (3) (1) (2) (4) C. (3) (4) (1) (2) D. (1) (3) (4) (2)

-[ViewController initWithCoder:]
-[ViewController loadView]
-[ViewController viewDidLoad]
-[ViewController viewWillAppear:]
-[ViewController viewDidAppear:]
<div class="crayon-line crayon-striped-line" id="crayon-578db04378d4e988019045-2"><span class="crayon-o">*</span><span class="crayon-h"> </span><span class="crayon-v">xib</span><span class="crayon-o">/</span><span class="crayon-v">storyboard</span>:<span class="crayon-o">-</span><span class="crayon-v">initWithCoder</span><span class="crayon-o">:</span>,而非<span class="crayon-v">xib</span><span class="crayon-o">/</span><span class="crayon-v">storyboard</span>的是<span class="crayon-o">-</span><span class="crayon-v">initWithNibName</span><span class="crayon-v">:bundle</span><span class="crayon-o">:</span>然后<span class="crayon-o">-</span><span class="crayon-t ">init</span></div><div class="crayon-line" id="crayon-578db04378d4e988019045-3"><span class="crayon-o">*</span><span class="crayon-h"> </span><span class="crayon-o">-</span><span class="crayon-t ">loadView</span></div><div class="crayon-line crayon-striped-line" id="crayon-578db04378d4e988019045-4"><span class="crayon-o">*</span><span class="crayon-h"> </span><span class="crayon-o">-</span><span class="crayon-t ">viewDidLoad</span></div><div class="crayon-line" id="crayon-578db04378d4e988019045-5"><span class="crayon-o">*</span><span class="crayon-h"> </span><span class="crayon-o">-</span><span class="crayon-v">viewWillAppear</span><span class="crayon-o">:</span></div><div class="crayon-line crayon-striped-line" id="crayon-578db04378d4e988019045-6"><span class="crayon-o">*</span><span class="crayon-h"> </span><span class="crayon-o">-</span><span class="crayon-v">viewDidAppear</span><span class="crayon-o">:</span></div><div class="crayon-line" id="crayon-578db04378d4e988019045-7"><span class="crayon-o">*</span><span class="crayon-h"> </span><span class="crayon-o">-</span><span class="crayon-v">viewWillDisappear</span><span class="crayon-o">:</span></div><div class="crayon-line crayon-striped-line" id="crayon-578db04378d4e988019045-8"><span class="crayon-o">*</span><span class="crayon-h"> </span><span class="crayon-o">-</span><span class="crayon-v">viewDidDisappear</span><span class="crayon-o">:</span></div>


11. 代码段:

NSMutableString * str1 = [[NSMutableString alloc] initWithString:@"aabbcc"];
NSString * str2 = [str1 copy];
NSString * str3 = [str2 copy];
NSLog(@"%p",str1);               //......1
NSLog(@"%p",str2);               //......2
NSLog(@"%p",str3);               //......3
对注释标记中的1、2、3三行,()

A. 1、2、3输出结果相同 B. 1、2输出结果相同,并与3不同 C.2、3输出结果相同,并与1不同 D.1、2、3输出结果各不相同

注释:

打印输出结果为:

2016-07-18 21:32:09.833 笔试检测[5012:664031] 0x7fccaaf2a1b0
2016-07-18 21:32:09.834 笔试检测[5012:664031] 0xa006363626261616
2016-07-18 21:32:09.834 笔试检测[5012:664031] 0xa006363626261616
12. 需要在ARC风格编写和编译的Xcode项目中引入手动内存分配和释放的文件,需要在文件的Compier Flage 上添加参数 (C)

A. - shared B. - fno - objc - arc C. - fobjc - arc D. 无法直接加入,只能将其中的内存管理代码删除再加入

13. 在没有navigationController的情况下,要从一个ViewController切换带另一个ViewController,应该使用 (C)

A. [self.navigationController pushViewController:nextViewController animated:YES];

B. [self.view addSubview:nextViewController.view];

C. [self pushViewController:nextViewController animated:YES];

D. [self presentModalViewController:nextViewController animated:YES];

注释:

A 的话需要 NavigationController
B 的话需要使用 ViewController 容器

C使用模态视图(已经弃用)

D 也需要 NavigationController

14. 对于下面的代码(B)

@implementation TestViewController

-(void) setVar :(int)var{

self.var = var;

}

A. 应该将var synthesize B. 调用会出现死循环 C. 正常 D. 返回值错误

注释:应改为 _var = var;

二、填空题 (共4题,每题3分)

1. 面向对象的特征有 继承封装多态

2. 实例化一个UITableView对象时必须要实现的代理有

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath


3. 写一个“标准”宏MIN,这个宏输入两个参数返回较小的一个

#define MIN(A,B) ((A)<(B)?(A):(B))


4. 在使用Pods管理第三方软件是,需要更新某个第三方库时,一把会在终端进行操作的指令是 pod install
pod update


三、简答题 (共4题)

1. 谈谈iOS中assign,copy,retain之间的区别;以及weak和strong的区别;并说出这行代码写法有什么问题:

@property (copy) NSMutableArray * array;(9 分)

assign,copy,retain之间的区别:

assign:这个是简单赋值,不更改引用引用计数;

copy:建立引用计数为一的对象,然后释放旧对象;

retain:释放旧对象,将旧对象的值赋予输入对象,再提高输入对象的引用索引计数;

<pre name="code" class="objc">当把属性声明为retain时,setter和getter方法内部实现


- (void)setName:(NSString *)name{

if (_name != name) {

[ _name release];

_name = [name retain];

}

}

- (NSString *)name{

return [[ _name retain] autorelease];

}



当把属性声明为copy时,setter和getter方法内部实现<p>- (void)setName:(NSString *)name{</p><p>    if (_name != name) {</p><p>       [ _name release];</p><p>       _name = [name copy];</p><p>    }</p><p>}</p><p>- (NSString *)name{</p><p>    return [[ _name retain] autorelease];</p><p>}</p>


当把语义特性声明为assign时,setter和getter时方法内部实现

- (void)setName:(NSString *)name{

_name = name;

}

- (NSString *)name{

 return _name;
}


assign :是对oc基础数据类型(CGRect,CGPoint)和C数据类型(float int);

copy:是对字符串NSString;

retain:是对其他NSObject 和其子类;

weak和strong的区别:

参考李明杰老师的内存管理指南之strong和weak指针:ARC指南1 - strong和weak指针

这行代码有两个问题:

1、添加,删除,修改数组内的元素的时候,程序会因为找不到对应的方法而崩溃.因为copy就是复制一个不可变NSArray的对象;

2、使用了atomic属性会严重影响性能。

atomic是oc使用的一种线程保护技术,是为了防止在写未完成的时候被其他线程读取,造成数据错误,而这种机制是很耗资源的,在iphone这小型设备上如果没有使用多线程之 间的通讯,那么使用nonatomic是一个非常好的选择

注:

oc的内存管理,第一:retain copy都是在手动内存管理中,赋值oc对象常用的防止内存泄露的方法,当A 要赋值给B时,A完成赋值操作后,将自己release,而B则将自己原持有的对象地址release,并持有A的对象及引用计数,这样就保证两个数据块的引用计数始终为1或0,程序中最后一位引用者release时,才能保证这块内存被很好的释放;

2. 写一个方法,要求把一个二维数组转换为字典类型,要求数组中每个元素中的第一个元素(NSString * 类型)作key, 第二个元素作为Value。根据你写的代码,下面的测试用例会输出什么?(9 分)

NSArray * changeArray = @[@[@"key1",@"value1"],@"NSString",@[@"key3"],@[],@[@'A',@123.4]];

NSLog(@"GetDict = %@",[self changeArrayFromDictionary:changeArray]);

//方法代码:

- (NSDictionary *)changeArrayFromDictionary:(NSArray *)array{
NSMutableDictionary * mDic = [NSMutableDictionary dictionary];
for (NSArray * subArray in array) {
if (subArray.count >= 2) {
NSString * key = [NSString stringWithFormat:@"%@",subArray[0]];
NSString * value = [NSString stringWithFormat:@"%@",subArray[1]];
[mDic setValue:value forKey:key];
}else if (subArray.count == 1){
NSString * key = [NSString stringWithFormat:@"%@",subArray[0]];
[mDic setValue:nil forKey:key];
}
}
return mDic;
}


GetDict = {
65 = "123.4";
key1 = value1;
}


3. 怎样实现一个单例模式的类,需要注意什么,可以给出思路。(9 分)

在objective-c中要实现一个单例类,至少需要做以下四个步骤:

  1、为单例对象实现一个静态实例,并初始化,然后设置成nil,

  2、实现一个实例构造方法检查上面声明的静态实例是否为nil,如果是则新建并返回一个本类的实例,

  3、重写allocWithZone方法,用来保证其他人直接使用alloc和init试图获得一个新实力的时候不产生一个新实例,

  4、适当实现allocWitheZone,copyWithZone,release和autorelease。

下面以SurveyRunTimeData为例子:

static SurveyRunTimeData *sharedObj = nil; //第一步:静态实例,并初始化。
@implementation SurveyRunTimeData
+ (SurveyRunTimeData*) sharedInstance  //第二步:实例构造检查静态实例是否为nil
{
@synchronized (self)
{
if (sharedObj == nil)
{
[[self alloc] init];
}
}
return sharedObj;
}

+ (id) allocWithZone:(NSZone *)zone //第三步:重写allocWithZone方法
{
@synchronized (self) {
if (sharedObj == nil) {
sharedObj = [super allocWithZone:zone];
return sharedObj;
}
}
return nil;
}

- (id) copyWithZone:(NSZone *)zone //第四步
{
return self;
}


4. 现有AViewController和BviewController,AViewController中有textField和button两个控件,BviewController中有tableBiew,数据源为array,

元素为dictionary(key = name)。假如在AViewController中点击button(事件为touchAction)后,push到BviewController,要求在

BviewController中点击cell后,pop到AviewController,并在textField中展示所选cell的name,要求分别用delegate和block实现。

(请在下方代码中插入你的代码,button,textField,tableView可直接使用,无需再实例化)。(9分)

代理实现

AViewController.h

#import <UIKit/UIKit.h>

@interface AViewController : UIViewController

@end


AViewController.m

#import "AViewController.h"
#import "BViewController.h"

@interface AViewController () <BViewControllerDelegate>

@property (weak, nonatomic) IBOutlet UITextField *textField;

@property (weak, nonatomic) IBOutlet UIButton *button;

-(IBAction)touchAction:(id)sender;

@end

@implementation AViewController

- (void)viewDidLoad {
[super viewDidLoad];

}

-(IBAction)touchAction:(id)sender{
BViewController * BVc = [[BViewController alloc] init];
BVc.delegate = self;
[self.navigationController pushViewController:BVc animated:YES];

}

#pragma mark - BViewControllerDelegate
-(void)changeTextFieldText:(NSString *)text{
_textField.text = text;
}
BViewController.h

#import <UIKit/UIKit.h>

@protocol BViewControllerDelegate <NSObject>

-(void)changeTextFieldText:(NSString *)text;

@end

@interface BViewController : UIViewController

@property (nonatomic, strong) NSArray * dataArray;

@property (nonatomic, strong) id<BViewControllerDelegate> delegate;

@end


BViewController.m

#import "BViewController.h"

@interface BViewController ()<UITableViewDelegate,UITableViewDataSource>

@end

@implementation BViewController

- (void)viewDidLoad {
[super viewDidLoad];
self.dataArray = @[@{@"key":@"name1"},@{@"key":@"name2"},@{@"key":@"name3"},@{@"key":@"name4"},@{@"key":@"name5"}];

UITableView * table = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
table.delegate = self;
table.dataSource = self;
[self.view addSubview:table];

}

#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{

return self.dataArray.count;

}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

static NSString * cellIdentifier = @"cellIdentifier";

UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.textLabel.text = [self.dataArray[indexPath.row] objectForKey:@"key"];

return cell;
}

#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{

[self.delegate changeTextFieldText:[self.dataArray[indexPath.row] objectForKey:@"key"]];

[self.navigationController popViewControllerAnimated:YES];

}


Block实现

AViewController.h

#import <UIKit/UIKit.h>

@interface AViewController : UIViewController

@end
AViewController.m

#import "AViewController.h"
#import "BViewController.h"

@interface AViewController ()

@property (weak, nonatomic) IBOutlet UITextField *textField;

@property (weak, nonatomic) IBOutlet UIButton *button;

-(IBAction)touchAction:(id)sender;

@end

@implementation AViewController

- (void)viewDidLoad {
[super viewDidLoad];

}

-(IBAction)touchAction:(id)sender{
BViewController * BVc = [[BViewController alloc] init];

[BVc changeTextFieldText:^(NSString *text) {
_textField.text = text;
}];

[self.navigationController pushViewController:BVc animated:YES];

}


BViewController.h

#import <UIKit/UIKit.h>

typedef void(^ChangeTextBlock)(NSString * text);

@interface BViewController : UIViewController

@property (nonatomic, strong) NSArray * dataArray;

@property (nonatomic, copy) ChangeTextBlock changeTextBlock;

-(void)changeTextFieldText:(ChangeTextBlock)block;

@end


BViewController.m

#import "BViewController.h"

@interface BViewController ()<UITableViewDelegate,UITableViewDataSource>

@end

@implementation BViewController

- (void)viewDidLoad {
[super viewDidLoad];
self.dataArray = @[@{@"key":@"name1"},@{@"key":@"name2"},@{@"key":@"name3"},@{@"key":@"name4"},@{@"key":@"name5"}];

UITableView * table = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
table.delegate = self;
table.dataSource = self;
[self.view addSubview:table];

}

-(void)changeTextFieldText:(ChangeTextBlock)block{
self.changeTextBlock = block;
}

#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{

return self.dataArray.count;

}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

static NSString * cellIdentifier = @"cellIdentifier";

UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.textLabel.text = [self.dataArray[indexPath.row] objectForKey:@"key"];

return cell;
}

#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{

if (self.changeTextBlock != nil) {
self.changeTextBlock([self.dataArray[indexPath.row] objectForKey:@"key"]);
}

[self.navigationController popViewControllerAnimated:YES];

}


四、风格纠错题 (共1题)

请使用你认为比较规范的风格(书写规范、命名规范等)重写以下代码。(10)

#import "UserModel.h"

typedef enum{
UserSex_Man,
UserSex_Woman
}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;
-(id)doLogin;


优化部分
1)enum建议使用 NS_ENUM 和 NS_OPTIONS 宏来定义枚举类型,参见官方的 Adopting
Modern Objective-C 一文:
//定义一个枚举
typedef NS_ENUM(NSInteger, CYLSex) {
CYLSexMan,
CYLSexWoman
};


2)age属性的类型:应避免使用基本类型,建议使Foundation数据类型,对应关系如下:

int -> NSInteger
unsigned -> NSUInteger
float -> CGFloat
动画时间 -> NSTimeInterval
同时考虑到age的特点,应使用NSUInteger,而非int。 这样做的是基于64-bit 适配考虑,详情可参考博文《64-bit Tips》

3)如果工程项目非常庞大,需要拆分成不同的模块,可以在类、typedef宏命名的时候使用前缀。

4)doLogIn方法不应写在该类中:虽然LogIn的命名不太清晰,但笔者猜测是login的意思,而登录操作属于业务逻辑,观察类名UserModel,以及属性的命名方式,应该使用的是MVC模式,并非MVVM,在MVC中业务逻辑不应当写在Model中。(如果是MVVM,抛开命名规范,UserModel这个类可能对应的是用户注册页面,如果有特殊的业务需求,比如:login对应的应当是注册并登录的一个Button,出现login方法也可能是合理的。)

5)doLogIn方法命名不规范:添加了多余的动词前缀。 请牢记:
如果方法表示让对象执行一个动作,使用动词打头来命名,注意不要使用do,does这种多余的关键字,动词本身的暗示就足够了。
6)-(id)initUserModelWithUserName: (NSString*)name withAge:(int)age;方法中不要用with来连接两个参数:withAge:应当换为age:,age:已经足以清晰说明参数的作用,也不建议用andAge::通常情况下,即使有类似withA:withB:的命名需求,也通常是使用withA:andB:这种命名,用来表示方法执行了两个相对独立的操作(从设计上来说,这时候也可以拆分成两个独立的方法),它不应该用作阐明有多个参数,比如下面的:

//错误,不要使用"and"来连接参数
- (int)runModalForDirectory:(NSString *)path andFile:(NSString *)name andTypes:(NSArray *)fileTypes;
//错误,不要使用"and"来阐明有多个参数
- (instancetype)initWithName:(CGFloat)width andAge:(CGFloat)height;
//正确,使用"and"来表示两个相对独立的操作
- (BOOL)openFile:(NSString *)fullPath withApplication:(NSString *)appName andDeactivate:(BOOL)flag;


7)按照接口设计的惯例,如果设计了“初始化方法” (initializer),也应当搭配一个快捷构造方法。而快捷构造方法的返回值,建议为instancetype,为保持一致性,init方法和快捷构造方法的返回类型最好都用instancetype。

硬伤部分
1)在-和(void)之间应该有一个空格
2)enum中驼峰命名法和下划线命名法混用错误:枚举类型的命名规则和函数的命名规则相同:命名时使用驼峰命名法,勿使用下划线命名法。
3)enum左括号前加一个空格,或者将左括号换到下一行
4)enum右括号后加一个空格
5)UserModel :NSObject 应为UserModel : NSObject,也就是:右侧少了一个空格。
6)@interface与@property属性声明中间应当间隔一行。
7)两个方法定义之间不需要换行,有时为了区分方法的功能也可间隔一行,但示例代码中间隔了两行。
8)-(id)initUserModelWithUserName: (NSString*)name withAge:(int)age;方法中方法名与参数之间多了空格。而且- 与(id)之间少了空格。
9)-(id)initUserModelWithUserName: (NSString*)name withAge:(int)age;方法中方法名与参数之间多了空格:(NSString*)name前多了空格。
10)-(id)initUserModelWithUserName: (NSString*)name withAge:(int)age;方法中(NSString*)name,应为(NSString *)name,少了空格。
11)doLogIn方法命名不清晰:笔者猜测是login的意思,应该是粗心手误造成的。
12)第二个@property中assign和nonatomic调换位置。
修改后:

typedef NS_ENUM(NSInteger,WLUserSex) {
WLUserSexMan,
WLUserSexWoman
};

@interface UserModel : NSObject<NSCopying>

@property(nonatomic, copy, readonly) NSString *name;
@property(nonatomic, assign, readonly) NSUInteger age;
@property(nonatomic, assign, readonly) WLUserSex sex;

- (instancetype)initWithName:(NSString *)name age:(int)age sex:(WLUserSex)sex;

+ (instancetype)userWithName:(NSString *)name age:(int)age sex:(WLUserSex)sex;

-(id)login;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  iOS笔试题