# 基础篇

下载Xcode:https://developer.apple.com/download/more/?name=Xcode 或者打开Mac App Store

# 工具篇

# 开发及调试工具

# Xcode内置调试技巧

Xcode 10.2.1 新增的 vppo更快哟

UIWindow里有一个名为_autolayoutTrace的私有方法,可以打印视图层级:

po [[UIWindow keyWindow] _autolayoutTrace]

# Injection III

Xcode Injection (opens new window) :代码注入,Cmd+S 即可查看修改后的效果,不用重新编译运行

使用方法(Swift代码,OC自己转,Xcode 10.2 and later):

#if DEBUG
Bundle(path: "/Applications/InjectionIII.app/Contents/Resources/iOSInjection.bundle")?.load()
//for tvOS:
Bundle(path: "/Applications/InjectionIII.app/Contents/Resources/tvOSInjection.bundle")?.load()
//Or for macOS:
Bundle(path: "/Applications/InjectionIII.app/Contents/Resources/macOSInjection.bundle")?.load()
#endif

Objc:

[[[NSBundle alloc] initWithPath:@"/Applications/InjectionIII.app/Contents/Resources/iOSInjection.bundle"] load];

可下载作者博客Demo (opens new window)体验,注意:工程组好不要放在 Desktop 或 Documents 路径下

# 拥抱CocoaPods 1.7.x

#启动 CDN 支持,以避免在本地机器或 CI 系统上克隆 master specs repo,让使用 CocoaPods 更加方便
#现在你可以删除电脑的~/.cocoapods/repos/master 文件夹,以节省844M磁盘空间
#source 'https://cdn.jsdelivr.net/cocoa/'  #这个测试了不管用
source 'https://cdn.cocoapods.org/'

platform :ios, 9.0

#禁止所有来自CocoaPods的警告
inhibit_all_warnings!

install! 'cocoapods',
#1.7新特性:生成多个 Xcodeproj(因为Pods.xcodeproj 文件越大,Xcode 用于解析其内容的时间越长,这会降低 Xcode 的使用体验)
generate_multiple_pod_projects: true,
#1.7新特性:增量安装(仅重新生成自上次安装以来已更改的pod目标,每次pod install可以节省几秒钟到几分钟的时间)
incremental_installation: true

target 'PandaNote' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for PandaNote
  pod 'Alamofire'
  pod 'FilesProvider'
  pod 'SnapKit'
  pod 'Down'
  pod 'DoraemonKit/Core'

  
  target 'PandaNoteTests' do
    inherit! :search_paths
    # Pods for testing
  end

  target 'PandaNoteUITests' do
    inherit! :search_paths
    # Pods for testing
  end

end
pod "WechatOpenSDK", :inhibit_warnings => true#,'1.8.4'

kangzubin的博客1.7beta介绍 (opens new window)

CocoaPods-1.7.2官方介绍如何使用CDN (opens new window)

# LLDB 调试工具Chisel

Chisel (opens new window)是Facebook出品的(一个灰常强大的)LLDB命令的集合,用于帮助调试iOS应用程序

在Xcode11上,Chisel初始化时会报错:

error: module importing failed: Missing parentheses in call to 'print'. Did you mean print('Whoops! You are missing the <' + arg.argName + '> argument.')? (fblldb.py, line 98)
  File "temp.py", line 1, in <module>
  File "/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.7/lib/python3.7/importlib/__init__.py", line 169, in reload
    _bootstrap._exec(spec, module)
  File "<frozen importlib._bootstrap>", line 630, in _exec
  File "<frozen importlib._bootstrap_external>", line 724, in exec_module
  File "<frozen importlib._bootstrap_external>", line 860, in get_code
  File "<frozen importlib._bootstrap_external>", line 791, in source_to_code
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed

这是由于最新的lldb基于Python3,从错误日志可以看到加载的是Xcode.app内置的python3.7

根据Xcode 11 Beta发行说明 (opens new window)

LLDB的Python脚本现在基于Python3。如果您使用的是与Python 3不兼容的Python扩展,它们将会中断。为了帮助过渡,您可以通过设置默认值以Python 2模式运行:

默认设置为com.apple.dt.lldb DefaultPythonVersion 2 将来将删除对Python 2的支持。(47806994)

解决办法1: 让lldb使用python2(不推荐,毕竟用新不用旧): 打开终端,输入:

defaults write com.apple.dt.lldb DefaultPythonVersion 2

解决办法2: 修改源码使其兼容Python3,这里有个小哥 (opens new window)已经兼容了Python3,可以用脚本快速拷贝到

#注意,我是用brew安装的(brew install chisel),所以chisel所在的路径是/usr/local/Cellar/chisel/1.8.1,如果你的此路径下面没文件,请改成你自己chisel所在的路径
cd ~/Downloads && git clone https://github.com/chenjiangchuan/chisel.git && cd chisel &&cp -f -R -v libexec /usr/local/Cellar/chisel/1.8.1

cd ~/Downloads && git clone https://github.com/facebook/chisel.git && cd chisel &&cp -f -R -v libexec /usr/local/Cellar/chisel/1.8.1

安装过程忽略,常见用法(更多请去官方GitHub查看)

Command 作用(描述) iOS OS X
pviews 打印key window的递归视图描述 Yes Yes
pvc 打印key window的递归视图控制器描述 Yes No
visualize 在Mac上的预览App中打开UIImage,CGImageRef等图像
fv 在层次结构中查找其类名与提供的正则表达式匹配的视图

# UI调试工具

https://lookin.work/

# JSON转类和结构体(OC&Swift)

https://github.com/Ahmed-Ali/JSONExport

# APNS远程推送测试工具

https://github.com/KnuffApp/Knuff/releases

{"aps":{"badge":1,"alert":{"userInfo":{"uid":"20B800000041","utype":"0"},"subtitle":" ","title":"233 12月9日推送3"},"sound":"default.caf","mutable-content":1}}

{
	"aps":{
		"alert":"Test2333",
		"sound":"default",
		"badge":1
	}
}

# 第三方依赖管理工具

# CocoaPods

# Swift Package Manager

# 解决Swift Package Manager依赖下载慢的问题
# -scmProvider system 强制 xcodebuild 使用“系统”git
xcodebuild -resolvePackageDependencies -scmProvider system

缓存位置: ~/Library/Caches/org.swift.swiftpm

# 好用的第三方库

#

  # -------------------- Objective-C 开源库 --------------------
  # 最受欢迎的网络请求库
  pod 'AFNetworking'
  # 目前还在维护的缓存库
  pod 'PINCache'
  # 加载网络图片,如需加载gif、webp等,可使用子Pod
  pod 'SDWebImage'
  pod 'SDWebImage/GIF'
  # 纯代码快捷自动布局
  pod 'Masonry', :git => 'https://github.com/SnapKit/Masonry.git'
  # HUD提示文字及圆形环形条形进度条
  pod 'MBProgressHUD'
  # 下拉刷新,上拉加载更多
  pod 'MJRefresh'
  # 自动计算UITableViewCell高度,兼容自动布局和sizeThatFits
  pod 'UITableView+FDTemplateLayoutCell'
  # 0行代码防止键盘挡住输入框
  pod 'IQKeyboardManager'
  # 一行代码实现字典快速转对象,无需继承统一父类
  pod 'MJExtension'
  #优雅地使用KVO https://github.com/facebook/KVOController
  pod 'KVOController'
  # TCP、UDP连接工具
  pod 'CocoaAsyncSocket'
  # 强大的图片选择器
  pod 'TZImagePickerController'
  # 管理导航栏转场 https://github.com/MoZhouqi/KMNavigationBarTransition/blob/master/README_CN.md
  pod 'KMNavigationBarTransition'
  # 日历控件
  pod 'FSCalendar', '~> 2.8.0'
  # 可实现Banner图及类似支付宝过年五福左右滑动切换效果
  pod 'TYCyclePagerView'
  # 二维码扫描功能及UI
  pod 'LBXScan/LBXNative'
  pod 'LBXScan/UI'
  # 快捷实现类似网易新闻今日顶部菜单+多页面切换,自带缓存
  pod 'WMPageController'
  # 可高度定制的视频播放器
  pod 'ZFPlayer','3.2.11'
  pod 'ZFPlayer/AVPlayer'
#  pod 'ZFPlayer/ControlView'
  # 微信SDK,不得不用
  pod 'WechatOpenSDK','1.8.0'
  # 微博SDK,不得不用
  pod 'Weibo_SDK', :git => 'https://github.com/sinaweibosdk/weibo_ios_sdk.git'
  # 统计bug
  pod 'Bugly'
  #iOS各种权限请求判断封装 https://github.com/MxABC/LBXPermission
  pod 'LBXPermission/Health'#其他权限请去github主页查看
  #https://github.com/eleme/Stinger AOP面向切面编程工具,饿了么开源的,据说比Aspect速度快20倍
  pod 'Stinger'
  #iOS 启动连续闪退保护方案https://wereadteam.github.io/2016/05/23/GYBootingProtection/
	#https://github.com/liuslevis/GYBootingProtection
	pod 'GYBootingProtection'
   # -------------------- Swift 开源库 --------------------
  #https://github.com/nixzhu/MonkeyKing 快速集成国内主流社交应用(微信、微博、QQ、支付宝)的分享、授权、支付等功能,不需要集成各种每个都几十兆的官方 SDK
  pod 'MonkeyKing'
  #https://github.com/kishikawakatsumi/KeychainAccess 轻量级 Keychain 封装,简单到极致的接口。支持 TouchID 与 Keychain 整合
  pod 'KeychainAccess'
  #https://github.com/krzyzanowskim/CryptoSwift 非常流行的加密解密库,项目配有完善的单元测试,支持MD5 | SHA1 | SHA224 | SHA256 | SHA384 | SHA512 | SHA3 | AES-128 | AES-192 | AES-256 | ChaCha20 等
  pod 'CryptoSwift'


  #--------------------DEBUG工具--------------------
  #Flipboard开源的应用内调试工具,可拦截查看网络请求及相应、浏览沙盒文件、方法调用、UI层级查看等 https://github.com/Flipboard/FLEX
  pod 'FLEX', '~> 3.0.0', :configurations => ['Debug']
  #滴滴开源的应用内调试工具,界面比较美观 https://github.com/didi/DoraemonKit
  pod 'DoraemonKit/Core', '~> 1.2.0', :configurations => ['Debug']
  #强大的日志记录工具,使用文档:https://github.com/CocoaLumberjack/CocoaLumberjack/tree/master/Documentation
  pod 'CocoaLumberjack'
#  pod 'Bagel', '~>  1.3.2'

  # Base64编码解码,自带的不好用,配合AES-256-CBC加密
  pod 'GTMBase64', '~> 1.0.1'
  # 阿里云对象存储SDK
  pod 'AliyunOSSiOS'
  pod 'Typeset'
  #---------------------------自己整的私有Pod----------------------------
  #-----如果pod install报错,先注释下面几行再pod install, 再解注释再pod install
  pod 'PWiOSTool/CommomViews', :git => 'https://git.coding.net/panway/PWiOSTool.git'
  pod 'PWiOSTool/Charts', :git => 'https://git.coding.net/panway/PWiOSTool.git'
  pod 'PWiOSTool/PPAlertAction', :git => 'https://git.coding.net/panway/PWiOSTool.git'
  # 庆科天猫精灵WIFI连接
  pod 'PWiOSTool/EasyLink', :git => 'https://git.coding.net/panway/PWiOSTool.git'
  pod 'QQSDK',:git =>'https://github.com/wooodypan/QQSDK.git'

  #---------------------------其他----------------------------
  #一站式解决 WKWebView 支持离线包、Ajax 请求和 Cookie 同步的问题 (基于 Ajax Hook 和 Cookie Hook):
  #https://github.com/karosLi/KKJSBridge
#  pod 'Fabric'
#  pod 'Crashlytics'
#  pod 'TencentOpenAPI'
#  pod 'YNPageViewController'
  #https://github.com/syik/ZJAttributedText
  # https://github.com/CocoaDebug/CocoaDebug
  # pod 'CocoaDebug', :configurations => ['Debug']

Google的Promis库: https://github.com/google/promises

应用内购买IAP封装 https://github.com/bizz84/SwiftyStoreKit

DNSPageView,类似网易新闻今日头条的多页面切换,未测试 (opens new window)

YJ3DTouch,3DTouch二次封装,被微云App使用 (opens new window)

视频压缩裁剪等 ,被微云App使用 (opens new window)

弹出菜单,未测试 (opens new window)

# Texture(AsyncDisplayKit)的基本使用

Github Demo (opens new window):需要将pod "AsyncDisplayKit"改为pod "Texture"

布局PinLayout+FlexLayout

https://github.com/layoutBox/PinLayout https://github.com/layoutBox/FlexLayout

# TODO

Stringz iOS Apps Localization Editor (opens new window)

一款很好用的做 App 本地化的工具,UI 简明清晰,并且能自动识别工程内的所有本地化文件。

CalendarKit (opens new window)

日历,尤其是复杂的日历 UI 都是产品开发中费时费力的部分,很多时候,因为缩减开发周期,设计师也会选择跳过这部分转而使用原生的日历 App 来设计功能。这个 CalendarKit 就是由一位外国朋友开发维护的开源日历 UI 库,可以很方便的进行日历相关功能的集成。

RealityUI (opens new window)

如果你正在做 AR/VR 相关的开发,那么这个库一定对你很有帮助。RealityUI 提供了一系列的控件,让你可以像做 2D 应用一样开发 AR/VR 应用。

iOS App Dev with SwiftUI Tutorials (opens new window)

苹果官方推出的 iOS App 入门级教程,大约 4 个小时时间,让你体会如何用 SwiftUI 构建一个简单的 App。整个教程还是采用类似逐步闯关的形式进行,十分友好。

App 启动提速实践和一些想法 (opens new window)

启动是门面,好的印象也有助于留存率提

雅虎开源的iOS开发工具包 https://github.com/yahoo/AppDevKit

Hammer (opens new window) 是一款模拟交互事件的 Swift 开源库,支持模拟触摸,iPad 手写笔,键盘输入。它能很好地用于 UI 自动化测试,尽可能替代一系列的人工操作

# 优质开源项目

如果你想学习SwiftUI,MovieSwiftUI是一个绝佳的参考项目,它基于MovieDB的API,用SwiftUI实现了一套完整的跨平台(iPhone/iPad/Mac)应用程序。值得一提的是,它的状态管理用的是SwiftUIFlux,类似于Redux的实现。整个结构看起来很像一个React应用。网页链接 (opens new window)

# Apple官方的Sample Code

Displaying Searchable Content by Using aSearch Controller (opens new window)

# 未测试开源项目

https://github.com/TermiT/Flycut

# 其他工具

一个可以用于提取任意 iOS App 图标原图的工具:https://bendodson.com/projects/itunes-artwork-finder/

下载你的AppleID购买过的ipa https://github.com/majd/ipatool

# 布局

self.topLayoutGuide在无导航栏的时候相当于状态栏那一块区域(iPhoneX是44px),在有状态栏的时候相当于状态栏+导航栏(导航栏44px+44px)

self.bottomLayoutGuide.length = 34px(iPhone X)

# 刨根问底

iOS框架源码解析 (opens new window)

# 语法Tips

  • class关键字可以直接在OC里可以用.调用:UIColor.redColor
+ (UIColor *)redColor;
@property(class, nonatomic, readonly) UIColor *redColor;
  • @synsthesize 需要手写的例外情况:

感谢自动合成,您不需要显式合成属性,因为它将由编译器自动合成 @synthesize propertyName = _propertyName 但是,存在一些例外:

使用自定义getter和setter的readwrite属性时:当同时提供getter和setter自定义实现时,该属性将不会自动合成

其他情况还有 https://stackoverflow.com/a/19821816

# 技巧篇 Tips

  • 旧版Xcode调试升级到最新系统的手机(这里以Xcode10调试iOS13为例,首先会报错 running iOS 13.0 (17A577), which may not be supported by this version of Xcode.)
  • 设置每个Target甚至每个文件的缩进:https://stackoverflow.com/a/47023275/4493393

# 不更新Xcode支持最新iOS设备支持文件

https://github.com/iGhibli/iOS-DeviceSupport/tree/master/DeviceSupport 粘贴文件夹到以下路径(先复制路径,然后Spotlight粘贴进去即可转到,然后输入管理员密码) /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport 重启Xcode

  • 查看任意App的bundleID 去这里搜索即可:https://www.deepaso.com/app/cn/1458072671

  • ~/Library/Developer/CoreSimulator/Devices

    模拟器中安装应用的数据保存在这里,建议使用xcrun simctl delete unavailable自动清理

  • 禁止Xcode控制台打印日志: Xcode menu open: Product > Scheme > Edit Scheme > On your Environment Variables set OS_ACTIVITY_MODE = disable https://stackoverflow.com/a/39461256/4493393

  • 123

# Xcode模拟器下载

搜索关键词:devimages-cdn.apple.com ios simulator

https://gist.github.com/rtrouton/f03fdca4b847ef4077b7979e7f1a5711

https://newbedev.com/download-xcode-simulator-directly

# 打包(Archieve)的文件位置

删除Organizer -Archieve残留垃圾 ~/Library/Developer/Xcode/Products

[self.window makeKeyAndVisible]这一步不执行的话,[UIApplication sharedApplication].keyWindow.rootViewController就会是nil

本地化复制粘贴等系统UI组件(复制粘贴弹出框框不显示英文):

https://stackoverflow.com/a/11282184/4493393

# 查看framework和静态库支持的架构

$ lipo -info AlicloudHttpDNS.framework/AlicloudHttpDNS
Architectures in the fat file: AlicloudHttpDNS.framework/AlicloudHttpDNS are: armv7 i386 x86_64 arm64
$ lipo -info /WeChatSDK/libs/libWeChatSDK.a
Architectures in the fat file: /WeChatSDK/libs/libWeChatSDK.a are: i386 armv7 armv7s x86_64 arm64

# js检测iPadOS是不是iOS

//https://stackoverflow.com/a/58065241
let isIOS = /iPad|iPhone|iPod/.test(navigator.platform)
|| (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)





# 小问题

  • Debug area 变量都显示nil? Product - Scheme - Edit Scheme - Run 里面的Build Configuration 由Release改成Debug

# Swift 和 Objective-C 混编

https://juejin.im/entry/5acd8e125188255c620f6d68

Importing Swift into Objective-C - AppleDeveloper (opens new window)

# 将 Swift 导入 Objective-C工程

怎么在Objc工程使用Swift代码呢?

  1. 在 framework target 内, 确保Build Settings -> Packaging -> Defines Module设置为Yes (貌似不是必须的)
  2. 如果是在 Target 中导入你写的Swift代码,需要#import "ProjectTargetName-Swift.h",其中ProjectTargetName是target名字 如果导入Framework Target中的Swift代码到 Objective-C .m 文件内, 使用下面的语法, 并替换成合适的名字:#import <ProductName/ProductModuleName-Swift.h>
  3. 如果Objc调用Swift的方法,需要在Swift代码的function前面加@objc
  4. Objc的方法里调用Swift类的属性,需要在Swift类的文件里加@objc关键字:
  5. 如果Objc使用Swift的类,需要在类前面加@objc,eg:public class Amplify改成@objc public class Amplify: NSObject
class Car: NSObject {
    @objc let name: String
    @objc let numberOfWheels: Int
    let manufacturer: String
}

# Mac Catalyst - 在macOS运行iOS App

https://developer.apple.com/documentation/uikit/mac_catalyst

为您的 iPad App 创建 Mac 版本 (opens new window)

为 Mac 优化你的 iPad 应用 (opens new window)

macOS沙盒路径如下,其中com.agolddata.pandanote是你的包名:

/Users/topcheer/Library/Containers/com.agolddata.pandanote/Data/

去相册目录:
cd ~/Pictures/Photos\ Library.photoslibrary/originals

# 通过 Catalyst 检测你的 iOS 应用何时在 macOS 上运行

检测你的 iOS 应用是否通过 Catalyst在 macOS 上运行:

Swift:

//https://www.hackingwithswift.com/example-code/catalyst/how-to-detect-your-ios-app-is-running-on-macos-catalyst
#if targetEnvironment(macCatalyst)
    print("UIKit running on macOS")
#else
    print("Your regular code")
#endif

Objc:

#if TARGET_OS_MACCATALYST
    NSLog(@"UIKit running on macOS");
#else
    NSLog(@"Your regular code");
#endif

Pods

#https://github.com/fermoya/CatalystPodSupport
load 'remove_ios_only_frameworks.rb'
#load 'remove_unsupported_libraries.rb'


  def catalyst_unsupported_pods
    [
      "Firebase/Crashlytics",
      "Firebase/Analytics",
      "Branch",
      "WechatOpenSDK"    ]
  end

  def supported_pods
      ['SwiftLint', 'Firebase/Auth', 'KeychainSwift']
  end

end


def debug
  true
end




#  $verbose = true # remove or set to false to avoid printing
#  installer.configure_support_catalyst(supported_pods, unsupported_pods)
#  installer.configure_support_catalyst

如何关闭沙盒?

https://stackoverflow.com/a/59752583/4493393

苹果 Project Catalyst:应用仅能在 macOS Catalina 和之后版本上运行 https://www.ithome.com/0/426/867.htm

# Tips

  • TableViewCell右滑删除在macOS怎么操作?

    如果你用两个手指在触摸板上滑动,它就能完美地工作。来源 (opens new window)

  • 2

# Objc为了方便转换成Swift所需的良好习惯

https://mp.weixin.qq.com/s/hPmL2fsAfQ-moeM5TjsliQ

- (instancetype)initWithBaseURL:(nullable NSURL *)url
           sessionConfiguration:(nullable NSURLSessionConfiguration *)configuration NS_DESIGNATED_INITIALIZER;
//通常 designated 构造器会调⽤ [super init] 这个方法,而 convenience 构造器会调⽤⾃⾝的某个 designated 构造器


@interface FLEXManager : NSObject
@property (nonatomic, readonly, class) FLEXManager *sharedManager;
//...
@end
  
  
  
// PPHTTPManager.h
  //+ (PPHTTPManager *)sharedManager;
@property (nonatomic, readonly, class) PPHTTPManager *sharedManager;//Swift可使用: PPHTTPManager.shared
@property (class) NSString *someString;

// PPHTTPManager.m
//static NSString *_someString = nil;
//+ (NSString *)someString { return _someString; }
//+ (void)setSomeString:(NSString *)newString { _someString = newString; }

# build号每次+1

buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${PROJECT_DIR}/${INFOPLIST_FILE}")
buildNumber=$(($buildNumber + 1))
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "${PROJECT_DIR}/${INFOPLIST_FILE}"

# ATS

在 iOS 10及以后版本和 macOS 10.12及以后版本中,如果你的应用程序的 Information Property List 文件中有以下任何一个键,则忽略 NSAllowsArbitraryLoads 键的值,并使用 NO 的默认值:

For more information about how the OS version affects ATS behavior, see the NSAppTransportSecurity (opens new window) key’s Versioning section.

# linkmap 默认位置

~/Library/Developer/Xcode/DerivedData/YOUR_XCODE_PROJECT_NAME-dbyywhxrphamjffeunjjdgbxoruz/Build/Intermediates.noindex/YOUR_XCODE_PROJECT_NAME.build/Debug-iphonesimulator/YOUR_XCODE_PROJECT_NAME.build/YOUR_XCODE_PROJECT_NAME-LinkMap-normal-x86_64.txt

# AFNetworking去掉UIWebView相关代码(过审)

#pod 'AFNetworking','~> 3.0'
pod 'AFNetworking', '~> 3.0', :subspecs => ['Reachability', 'Serialization', 'Security', 'NSURLSession']

# APNS

冷知识

  • 可以创建多个Push证书,App跟Push证书没啥关系,因为描述文件不含推送证书

Create a New Certificate -> Apple Push Notification service SSL (Sandbox & Production)

钥匙串访问里显示Apple Push Services: com.yourdomain.appid

# 文件

// 分享文件夹fullPath,来自FLEXFileBrowserController
- (void)openFileController:(NSString *)fullPath {
    UIDocumentInteractionController *controller = [UIDocumentInteractionController new];
    controller.URL = [NSURL fileURLWithPath:fullPath];

    [controller presentOptionsMenuFromRect:self.view.bounds inView:self.view animated:YES];
}

# 官方文档参考

iOS 显示的物理尺寸及分辨率 (opens new window)

# 优质iOS博客及代码

老司机iOS 周报 (opens new window)

Draven's Blog - 开源框架的理解分析 (opens new window)

iOS开发:我的初级到中级的晋级之路(619 Star) (opens new window)

iOS性能优化系列文章 - 戴铭的github (opens new window)

iOS Core Animation: Advanced Techniques中文译本 (opens new window)

iOS编译速度如何稳定提高10倍以上 (opens new window)

https://github.com/yixiangboy/IOSAnimationDemo

macOS 开发教程 https://github.com/DeveloperLx/macOS_Development_Tutorials_translation

未测试 https://github.com/JohnSundell/Files

iOS重签名模块 https://github.com/togettoyou/super-signature

# UI

Context Menus Tutorial for iOS: Getting Started

https://www.raywenderlich.com/6328155-context-menus-tutorial-for-ios-getting-started

# 前端相关

H5 缓存机制浅析 - 移动端 Web 加载性能优化 https://segmentfault.com/a/1190000004132566

微信Html5支付跳回原生App https://juejin.im/post/5be14b3af265da61542d1801

# 发布

# 博客&文章链接

SDK静态库的封装 https://juejin.cn/post/6844904178762907661

https://juejin.cn/post/6844903878094225422

# 未整理

Building for iOS, but the linked and embedded framework 'BaiduTraceSDK.framework' was built for iOS + iOS Simulator.

一般在Xcode 12.3上出现,主要是使用了模拟器+真机通用的framework,苹果在高版本Xcode貌似不推荐这种合并arm64和i386架构framework的方式。

一种解决方法是将 BuildSettings ->“Validate Workspace”设置为 Yes。它仍然会显示警告,但会构建项目。

https://stackoverflow.com/q/63267897/4493393

Q

A

//1.AppDelegate.m didFinishLaunchingWithOptions方法里:
//套了个WebViewController的UINavigationController给rootViewController
WebViewController *mainVC=[[WebViewController alloc]init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:mainVC];
self.window.rootViewController = nav;

//2.尝试给UINavigationController加Category不起作用:

//2.1 UINavigationController+StatusBarStyle.h
@interface UINavigationController (StatusBarStyle)

@end
  
//2.2 UINavigationController+StatusBarStyle.m
#import "UINavigationController+StatusBarStyle.h"

@implementation UINavigationController (StatusBarStyle)

- (UIStatusBarStyle)preferredStatusBarStyle {
    return [[self topViewController] preferredStatusBarStyle];
}
-(UIViewController *)childViewControllerForStatusBarStyle {
    return self.topViewController;
}
-(UIViewController *)childViewControllerForStatusBarHidden {
    return self.topViewController;
}
@end
  
//2.3 WebViewController的方法死活不会被调用
- (UIStatusBarStyle)preferredStatusBarStyle {
    return (_statusBarContentLight) ? UIStatusBarStyleLightContent : UIStatusBarStyleDefault;
}

//3 终极解决方法:
//新建一个类PPNavigationController,继承UINavigationController,替换AppDelegate.m的代码
//内容跟UINavigationController (StatusBarStyle)里一样

//4 不要忘了修改Info.plist里的View controller-based status bar appearance!!!
//删掉或者改为true

https://help.apple.com/app-store-connect/#/devd274dd925

# iOS12 在UIScrollView上嵌套的UITableView 滑动Cell时

2019-04-18 13:54:27.653615+0800 WeeXTemplate[64087:2769364] 
UITableView
_UISwipeActionPanGestureRecognizer
2019-04-18 13:54:27.653920+0800 WeeXTemplate[64087:2769364] 
WMScrollView
UIScrollViewPagingSwipeGestureRecognizer
2019-04-18 13:54:27.654130+0800 WeeXTemplate[64087:2769364] 
UIWindow
_UISystemGestureGateGestureRecognizer
2019-04-18 13:54:27.654276+0800 WeeXTemplate[64087:2769364] 
WMScrollView
UIScrollViewPanGestureRecognizer
2019-04-18 13:54:27.654394+0800 WeeXTemplate[64087:2769364] 
UITableView
UIScrollViewDelayedTouchesBeganGestureRecognizer
2019-04-18 13:54:27.654494+0800 WeeXTemplate[64087:2769364] 
UIWindow
_UISystemGestureGateGestureRecognizer
2019-04-18 13:54:27.654617+0800 WeeXTemplate[64087:2769364] 
UITableViewCellContentView
UILongPressGestureRecognizer
2019-04-18 13:54:27.654746+0800 WeeXTemplate[64087:2769364] 
UITableView
UIScrollViewPanGestureRecognizer
2019-04-18 13:54:27.655100+0800 WeeXTemplate[64087:2769364] 
UITableView
_UISwipeActionPanGestureRecognizer
2019-04-18 13:54:27.655470+0800 WeeXTemplate[64087:2769364] 
WMScrollView
UIScrollViewDelayedTouchesBeganGestureRecognizer
2019-04-18 13:54:27.656018+0800 WeeXTemplate[64087:2769364] 
UIWindow
_UISystemGestureGateGestureRecognizer
2019-04-18 13:54:27.656944+0800 WeeXTemplate[64087:2769364] 
UITableView
UIScrollViewDelayedTouchesBeganGestureRecognizer
2019-04-18 13:54:27.657323+0800 WeeXTemplate[64087:2769364] 
UIWindow
_UISystemGestureGateGestureRecognizer
2019-04-18 13:54:27.658401+0800 WeeXTemplate[64087:2769364] 
UITableViewCellContentView
UILongPressGestureRecognizer
2019-04-18 13:54:27.658872+0800 WeeXTemplate[64087:2769364] 
UITableView
UIScrollViewPanGestureRecognizer

# xcodeproj

示例脚本

http://xttxqjfg.cn/2017/07/11/xcodeproj修改xcode工程文件/ (opens new window)

https://www.rubydoc.info/gems/xcodeproj#initialize (opens new window)

require 'xcodeproj'  
project_path = ''    # 工程的全路径  
project = Xcodeproj::Project.open(project_path)  

# 1、显示所有的target  
project.targets.each do |target|  
puts target.name  
end  

# 增加新的文件到工程中  
target = project.targets.first  
group = project.main_group.find_subpath(File.join('testXcodeproj','newGroup'), true)  
group.set_source_tree('SOURCE_ROOT')  

# 获取全部的文件引用  
file_ref_list = target.source_build_phase.files_references  

# 设置文件引用是否存在标识  
file_ref_mark = false  

# 检测需要添加的文件是否存在  
for file_ref_temp in file_ref_list  
    puts file_ref_temp.path.to_s  
    if file_ref_temp.path.to_s.end_with?('ViewController1.m') then  
        file_ref_mark = true  
    end  
end  

if !file_ref_mark then  
    file_ref = group.new_reference('ViewController1.h文件路径')  
    target.add_file_references([file_ref])  
else  
    puts '文件引用已存在'  
end  

if !file_ref_mark then  
    file_ref = group.new_reference('ViewController1.m文件路径')  
    target.add_file_references([file_ref])  
else  
    puts '文件引用已存在'  
end 

project.save  
puts '文件添加完成'
require 'xcodeproj'  
project_path = ''    # 工程的全路径  
project = Xcodeproj::Project.open(project_path)  

# 1、显示所有的target  
project.targets.each do |target|  
puts target.name  
end  

# 从工程中删除文件  
target = project.targets.first  
group = project.main_group.find_subpath(File.join('testXcodeproj','newGroup'), true)  
group.set_source_tree('SOURCE_ROOT')  

def removeBuildPhaseFilesRecursively(aTarget, aGroup)  
aGroup.files.each do |file|  
    if file.real_path.to_s.end_with?(".m", ".mm", ".cpp") then  
        aTarget.source_build_phase.remove_file_reference(file)  
    elsif file.real_path.to_s.end_with?(".plist") then  
        aTarget.resources_build_phase.remove_file_reference(file)  
    end  
end  

aGroup.groups.each do |group|  
    removeBuildPhaseFilesRecursively(aTarget, group)  
    end  
end  

if !group.empty? then  
    removeBuildPhaseFilesRecursively(target, group)  
    group.clear()  
    group.remove_from_project  
end  

project.save
require 'xcodeproj'

project_path = ''    # 工程的全路径
project = Xcodeproj::Project.open(project_path)

puts 'ruby开始修改证书id和描述文件...'

project.targets.each do |target|
    target.build_configurations.each do |config|
        # 修改描述文件的id,值为id而不是名称
        config.build_settings['PROVISIONING_PROFILE'] = '5d6e268e-831b-4992-9b80-7595fe49380a'

        # 修改证书签名标识,一般无需修改
        # config.build_settings['CODE_SIGN_IDENTITY']
    
        # 修改工程的标识,即Bundle ID
        config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = ''
    end
end

project.save
puts '修改完成...'

project.targets.each do |target|
    target.build_configurations.each do |config|
        puts '修改之后描述文件的id'
        puts config.build_settings['PROVISIONING_PROFILE']

        # 证书签名标识
        # puts '修改之后证书签名标识'
        # puts config.build_settings['CODE_SIGN_IDENTITY']
    
        # 工程的标识
        puts '修改之后工程的id'
        puts config.build_settings['PRODUCT_BUNDLE_IDENTIFIER']
    end
end


上次更新: 3/13/2022, 12:02:34 AM