Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iTeaTime(技术清谈)【001期】【代号:海王】 #114

Open
ChenYilong opened this issue Apr 26, 2019 · 0 comments
Open

iTeaTime(技术清谈)【001期】【代号:海王】 #114

ChenYilong opened this issue Apr 26, 2019 · 0 comments

Comments

@ChenYilong
Copy link
Owner

ChenYilong commented Apr 26, 2019

iTeaTime(技术清谈)【001期】【代号:海王】



出题:微博@iOS程序犭袁
本期代号:海王



enter image description here


1.【问题】【iOS】请问前后台切换,会发生些什么,系统哪些方法会被调用,viewcontroller哪些方法会被调用
【答案】

在不考虑 APP 在后台被 kill 的情况:

进入后台:

方法 作用
applicationWillResignActive 点击 Home 键,app 开始准备进入后台,这个时候会进入该回调,意味着 app 被挂起,进程即将失去活跃。经过不严谨的测试,大约有 10 分钟左右的时间用来处理事务。
applicationDidEnterBackground 当 applicationWillResignActive 回调方法完全执行完毕后,会进入 applicationDidEnterBackground 。

进入前台:

方法 作用
applicationWillEnterForeground 在 app 未被杀死的情况下,点击 icon 再次进入 app,重新回到前台之前会先进入 applicationWillEnterForeground 回调
applicationDidBecomeActive applicationWillEnterForeground 执行完毕后,会进入 applicationDidBecomeActive 回调,正式回归活跃。

前后台切换,主要的坑点在于:VC中并没函数会调用,尤其注意:VC 相关的 Appear 和 Disappear 函数并不会被调用。想在VC中监听切换,只能监听通知,每个在appdelegate的生命代理方法都有对应的通知。

如果考虑 APP 在后台被 kill 的情况:

进入后台后,如果没有后台运行权限及功能,可能在一段时间后被系统 kill 掉,再次进入app后,会重新进入启动流程。

方法 作用
main() 函数: 这个阶段一般是 可执行 .o 文件,动态库加载,objc 类注册,category 类注册,selector 唯一性检查,+(void)load 方法,C++ 静态全局变量的创建等。
didFinishLaunchingWithOptions 用户点击 icon 启动 app,或者被 kill 后以任何方式进入 app,在 main() 执行后,会进入 didFinishLaunchingWithOptions 回调,处理首屏渲染,以及其他业务相关的事件,例如监听事件,配置文件读写或者 SDK 初始化等等。
applicationDidBecomeActive 在 didFinishLaunchingWithOptions 方法作用域结束后,会进入 applicationDidBecomeActive 回调,也正式意味着 app 已经处于活跃状态。
rootViewController 的相关的 Appear 函数 注意:此时 rootViewController 的相关的 Appear 函数会被调用。

2 【问题】【iOS】请问对无序的Array排序,有什么好的方法,代码越少,API越高级越好。有无原生方法可以办到。

苹果为我们提供了很多 Array 的排序方法,但原理上可以看到就是 Comparator (比较器) 和 Descriptor (描述器) 两种,像是 Selector 和 Function ,最终也是使用 Comparator 在做排序,只是响应方法不同。

其中 Swift 也有方法: array.sort(),见 Apple Documentation-Swift-Array-sorted(by:)

先说说 Comparator ,如果数组中元素是 String 或 Number,首选 Comparator,可以将 compare: 方法的返回值直接作为 NSComparisonResult 返回值。实际的排序代码三行就可以搞定。当然用 Selector 和 Function,也是一样的效果,但需要写更多的代码。

例子一:

NSArray *sortedArray = [array sortedArrayUsingComparator:^NSComparisonResult(NSString *obj1, NSString *obj2) {
               if ([obj1 compare:obj2] == NSOrderedAscending) {
                   return NSOrderedAscending;
               } else if ([obj1 compare:obj2] == NSOrderedDescending){
                   return NSOrderedDescending;
               }else {
                   return NSOrderedSame;
               }
           }];

例子二:

- (void)arraySortUsingCompare {
   // 比较器 排序
   
   NSMutableArray *arr = [NSMutableArray array];
   for (int i = 0; i < 10; i ++) {
       int n = arc4random() % (10 - 0) + 1;
       [arr addObject:@(n)];
   }
   NSLog(@"排序前 ===== %@", arr);
   
   [arr sortUsingComparator:^NSComparisonResult(NSNumber *num1, NSNumber *num2) {
       //        return [num1 compare:num2];  // 正序
       return [num2 compare:num1]; // 倒序
       
   }];
   
   NSLog(@"排序后 %@", arr);
   
   
   arr = [NSMutableArray array];
   [arr addObject:@"Kobe Bryant"];
   [arr addObject:@"LeBorn James"];
   [arr addObject:@"Steve Nash"];
   [arr addObject:@"Stephen Curry"];
   [arr addObject:@"Monkey D Luffy"];
   [arr addObject:@"Roronoa Zoro"];
   
   NSLog(@"排序前 ==== %@", arr);
   
   [arr sortUsingComparator:^NSComparisonResult(NSString *str1, NSString *str2) {
       //        return [str1 compare:str2];  // 正序
       return [str2 compare:str1]; // 倒序
   }];
   
   NSLog(@"排序后 %@", arr);
}

可参考: 《Objective—C中的排序及Compare陷阱》

但是如果需要针对一个对象的几个属性作为不同的维度去做排序,那选择 Descriptor,因为不需要根据利用属性对排序优先级写一大堆的逻辑判断。主要将所有参与比较的属性都放入描述器中即可,如果想对球员的年龄和号码(优先级分先后)进行排序,只需要依次加入描述器组,三行代码就可以完成。

- (void)arraySortUsingDescriptor {
   NSMutableArray *arr = [NSMutableArray array];
   
   Person *person = [[Person alloc] init];
   person.name = @"Ingram";
   person.age = 21;
   person.number = 14;
   
   [arr addObject:person];
   
   person = [[Person alloc] init];
   person.name = @"Ball";
   person.age = 21;
   person.number = 2;
   
   [arr addObject:person];
   
   person = [[Person alloc] init];
   person.name = @"Zubac";
   person.age = 21;
   person.number = 15;
   
   [arr addObject:person];
   
   NSSortDescriptor *ageDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:YES];
   NSSortDescriptor *numberDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"number" ascending:YES];
   [arr sortUsingDescriptors:@[numberDescriptor, ageDescriptor]];
   
   for (Person *person in arr) {
       NSLog(@"\n 球员姓名: %@ \n 球员号码: %d \n 球员年龄: %d \n -------- \n", person.name, person.number, person.age);
       
   }
}

3【问题】【iOS】请问APNs推送如何区分设备,如何将设备的信息传给Apple,你上传的时机时怎样的,猜想这个设备信息是如何生成的

【答案】

【设备信息传递给apple】
post请求;
Use HTTP/2 and TLS 1.2 or later to establish a connection between your provider server and one of the following servers:
• Development server: api.sandbox.push.apple.com:443
• Production server: api.push.apple.com:443

也就是:

设备信息是通过一个 POST 请求将 DeveiceToken 和其他信息发送给 APNS,需要用 HTTP/2 和 TLS 1.2 或以上的版本,在自己提供的服务和以上服务之间建立连接。

  • 开发环境: api.sandbox.push.apple.com:443
  • 生产环境:api.push.apple.com:443

当然,还可以用一台机器的 2197 端口让 APNS 通过防火墙

请求示例:

HEADERS
 - END_STREAM
 + END_HEADERS
 :method = POST
 :scheme = https
 :path = /3/device/00fc13adff785122b4ad28809a3420982341241421348097878e577c991de8f0
 host = api.sandbox.push.apple.com
 authorization = bearer eyAia2lkIjogIjhZTDNHM1JSWDciIH0.eyAiaXNzIjogIkM4Nk5WOUpYM0QiLCAiaWF0I
    jogIjE0NTkxNDM1ODA2NTAiIH0.MEYCIQDzqyahmH1rz1s-LFNkylXEa2lZ_aOCX4daxxTZkVEGzwIhALvkClnx5m5eAT6
    Lxw7LZtEQcH6JENhJTMArwLf3sXwi
 apns-id = eabeae54-14a8-11e5-b60b-1697f925ec7b
 apns-expiration = 0
 apns-priority = 10
 apns-topic = com.example.MyApp
DATA
 + END_STREAM
 { "aps" : { "alert" : "Hello" } }

【上传时机】didRegisterForRemoteNotificationsWithDeviceToken 方法,回调内处理设备信息上传的业务。但有些情况是,我们希望根据用户账号来做推送,例如即时通讯应用。那么我们就要在登录或自动登录后,上传deviceToken,和用户信息绑定并处理替换逻辑,避免推送错乱。

【设备信息】This address takes the form of a device token unique to both the device and your app.

猜测:UDID+bundleId+生产/开发环境+时间戳。

其中注意带时间戳hash是为什么频繁上传device token的主要原因。长期不活跃app,比如用户一个月或者两个月没打开过该app,该服务器后端就再也推不到了。


4【问题】【前端】js中,this指向性问题如何解决。
【答案】「.bind(this) 或 用箭头函数」「const that = this;」


5【算法】我如果说我每天都在处理昨天和前天产生的bug,那么我是一个什么类型的程序员。
【答案】斐波那契程序员,这个梗可以参考:斐波那契数列。


Posted by 微博@iOS程序犭袁
原创文章,版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0


One more thing...

【非礼勿视】以下为彩蛋部分,建议28岁以上男性观看


image

@ChenYilong ChenYilong changed the title 微信群面试题第一期 微信群面试题第001期 May 10, 2019
@ChenYilong ChenYilong changed the title 微信群面试题第001期 微信群面试题【001期】 May 10, 2019
@ChenYilong ChenYilong changed the title 微信群面试题【001期】 微信群面试题【001期】【已过期】 May 13, 2019
@ChenYilong ChenYilong changed the title 微信群面试题【001期】【已过期】 技术清谈【001期】【已过期】 May 26, 2019
@ChenYilong ChenYilong changed the title 技术清谈【001期】【已过期】 iTeaTime(技术清谈)【001期】【已过期】 Jul 10, 2019
@ChenYilong ChenYilong changed the title iTeaTime(技术清谈)【001期】【已过期】 iTeaTime(技术清谈)【001期】【代号:海王】 Jul 12, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant