文章目录
今天早上更新了电脑系统10.15.4 (19E287),下载了最新的Xcode,Version 11.4 (11E146),尝试使用了一下,Xcode 11.4有哪些变化呢?
1. The subversion command line tools are no longer provided by Xcode
看了下command line tools的安装目录/资源库/Developer/
,发现里面没有command line tools。
这个不是Xcode11.4的问题,xcode-select是Xcode内置的开发者工具,里面支持git、svn命令行等。
如果第一次下载Xcode没有安装的话会报这个问题。解决方案就是打开终端执行如下命令更新xcode-select。
xcode-select --install
安装就可以了。
2. 工程默认文件多了个SceneDelegate
感觉这个挺好的,设计挺合理,AppDelegate管理App,SceneDelegate管理UI相关的代码,相当于代码解耦了。
3. Main()函数的改变
int main(int argc, char *argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, NSStringFromClass([UIApplication class]), NSStringFromClass([AppDelegate class]));
}
}
iOS13
int main(int argc, char * argv[]) {
NSString * appDelegateClassName;
@autoreleasepool {
// Setup code that might create autoreleased objects goes here.
appDelegateClassName = NSStringFromClass([AppDelegate class]);
}
return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
好像没啥变化,UIApplicationMain()这个函数为什么不放在@autoreleasepool里?会不会有什么问题呢?
另外一个改变是iOS13 UIApplicationMain()函数的第三个参数传了空值。iOS 13之前此函数传UIApplication作为主体类,iOS13这里传nil的话,会创建UIApplication的实例,这里不传,也可以在info.plist里面设置主体类,如果你要复写UIApplication这个类并把它作为程序的主体类的话。
4. 新增了一些类和方法
iOS 13里面新增了一些类
如UIScene系列的类:
UIScene
UISceneSession
UISceneConnectionOptions
UISceneConfiguration
UISceneDelegate
等...
5. 程序启动顺序
先到AppDelegate的application:didFinishLaunchingWithOptions:方法里
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return YES;
}
然后到SceneDelegate的scene:willConnectToSession:
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
}
这里的scene是UIWindowScene的一个实例。
再到SceneDelegate的sceneWillEnterForeground:
- (void)sceneWillEnterForeground:(UIScene *)scene {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
再到SceneDelegate的sceneDidBecomeActive:
- (void)sceneDidBecomeActive:(UIScene *)scene {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}
主界面就展示出来了。
感觉SceneDelegate里面的几个关于程序生命周期的相关方法,和AppDelegate里面的其实是一样一样的,只是两处回调,用户自己看着各自处理各自的事情。SceneDelegate里处理与试图有关的业务,AppDelegate里处理与App进程有关的业务。
6. 关于window
iOS13新加了SceneDelegate类,将window放在了这个类里面,这样我们对window的创建等都应该放在此类里完成,而AppDelegate专心负责别的事务,分工合理,明白,业务解耦的相当完美。
如果不喜欢使用Main.storyboard这个入口还是可以直接删掉,用代码来实现主window的创建和显示。
于是乎我删除了Main Interface选项下的Main
按照之前创建window的方式在SceneDelegate的scene:willConnectToSession: options:下添加了代码,运行了一下程序闪退了,问题见 7 删除Main.storyboard中的描述。
删除Main Interface那里的Main,但是程序还是走Main.storyboard,因为plist中的Main.storyboard配置没被删除
这可能是Xcode的坑,删除plist文件的配置后还是闪退,详情看6的描述。
7. 删除Main.storyboard
只删除Main Interface下的main是不行的,起码Xcode Version 11.4 (11E146) 是不行的,会闪退
2020-04-15 14:34:28.955349+0800 MyTest[30217:548573] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Could not find a storyboard named 'Main' in bundle NSBundle </Users/encompass/Library/Developer/CoreSimulator/Devices/5CF2559E-0CFD-4703-923A-901D732C1978/data/Containers/Bundle/Application/A075E79E-E73A-4326-8E2F-2B8654648780/MyTest.app> (loaded)'
还需要删除plist问价中Main.storyboard的相关配置
Main storyboard file base name
都删除后,按照iOS 13之前创建window的方式添加了代码,只是这回放在了SceneDelegate里面,程序还是闪退了但是出现了黑屏的情况,而且我设置了window的背景色为白色啊。
改了一下代码,必须设置windowScene,否则会黑屏。
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
//self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window = [[UIWindow alloc] initWithWindowScene:(UIWindowScene *)scene];
self.window.backgroundColor = [UIColor whiteColor];
ViewController *naviRootVc = [[ViewController alloc] init];
UINavigationController *windowRootVc = [[UINavigationController alloc] initWithRootViewController:naviRootVc];
self.window.rootViewController = windowRootVc;
[self.window makeKeyAndVisible];
}
这里找到了为什么黑屏的原因,看注释
// If nil, window will not appear on any screen.
// changing the UIWindowScene may be an expensive operation and should not be done in performance-sensitive code
@property(nullable, nonatomic, weak) UIWindowScene *windowScene API_AVAILABLE(ios(13.0));
If nil, window will not appear on any screen.
8. 黑屏问题
// If nil, window will not appear on any screen.
// changing the UIWindowScene may be an expensive operation and should not be done in performance-sensitive code
@property(nullable, nonatomic, weak) UIWindowScene *windowScene API_AVAILABLE(ios(13.0));
If nil, window will not appear on any screen.
黑屏归根结底是因为UIWindowScene的设置出了问题,需要检查两处:
- Window的创建
self.window = [[UIWindow alloc] initWithWindowScene:(UIWindowScene *)scene];
- Info.plist配置
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>MMSceneDelegate</string>
</dict>
</array>
</dict>
</dict>
特别是改了SceneDelegate名后,进行全局替换,要注意上面的UISceneDelegateClassName也会被改,这里的key不能改,系统根据这个找对应的SceneDelegate。
例如我这里将SceneDelegate改成了MMSceneDelegate,结果运行后发现黑屏,代码根本没有执行到MMSceneDelegate这个文件。看了下这里的UISceneDelegateClassName,原来这个key在全局替换中被改成了MMSceneDelegateClassName,这个是不可以的。
9. Could not launch “xxx”
Details:
Details
Could not launch “xxx”
Domain: IDEDebugSessionErrorDomain
Code: 3
Failure Reason: xx iPad has denied the launch request.
Internal launch error: process launch failed: Unspecified
User Info: {
DVTRadarComponentKey = 855031;
RawLLDBErrorMessage = "process launch failed: Unspecified";
}
--
System Information
macOS Version 10.15.4 (Build 19E287)
Xcode 11.4.1 (16137)
TERGET->Building Setting->Linking->Mach-O-Type,改成Executable。
10. dyld: Library not loaded:
修改Podfile,注释掉use_frameworks!添加use_modular_headers!,重新pod install。
target 'Test-1' do
# Comment the next line if you don't want to use dynamic frameworks
# use_frameworks!
use_modular_headers!
# Pods for Test-1
pod 'AFNetworking', '~> 4.0'
end
别用framwork了,使用静态库不会闪退,谁知道是什么鬼。
11. 关于MD5
MD5不安全这个说了好久了,在iOS13里,如果使用MD5,Xcode会报警告:
'CC_MD5' is deprecated: first deprecated in iOS 13.0 - This function is cryptographically broken and should not be used in security contexts. Clients should migrate to SHA256 (or stronger).
不推荐使用“ CC_MD5”:在iOS 13.0中首先不推荐使用-此功能在密码上已损坏,不应在安全上下文中使用。 客户应迁移到SHA256(或更高版本)。
12. UITextField不显示内容
这个是在iPad13.4.1上发现的一个问题,如果初始化UITextField不设置textColor的话,可能会出现再赋值的时候,字体不显示的问题。但是奇怪的是我们项目之前一直是好的,就在13.4.1上发现了这个问题,也不知道是不是系统问题,暂且记下吧。
后来找到具体原因了,在iOS13上如果UITextField不设置字体颜色的话,在黑暗模式下,字体是不显示的,所以设置个textColor吧。
其他有什么新的发现持续更新…