# 基础篇
下载Xcode:https://developer.apple.com/download/more/?name=Xcode 或者打开Mac App Store
# 工具篇
# 开发及调试工具
# Xcode内置调试技巧
Xcode 10.2.1 新增的 v 比p和po更快哟
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)
# 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 库,可以很方便的进行日历相关功能的集成。
如果你正在做 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)
# 刨根问底
# 语法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代码呢?
- 在 framework target 内, 确保
Build Settings->Packaging->Defines Module设置为Yes(貌似不是必须的) - 如果是在 Target 中导入你写的Swift代码,需要
#import "ProjectTargetName-Swift.h",其中ProjectTargetName是target名字 如果导入Framework Target中的Swift代码到 Objective-C .m 文件内, 使用下面的语法, 并替换成合适的名字:#import <ProductName/ProductModuleName-Swift.h> - 如果Objc调用Swift的方法,需要在Swift代码的function前面加
@objc - Objc的方法里调用Swift类的属性,需要在Swift类的文件里加
@objc关键字: - 如果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 的默认值:
NSAllowsArbitraryLoadsForMedia(opens new window)网络媒体
NSAllowsArbitraryLoadsInWebContent(opens new window)网络内容
NSAllowsLocalNetworking(opens new window)网络
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博客及代码
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