mirror of
https://github.com/NohamR/knowledge-kit.git
synced 2026-05-24 20:00:37 +00:00
135 lines
8.4 KiB
Markdown
135 lines
8.4 KiB
Markdown
# Xcode 小技巧
|
||
|
||
1. 快速打开:**Command+Shift+O** 。这个命令可以开启一个小窗格用来快速搜索浏览文件、类、算法以及函数等,且支持模糊搜索,这个命令可以说是日常开发中最常用的一个命令了。
|
||
|
||
2. 显示项目导航器:**Command+Shift+J**。使用快速打开命令跳转到对应文件后,如果需要在左侧显示出该文件在项目中的目录结构,只需要键入这个命令,非常方便
|
||
|
||
3. 显示编辑历史。如果一行代码写的很好或者很糟糕,不需要专门跑到 diff 工具去查看代码历史。在该行代码处右击,选择**Show Last Change For Line**
|
||
|
||
4. 跳转到方法。在使用类或者结构时,我们经常需要快速的跳转到类的某个特定方法。通过快捷键**control+6**再输入方法的头几个字母就可以非常方便的做到这点。
|
||
|
||
5. 范围编辑。多光标是个很棒的并且每个高级的编辑器都该有的特训过,快捷键为**Command+Control+E**。将光标移动刀需要编辑的符号,输入快捷键,然后就可以在当前页面全局编辑了。
|
||
|
||
6. Xcode 设置代码只在 Debug 下起效的几种方式
|
||
在日常开发中 Xcode 在 Debug 模式下写很多测试代码,或者引入一些第三方测试用的 .a 和 .framework 动态库,也会通过 CocoaPods 引入一些第三方测试工具或者库;但是不希望这些库在**Release**正式包中被引入,如何做到呢?
|
||
* .h/.m 文件中的测试代码
|
||
|
||
Xcode 在 Debug 模式下定义了宏 DEBUG=1 ,所以我们可以在代码中把相关的测试代码写在预编译处理命令 **\#ifdef DEBUG... \#endif** 中间即可,如图所示
|
||
|
||

|
||
|
||

|
||
|
||
* 测试用的 .a 和 .framework
|
||
|
||
对于拖拽到工程中的 .a .framework 静态库,可以在 **target->Build Settings->Search Paths**这2个选项,分别设置 **Library Search Paths**和**Framework Search Paths**这2个选项。如果我们需要在测试的时候会用到,那么我们可以将 **Debug** 对应的值留下,删掉**Release** 对应的值。这样我们打包 Release 包的时候就不会包含不需要的包。
|
||
|
||

|
||
|
||
* CocoPods 引入的库
|
||
对于 CocoPods 方式引入的库,在配置的时候就可以处理掉,比如下面的方式
|
||
|
||
```
|
||
platform: iOS, '8.0'
|
||
...
|
||
pod 'PonyDebugger', :configurations => ['Debug']
|
||
```
|
||
7. App Store Connect 经常在上架的时候需要开发人员判断是否满足出口合规的证明,每次写都很麻烦,所以可以在工程里面的 plist 里面进行设置。
|
||
|
||
```
|
||
<key>ITSAppUsesNonExemptEncryption</key>
|
||
<false/>
|
||
```
|
||
|
||
8. 让 Xcode 折叠代码
|
||
在 VS Code 或者其他 IDE 里面都具有代码折叠的功能,Xcode 也支持代码折叠功能,但是默认没有开启。所以我们需要做的就是打开代码折叠功能。步骤:打开 Xcode - Preference - Text Editing - 在「Show」模块下面勾选「Code folding ribbon」。这样 Xcode 就具备代码折叠的功能了。
|
||
快捷键:
|
||
- command + option + 左右方向键 : 折叠或展开鼠标光标所在位置的代码
|
||
- command + option + shift + 左右方向键:折叠或展开当前页面全部的方法(函数)
|
||
9. 几种设置废弃 Api 的方法
|
||
- __deprecated
|
||
|
||
- NS_UNAVAILABLE。`- (instancetype)init NS_UNAVAILABLE;`
|
||
|
||
- #define MJRefreshDeprecated(instead) NS_DEPRECATED(2_0, 2_0, 2_0, 2_0, instead)
|
||
|
||
```
|
||
MJRefreshDeprecated("请使用automaticallyChangeAlpha属性");
|
||
```
|
||
|
||
- DEPRECATED_ATTRIBUTE
|
||
|
||
```
|
||
@property (nonatomic, strong, readonly) UILabel *dateLabel DEPRECATED_ATTRIBUTE;
|
||
```
|
||
|
||
- DEPRECATED_MSG_ATTRIBUTE
|
||
|
||
```
|
||
@property (nonatomic, assign) NSStringEncoding stringEncoding DEPRECATED_MSG_ATTRIBUTE("The string encoding is never used. AFHTTPResponseSerializer only validates status codes and content types but does not try to decode the received data in any way.");
|
||
```
|
||
|
||
- @property(nullable, nonatomic, strong) IBOutlet NSLayoutConstraint *IQLayoutGuideConstraint __attribute__((deprecated("Due to change in core-logic of handling distance between textField and keyboard distance, this layout contraint tweak is no longer needed and things will just work out of the box regardless of constraint pinned with safeArea/layoutGuide/superview.")));
|
||
|
||
- + (CLLocationDistance)getCurrentLocationDistanceFilter __deprecated_msg("废弃方法(空实现),使用distanceFilter属性替换");
|
||
|
||
- + (NSString *)getWeiboAppSupportMaxSDKVersion __attribute__((deprecated));
|
||
|
||
- #pragma clang diagnostic push
|
||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||
|
||
result = [self sizeWithFont:font constrainedToSize:size lineBreakMode:lineBreakMode];
|
||
|
||
#pragma clang diagnostic pop
|
||
10. Xcode Instruments 内存泄漏检测工具 Leaks 在内存检测后,无法看到具体的堆栈信息。
|
||
|
||

|
||
|
||
涂上右下方的 `Heaviest Stack Trace` 模块看不到对应的堆栈信息。一番定位问题后发现是工程项目在 debug 阶段,Build Setting 中的 **Debug Information Format** 选项的 debug 条目是没有 dSYM 文件的,我们要想看到堆栈信息,就必须选择 `DWARF with dSYM File` 选项。
|
||
|
||

|
||
|
||
DWARF,即 ***Debug With Arbitrary Record Format*** ,是一个标准调试信息格式,即调试信息。这部分信息可以查看我的[这篇文章](./1.74.md)中讲 iOS 符号化的部分。
|
||
|
||
11. 将 OC 代码还原为 C++ 代码
|
||
|
||
```objectivec
|
||
// 方法1
|
||
clang -rewrite-objc xxxx.m -o xxxx.cpp
|
||
// 方法2
|
||
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc xxxx.m -o xxxx.cpp
|
||
```
|
||
|
||
12. 工程打开汇编,Debug 更多信息
|
||
|
||
菜单栏:Xcode -> Debug -> Debug Workflow -> Always Show Disassembly 可以查看汇编。
|
||
|
||
查看汇编可以从更深层了解当前函数的汇编层面的执行,为 objc 源码分析提供信
|
||
息避免方向性错误,结合 memory read 可以更清楚的看到寄存器之间是如何互相配合
|
||
处理配合的;使用汇编查看流程,可以在不确定源码出处和执行流程的情况下,跟踪内
|
||
部代码,并可以找到出处!同时,结合下符号断点的方式,能够更清晰的跟踪源码实
|
||
现。
|
||
|
||
13. Xcode 运行项目,模拟器启动失败。报错 `Failed to start launchd_sim: could not bind to session, launchd_sim may have crashed or quit respond`
|
||
- 关闭Xcode,在终端中键入以下命令:sudo chmod 1777 /tmp
|
||
- 清理此路径中的dyld文件夹:/Library/Developer/CoreSimulator/Caches
|
||
- 重新启动Xcode,完成!
|
||
|
||
14. Xcode 自动设置 __nonnull.
|
||
升级到 Xcode 10 , 新建类的时候发现头文件中多了2个宏:
|
||
|
||
NS_ASSUME_NONNULL_BEGIN
|
||
NS_ASSUME_NONNULL_END
|
||
|
||
作用
|
||
这两个东西是Nonnull区域设置(Audited Regions) 。
|
||
这两个宏之间的代码里的所有简单指针对象都被默认为 ___nonnull,我们只需要去指定 __nullable 的指针。
|
||
|
||
2014 年的 Apple WWDC 发布了强语言 swift ,必须要指定一个对象是否为空。为了迎合swift,OC中增加了 __nullable 和 ___nonnull 用于指定对象是否为空。
|
||
每个属性、方法都指定 ___nonnull 和 __nullable 是一件非常繁琐的事。为了减轻开发工作量,苹果提供了两个宏:NS_ASSUME_NONNULL_BEGIN 和 NS_ASSUME_NONNULL_END 。这两个宏之间的代码里的所有简单指针对象都被默认为 ___nonnull,我们只需要去指定 __nullable 的指针。
|
||
|
||
解决的问题
|
||
|
||
- 减少冗余代码:避免在每个属性、方法参数或返回值前手动添加 nonnull,提高代码简洁性。
|
||
- 提升类型安全性:编译器会对默认的 nonnull 指针进行静态检查,传递 nil 时会触发警告。
|
||
- 改善 Swift 互操作性:Swift 能识别这些注解,将 nonnull 指针转换为非可选类型(如 String),将 nullable 指针转换为可选类型(如 String?),使接口更清晰。 |