当前位置: 首页 > 工具软件 > iOS Survey > 使用案例 >

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

董昕
2023-12-01

前言:

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




        

 类似资料: