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

来源:互联网 发布:echarts.jar源码 编辑:程序博客网 时间:2024/05/02 04:59

前言:

      前两天在杭州东站附近参加了这家公司的笔试题,面试题有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;




        

0 0
原创粉丝点击