贝壳

贝壳

一面:

1.SDK体积优化,从多大优化到了多大,为什么减少Masony的使用会减少包大小

2.加载速度优化,两套网络请求的问题

3.上传视频需要注意什么?视频很大,分片,内存占用

4.自动释放池,什么时候会加 autorelease,一个方法里,alloc一个对象,这个对象加了autorelease吗?如果这个方法返回了这个对象呢?自动释放池能嵌套吗?

5.循环引用,block什么时候循环引用,block用到了_xxx成员变量,会循环引用吗?成员变量会编译成什么 self ->

6.NSTimer的循环引用,为什么?

7.多线程:A/B/C并发,请求完成后执行其他任务

二面:

1.通用化技术提升迭代效率指的什么?卡片等是什么实现的

2.多线程:A -> B C -> D B依赖A、D依赖C,都完成后执行E

3.代理和block怎么选型?

4.页面传值一对多怎么实现?对象加到数组里,这个对象的引用计数增加了吗?weak呢?

5.SDWebImage原理,解码是在什么时候做的?一张图片加载到界面的过程,大图加载

6.设计:多个弹窗依次弹出,有优先级

三面:

1.iOS中遇到过的不易解决的问题,怎么解决的?

2.A -> B -> C 用路由的方式反向传值,什么是路由?什么时候注册?参数是什么类型?

3.autoreleasePool和Runloop的关系

4.mach-o了解吗?

参考答案

一面:

1.SDK体积优化,从多大优化到了多大,为什么减少Masony的使用会减少包大小

2.加载速度优化,两套网络请求的问题

3.上传视频需要注意什么?视频很大,分片,内存占用

在iOS开发中,网络请求上传视频是一个常见的需求,尤其是当视频文件较大时,更需要注意一系列的技术细节和优化手段以确保上传过程的稳定性、效率和用户体验。以下是一些关键的注意事项和优化手段:

注意事项

  1. 文件大小检测
    • 在上传前,先检查视频文件的大小,避免上传过大的文件导致内存溢出或上传时间过长。
  2. 网络状态检测
    • 检测用户的网络状态(如Wi-Fi、4G/5G等),根据网络状况调整上传策略,如在网络较差时暂停上传或提示用户。
  3. 用户反馈
    • 提供清晰的上传进度反馈,让用户了解上传的当前状态和预计剩余时间。
  4. 权限检查
    • 确保应用已获取必要的权限,如访问相册或相机权限,以便读取视频文件。

优化手段

  1. 视频压缩
    • 在上传前对视频进行压缩,减小文件大小,从而减少上传时间和占用的网络带宽。可以使用如FFmpeg等库进行视频转码和压缩。
  2. 分片上传
    • 将大视频文件分割成多个较小的片段,并行上传这些片段。这样可以显著提高上传速度,并降低因网络问题导致上传失败的风险。当所有片段都上传完成后,服务器端可以将这些片段合并成完整的视频。
  3. 断点续传
    • 支持断点续传功能,即在网络中断或应用退出等情况下,能在下次上传时从上次中断的地方继续上传,而不是重新开始上传整个视频。
  4. 适当设置HTTP头部
    • 设置合适的Content-Type,并确保HTTP头部中的其他字段(如Content-Length)正确无误。对于分片上传,每个片段请求都应有对应的头部信息。
  5. 使用合适的网络库
    • 利用成熟的网络库(如AFNetworking、URLSession等)来简化网络请求的代码量,并利用这些库提供的优化功能来提高上传效率。
  6. 缓存策略
    • 对于已上传的视频或片段,可以在本地缓存其状态和信息,以便在网络恢复或应用重启时快速恢复上传状态。
  7. 后台上传
    • 利用iOS的后台任务功能,在应用进入后台时继续上传视频,不影响用户的其他操作。
  8. 错误处理和重试机制
    • 实现完善的错误处理逻辑,当上传失败时,根据错误类型进行重试或提示用户。可以设置合理的重试次数和重试间隔。

综上所述,iOS网络请求上传视频时需要注意多个方面,并通过一系列优化手段来提高上传的效率和稳定性。这些优化手段不仅有助于提升用户体验,还能降低因网络问题导致的数据丢失风险。

4.自动释放池,什么时候会加 autorelease,一个方法里,alloc一个对象,这个对象加了autorelease吗?如果这个方法返回了这个对象呢?自动释放池能嵌套吗?

5.循环引用,block什么时候循环引用,block用到了_xxx成员变量,会循环引用吗?成员变量会编译成什么 self ->

6.NSTimer的循环引用,为什么?

7.多线程:A/B/C并发,请求完成后执行其他任务

二面:

1.通用化技术提升迭代效率指的什么?卡片等是什么实现的

2.多线程:A -> B C -> D B依赖A、D依赖C,都完成后执行E

3.代理和block怎么选型?

4.页面传值一对多怎么实现?对象加到数组里,这个对象的引用计数增加了吗?weak呢?

5.SDWebImage原理,解码是在什么时候做的?一张图片加载到界面的过程,大图加载

6.设计:多个弹窗依次弹出,有优先级

三面:

1.iOS中遇到过的不易解决的问题,怎么解决的?

2.A -> B -> C 用路由的方式反向传值,什么是路由?什么时候注册?参数是什么类型?

在iOS应用中通过路由机制进行页面导航和数据传递时,有时需要将数据从一个页面传递回到之前的页面。可以通过闭包(Block)来实现这种反向传值。下面是一个详细的示例,展示了如何通过路由机制进行反向传值。

示例:通过路由进行反向传值

假设我们有三个页面:A -> B -> C,并希望在C页面完成某些操作后将数据传回A页面。

1. 定义路由管理器

首先,我们需要一个路由管理器来管理导航和数据传递。我们将使用一个单例类Router来实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Router.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

typedef void (^CompletionHandler)(id data);

@interface Router : NSObject

+ (instancetype)sharedInstance;

- (void)registerPath:(NSString *)path forClass:(Class)className;
- (void)openPath:(NSString *)path withParams:(NSDictionary *)params completionHandler:(CompletionHandler)completionHandler;

@end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// Router.m
#import "Router.h"

@interface Router ()
@property (nonatomic, strong) NSMutableDictionary *routeMap;
@end

@implementation Router

+ (instancetype)sharedInstance {
static Router *instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[Router alloc] init];
});
return instance;
}

- (instancetype)init {
self = [super init];
if (self) {
_routeMap = [NSMutableDictionary dictionary];
}
return self;
}

- (void)registerPath:(NSString *)path forClass:(Class)className {
self.routeMap[path] = className;
}

- (void)openPath:(NSString *)path withParams:(NSDictionary *)params completionHandler:(CompletionHandler)completionHandler {
Class className = self.routeMap[path];
if (className) {
UIViewController *viewController = [[className alloc] init];
if ([viewController isKindOfClass:[UIViewController class]]) {
if (completionHandler) {
[viewController setValue:completionHandler forKey:@"completionHandler"];
}
[viewController setValuesForKeysWithDictionary:params];
[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:viewController animated:YES completion:nil];
}
} else {
NSLog(@"No route found for path: %@", path);
}
}

@end

2. 定义页面C

在C页面中定义一个回调Block,用于传递数据。

1
2
3
4
5
6
// CViewController.h
#import <UIKit/UIKit.h>

@interface CViewController : UIViewController
@property (nonatomic, copy) void (^completionHandler)(id data);
@end

在C页面完成操作时调用回调Block。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// CViewController.m
#import "CViewController.h"

@implementation CViewController

- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];

UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
button.frame = CGRectMake(100, 100, 100, 50);
[button setTitle:@"Send Data" forState:UIControlStateNormal];
[button addTarget:self action:@selector(sendData) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
}

- (void)sendData {
NSString *data = @"Some data from C";
if (self.completionHandler) {
self.completionHandler(data);
}
[self dismissViewControllerAnimated:YES completion:nil];
}

@end

3. 注册路由

在AppDelegate中注册路由。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// AppDelegate.m
#import "AppDelegate.h"
#import "Router.h"
#import "AViewController.h"
#import "BViewController.h"
#import "CViewController.h"

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[Router sharedInstance] registerPath:@"a" forClass:[AViewController class]];
[[Router sharedInstance] registerPath:@"b" forClass:[BViewController class]];
[[Router sharedInstance] registerPath:@"c" forClass:[CViewController class]];

self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.rootViewController = [[AViewController alloc] init];
[self.window makeKeyAndVisible];

return YES;
}

4. 使用路由

在A页面中导航到C页面并处理回调。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// AViewController.m
#import "AViewController.h"
#import "Router.h"

@implementation AViewController

- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];

UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
button.frame = CGRectMake(100, 100, 100, 50);
[button setTitle:@"Go to C" forState:UIControlStateNormal];
[button addTarget:self action:@selector(openCViewController) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
}

- (void)openCViewController {
[[Router sharedInstance] openPath:@"c" withParams:@{} completionHandler:^(id data) {
NSLog(@"Received data: %@", data);
// 处理接收到的数据
}];
}

@end

总结

通过以上步骤,你可以实现页面间的数据传递和反向传值。路由管理器负责管理页面的导航和数据传递,页面C通过回调Block将数据传回A页面。这种方法不仅简化了页面间的数据传递,还保持了代码的清晰和可维护性。

3.autoreleasePool和Runloop的关系

4.mach-o了解吗?

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×