其实人生也没有什么道理可讲,但是我们不必丧气,还是要期待,人生有奇遇。
苹果开发者:iOS Developer
最近因为工作需要要开始搞iOS了,简单记录下我收集和学习的过程。
组里大佬给我推荐的资料:
地址 | 说明 |
---|---|
人机交互指南 | 快速看完这个人机交互指南,对iOS系统有个概念。 |
旧版Sample | 有很多可以快速入门的Sample。 |
官方文档 | 官方的文档,可以快速检索。 |
官方OC教程 | 可以看看了解下OC的基本语法。 |
Swift官方文档 | The powerful programming language that is also easy to learn. |
Swift UI官方手把手教学 | 这是一份手把手教学的文档,很适合新手开发,了解Swift UI的开发和使用流程。 |
大佬给我的意见是先看完人机交互指南,了解iOS开发和Android开发的区别,看完之后再看看旧版Sample,从Sample中学习Objective-c的语法和iOS的开发流程。
文章 | 说明 |
---|---|
Objective-C | Objective-C的基础语法WIKI介绍。 |
Objective-C 入门教程 | 简单容易理解的Objective-C的基础教程。 |
苹果开发者文档·中文版 | 一份半成品的中文版开发文档,可以简单看看。 |
语法基础——Objective-C语法基础 | 比较简单的介绍了OC的一些语法和注意事项。 |
let | 定义常量,用let的原因可见于:A Guide to Writing Mathematics,见第10页:Defining variables and formulas。 |
谈谈 Objective-C 链式语法的实现 | 类似于Java的建造者模式,可以大大的简化代码,提高可读性和接口易用性。 |
文章 | 说明 |
---|---|
Swift官方文档 | The powerful programming language that is also easy to learn. |
Swift教程 | 一个极其简单的Swift语法入门教程。 |
Swift 函数参数前的“_”是什么意思? | 比如func someFunction(_ firstParameterName: Int, secondParameterName: Int) 中的_ 表示调用的时候可以忽略参数名称,someFunction(1, secondParameterName: 2) 。 |
官方基础工程简介 2019 | Version 11.1 (11A1027)【2019】的Xcode创建的工程目录结构介绍,以及SceneDelegate生命周期会掉方法的介绍、ContentView的介绍。 |
Swift3.0语法变化 | 对比介绍了Swift 3.0和Swift 2.0的区别,有助于了解语言的发展历史。 |
Swift UI官方手把手教学——这是一份手把手教学的文档,很适合新手开发,了解Swift UI的开发和使用流程。
lipo -info xxx.framework/xxxxFramework
也不知道用不用得着,暂时放着,不整理了。
不得不说,Bilibili果然是一个学习的好地方……╮(╯▽╰)╭
视频 | 说明 |
---|---|
【爱学啊】快速入门iOS Swift编程开发 Swift OC Objective-C Xcode 0基础 入门 | 强烈安利看看,这个很适合快速了解Storyboard是如何使用「拖一拖」的神仙操作完成界面设计的过程。 |
文章 | 说明 |
---|---|
id类型和instancetype类型 | 介绍OC的id类型和instancetype的类型的区别。 |
iOS·NSObject的两种含义:类与协议 | 介绍了类与协议,并介绍如何通过协议实现多继承。 |
@selector()的原理 | 理解OC中方法的创建和查找的创建过程。也推荐阅读iOS套路面试题之Selector的文末部分,更深入的分析推荐阅读:深入理解Objective-C:方法调用。 |
关于方法的「+」和「-」 | -方法是实例方法,放在类的结构空间的方法列表中,而+方法是类方法。 |
iOS开发中方法延迟执行的几种方式 | 四种延迟执行的方法比较与说明。 |
@property 参数详解 | strong:强引用;week:弱引用;copy:每次生成一个实例,防止Mutable对象被修改;nonatomic:非原子性;atomic:原子性…… |
OC学习笔记十四 构造函数 | 如何自定义构造函数的多种方式。 |
oc 16进制字符串与10进制的转换 两行代码搞定 | 10进制转换为16进制:NSLog(@"%ld",strtoul([@"0000c376" UTF8String],0, 16)); 。 |
Int转NSString的高大上写法 | NSString *string = @(number).stringValue; |
CRC校验32位,提供给iOS使用 | 扩展NSData,实现crc32校验。 |
iOS-如何优雅的隐藏主页面的导航栏,而只展示详细页面的导航栏(UINavigationBar) | 如何显示和隐藏UINavigationBar的操作。 |
下述段落摘抄于:IOS开发之-NS**概述
在iOS开发中,经常会遇到NS开头的对象,这个要从乔帮主历史恩怨说起。当年Steve Jobs 和John Scullery与恩怨,乔帮主当年被人挤兑出苹果,自立门户的时候做了个公司叫做NextStep,里面这一整套开发包很是让一些科学家们喜欢,而现在Mac OS用的就是NextStep这一套函数库。
这些开发NextStep的人们比较自恋地把函数库里面所有的类都用NextStep的缩写打头命名,也就是NS了。比较常见的比如:NSLog、NSString、NSInteger、NSURL、NSImage……
Historical Note: If you’re wondering why so many of the classes you encounter have an NS prefix, it’s because of the past history of Cocoa and Cocoa Touch. Cocoa began life as the collected frameworks used to build apps for the NeXTStep operating system. When Apple purchased NeXT back in 1996, much of NeXTStep was incorporated into OS X, including the existing class names. Cocoa Touch was introduced as the iOS equivalent of Cocoa; some classes are available in both Cocoa and Cocoa Touch, though there are also a large number of classes unique to each platform.
Two-letter prefixes like NS and UI (for User Interface elements on iOS) are reserved for use by Apple.
前缀 | 说明 |
---|---|
NS | NextStep |
UI | for User Interface elements on iOS |
xcrun simctl 操作模拟器的命令
xcrun simctl list
:查看当前可用设备列表xcrun simctl boot $UUID
:启动模拟器xcrun simctl delete unavailable
:清理不可用的模拟器xcrun simctl io booted screenshot app-screenshot.png
:模拟器截屏xcrun simctl io booted recordVideo app-preview.mp4
:模拟器录屏工欲善其事必先利其器,Cocoapod基于Ruby,需要先把环境搭建好(Mac自带,不需要安装了)
gem sources --add https://gems.ruby-china.com/ --remove https://rubygems.org/
常用指令 | 说明 |
---|---|
gem sources -l |
查看源地址 |
gem sources -u |
更新缓存 |
gem sources --add 源地址 |
添加源 |
gem sources --remove 源地址 |
删除源 |
Pod是CocoaPods提供的功能,详见开源项目:CocoaPods。
文章 | 说明 |
---|---|
Podfile 解析最佳实践 | 介绍Podfile的原理和Ruby的语法。 |
Pods的static_framework使用感受 | 介绍podspec的s.static_framework=true 的使用及其优缺点。Tips:如果依赖的库是某个库的静态库,也就是framework ,则需要在.podspec文件中的添加依赖前进行指明s.static_framework=true 。 |
使用cocoapods打包静态库(依赖私有库,开源库,私有库又包含静态库) | 详细的介绍了Podspec的配置和使用。 |
使用Podspec的subspec实现组件的按需引用 | 按需引用Pod中的某一部分。 |
使用私有Cocoapods仓库 中高级用法 | 私有Pods的创建流程及PodSpec的配置流程讲解。 |
配置 | 说明 |
---|---|
inhibit_all_warnings! |
屏蔽Cocoapods库里面的所有警告。 |
use_frameworks! |
在Pods中用frameworks 替代静态库。 |
source 'https://github.com/CocoaPods/Specs.git' |
使用公有库,支持使用私有库,修改地址即可。 |
附上一个PodSpec逐字解析:
Pod::Spec.new do|s|
# 项目名称
s.name = 'YourPodName'
# 版本
s.version = '0.1.0'
# 简介
s.summary = 'A short description of YourPodName.'
# 详细介绍
s.description = "详细介绍"
# 项目主页
s.homepage = "https://github.com/xxx/YourPodName"
# 截图
s.screenshots = "www.example.com/screenshots_1"
# 支持的协议及文件
s.license = { :type => 'MIT', :file => 'LICENSE' }
# 作者名字和邮箱
s.author = { 'skx926' => '[email protected]' }
# 仓库地址
s.source = { :git => 'https://github.com/skx926/YourPodName.git', :tag => s.version.to_s }
# 社交媒体地址
s.social_media_url = 'https://twitter.com/xxx'
# 最低要求的系统版本
s.ios.deployment_target = '8.0'
# 源文件路径
s.source_files = 'YourPodName/Classes/**/*'
# 资源文件存放位置
s.resource_bundles = {
'YourPodName' => ['YourPodName/Assets/*.png']
}
# 暴露给外部的头文件
s.public_header_files = 'YourPodName/Classes/**/*.h'
# 项目中使用的系统framework
s.frameworks = 'UIKit', 'MapKit'
# 项目中使用的第三方framework
s.vendored_frameworks = 'Thirdparty.framework'
# 项目中使用的系统静态库
s.libraries = 'iconv', 'xml2'
# 项目中使用的第三方静态库
s.vendored_libraries = 'Library/gmssl/*.a'
# Xcode配置
s.xcconfig = { "HEADER_SEARCH_PATHS" => "${PODS_ROOT}/../../Library/gmssl"}
# 项目依赖的第三方库
s.dependency 'AFNetworking', '~> 2.3'
end
源于:SDK开发和打包静态库遇到的坑,SubSpec请见:podspec文件解析
参数 | 说明 |
---|---|
pod ‘模块名’ | 不显式指定依赖库版本,表示每次都获取最新版本 |
pod ‘模块名’, ‘2.0’ | 只使用2.0版本 |
pod ‘模块名’, ‘> 2.0’ | 使用高于2.0的版本 |
pod ‘模块名’, ‘>= 2.0’ | 使用大于或等于2.0的版本 |
pod ‘模块名’, ‘< 2.0’ | 使用小于2.0的版本 |
pod ‘模块名’, ‘<= 2.0’ | 使用小于或等于2.0的版本 |
pod ‘模块名’, ‘~> 0.1.2’ | 使用大于等于0.1.2但小于0.2的版本 |
pod ‘模块名’, ‘~>0.1’ | 使用大于等于0.1但小于1.0的版本 |
pod ‘模块名’, ‘~>0’ | 高于0的版本,写这个限制和什么都不写是一个效果,都表示使用最新版本 |
命令 | 说明 |
---|---|
pod install | 只会安装Podfile中新改变的东西,不会更新那些已经安装了的库。优先遵循 Podfile 里指定的版本信息;其次遵循Podfile.lock里指定的版本信息来安装对应的依赖库。 |
pod install --verbose --no-repo-update | 不更新本地Spec仓库,直接拉取更新。 |
pod update | 根据Podfile的规则更新所有依赖库,Podfile.lock无效,且会生成新的文件来覆盖原来的。 |
pod update --verbose --no-repo-update | 不更新本地Spec仓库,直接拉取更新。 |
pod repo update | 用来更新本地cocoapods的spec资源配置信息。 |
pod cache list | 查看所有spec文件的缓存,可以直接到路径下删除文件 |
pod cache clean AFNetworking | 删除指定库的缓存文件 |
pod ipc spec --help | 将pobspec转化为podspec.json |
产物 | 说明 |
---|---|
Podfile.lock | 初次执行pod install 时产生,包含依赖库的版本号。 |
Manifest.lock | Manifest.lock 是 Podfile.lock 的副本。每次只要生成 Podfile.lock 时就会生成一个一样的 Manifest.lock 存储在 Pods 文件夹下。项目 Build 的时候,会检查一下 Podfile.lock 和 Manifest.lock 是否一致。 |
Spec Repo | 存放 Spec 文件的仓库,所有公开的 Pods 都在这个里面,是一个Git仓库 remote 端。执行 pod setup命令会clone 该仓库 到本地的~/.cocoapods/repos目录下。仓库保存了依赖库的名称,版本号,以及spec文件。 |
产物 | 说明 | 缺点 |
---|---|---|
静态库*.a | 编译时将库编译到目标程序中。 | 包体积变大。 |
动态库*.dyld | 编译只存储了指向动态库的引用,多个程序可共用,在运行时加载,不会使包体积变大 | 运行时加载会损耗部分性能,并且依赖外部环境,如果库不存在或者版本不正确则无法运行。 |
Framework | 实际上只是一种打包方式,将库的二进制文件、头文件和有关的资源打包到一起,方便管理与分发。 |
对比:
use_frameworks!
use_frameworks!
。use_frameworks!
则是会生成相应的*.a
文件(静态链接库),通过Static Libraries这个方式来管理Pod的代码。use_frameworks!
则Cocoapods 会生成相应的*.frameworks
文件(动态链接库:实际内容为Header+动态链接库+资源文件),使用Dynamic Frameworks 来取代Static Libraries方式。Linked:libPods-xxx.a
包含了其它用pod导入的第三方框架的*.a
文件。Linked:Pods_xxx.framework
包含了其它用pod导入的第三方框架的*.frameworks
文件。文章 | 说明 |
---|---|
iOS组件化之私有库 | 讲解了建立私有pod仓库,以及代码解耦分pod的方式。 |
基于 CocoaPods 的组件二进制化实践 | 火掌柜 iOS 客户端经过近两年的组件化推进,组件数量已经颇具规模,达到了近 100 个。随着组件数量和代码量越来越多,主工程的打包时间从最初的十几分钟,增加到了现在的四十分钟左右。依赖组件较多,改动相对频繁的上层业务组件,其发布时间也较为漫长。编译时长的困扰,已经明显影响了日常开发体验,同时也造成 CI pipeline 执行时间过长,在 runner 资源匮乏的情况下,不利于内部 CI 的推广。当前时间节点下,如何减少编译时长,已经成为开发团队较为迫切的需求。 |
键位 | 说明 |
---|---|
command+方向键 | 模拟器屏幕旋转 |
command+shift+h | home键操作 |
command+s | 模拟器截图 |
command+shift+c | 复制模拟器截图到剪贴板 |
command+L | 模拟器锁屏 |
链接 | 说明 |
---|---|
target depnedencies | 编译前,告诉工程在运行的时候先去编译这里导入的库。 |
Link Binary With Libraries | 编译时期,添加某个project需要链接的库,会被编译到工程的包里。 |
Embedded Binaries | 运行时,告诉app运行时去哪些库里找实现方法。 |
Cocoapods的使用介绍:Cocoapods
强烈推荐这个教程:Podfile文件用法详解
source 'https://github.com/CocoaPods/Specs.git'
# 忽略引入库的所有警告
inhibit_all_warnings!
repo add PodSpec名称 http://xxx/xxx/PodSpec.git
更新源:pod repo update
导入依赖
# 拉取最新版本的依赖
pod 'project'
# 拉取指定版本的依赖
pod 'project', '1.2.3'
# 在指定配置下拉取依赖
pod 'project', :configuration => 'Debug' # 一个配置
pod 'project', :configurations => ['Debug', 'Release'] # 多个配置
# 拉取子模块
pod 'project/subProject' # 单个子模块
pod 'project', :subspecs => ['subProject1', 'subProject2'] # 多个子模块
# 拉取本地的依赖
pod 'project', :path => '~/Library/project'
# 拉取远程的版本
pod 'project', :git => 'https://github.com/notzuonotdied/project.git' # 默认是master分支
pod 'project', :git => 'https://github.com/notzuonotdied/project.git', :branch => 'dev' # 指定dev分支
pod 'project', :git => 'https://github.com/notzuonotdied/project.git', :tag => '1.2.3' # 指定tag
pod 'project', :git => 'https://github.com/notzuonotdied/project.git', :commit => '123456' # 指定commit ID
# 拉取其他podspec的源
pod 'project', :podspec => 'https://gitlab.com/project.podspec'
/Users/username/Library/Application Support/iPhone Simulator
目录 | 说明 |
---|---|
Documents | 苹果建议将程序中建立的或在程序中浏览到的文件数据保存在该目录下,iTunes备份和恢复的时候会包括此目录。 |
Library | 存储程序的默认设置或其它状态信息。 |
Library/Caches | 存放缓存文件,iTunes不会备份此目录,此目录下文件不会在应用退出删除,当手机的内存不足是会删除该目录下的文件。 |
tmp | 提供一个即时创建临时文件的地方。 |
/Users/username/Library/Developer/CoreSimulator/Devices/cryptic number/data/Containers/Data/Application/cryptic number
cryptic number
:虚拟机的序列号。
cryptic number
:安装在虚拟机的序列号。
tree
输出查找。brew cask install tree
安装tree
命令。详见:iOS开发 查看真机沙盒文件
OC可以使用Gcov进行代码覆盖测试
项目集成
Generate Legacy Test Coverage Files
为YesInstrument Program Flow
为Yes代码配置
在AppDelegate.m
的didFinishLaunchingWithOptions
中配置如下代码:
- (void)applicationDidEnterBackground:(UIApplication *)application {
//#if NT_COVERAGE
#if !TARGET_IPHONE_SIMULATOR
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
setenv("GCOV_PREFIX", [documentsDirectory cStringUsingEncoding:NSUTF8StringEncoding], 1);
setenv("GCOV_PREFIX_STRIP", "13", 1);
#endif
extern void __gcov_flush(void);
__gcov_flush();
//#endif
}
在需要采集覆盖率的地方加入代码
extern void __gcov_flush(void);
__gcov_flush();
知识点 | 说明 |
---|---|
iOS应用程序的生命周期 | 介绍iOS应用程序的架构(MVC)和生命周期。 |
iOS开发 生命周期 | 这篇文章关于iOS的生命周期的介绍比较直观。 |
iOS 中静态链接库的使用 | 介绍Framework和*.a文件。 |
库 | 说明 |
---|---|
ZipArchive | 解压缩,工程的配置详见:SSZipArchive |
iOS 数据压缩与解压 | gzip解压缩oc代码。 |
收集一些遇到的问题以及解决方案。
Always get build error : No such module 'Alamofire’的解决方案:Make sure you have opened the “project_name”.xcworkspace instead of “project_name”.xcodeproj .As you are working on pods all the installed pod will be available only in your .xcworkspace project file.
(不得不说,我看到这个答案,我的内心是崩溃的……)
pod install
和pod update
慢可以使用下面的指令:
pod install --verbose --no-repo-update
pod update --verbose --no-repo-update
问题:Attempt to present UIViewController on UIViewController whose view is not in the window hierarchy
解决方案:
UIViewController *yourCurrentViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
while (yourCurrentViewController.presentedViewController)
{
yourCurrentViewController = yourCurrentViewController.presentedViewController;
}
[yourCurrentViewController presentViewController:composeViewController animated:YES completion:nil];
UIViewController *yourCurrentViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
while (yourCurrentViewController.presentedViewController)
{
yourCurrentViewController = yourCurrentViewController.presentedViewController;
}
[yourCurrentViewController dismissViewControllerAnimated:YES completion:nil];
问题描述:Xcode 10使用了新的build system
,需要替换为另外的一个模式的build system
。
问题解决:按照File->Workspace Settings->build system
路径修改build system
为Legacy Build System
。
配置完Flutter
环境之后,使用flutter doctor
检查下环境,会出现以下的提示:
[!] iOS toolchain - develop for iOS devices (Xcode 9.1)
✗ CocoaPods not installed.
CocoaPods is used to retrieve the iOS platform side's plugin code that responds to your plugin usage on the Dart side.
Without resolving iOS dependencies with CocoaPods, plugins will not work on iOS.
For more info, see https://flutter.io/platform-plugins
To install:
brew install cocoapods
pod setup
按照命令安装一波:
brew install cocoapods
pod setup
执行pod setup
后,就只有光秃秃的➜ ~ pod setup
,其他提示啥也没有……(脑阔疼)
使用flutter doctor
看看:
➜ ~ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.9.1+hotfix.4, on Mac OS X 10.14.6 18G103, locale
zh-Hans-CN)
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
[!] Xcode - develop for iOS and macOS (Xcode 11.1)
✗ CocoaPods installed but not initialized.
CocoaPods is used to retrieve the iOS and macOS platform side's plugin
code that responds to your plugin usage on the Dart side.
Without CocoaPods, plugins will not work on iOS or macOS.
For more info, see https://flutter.dev/platform-plugins
To initialize CocoaPods, run:
pod setup
once to finalize CocoaPods' installation.
[✓] Android Studio (version 3.5)
[!] IntelliJ IDEA Ultimate Edition (version 2019.2.3)
✗ Flutter plugin not installed; this adds Flutter specific functionality.
✗ Dart plugin not installed; this adds Dart specific functionality.
[✓] VS Code (version 1.38.1)
[!] Connected device
! No devices available
! Doctor found issues in 3 categories.
pod setup
没有初始化成功……后来在github找到了相似的问题的解决方案
CocoaPods installed but not initialised #41291
As per solution in #41253:
sudo gem uninstall cocoapods
sudo gem install cocoapods -v 1.7.5
pod setup
sudo gem install cocoapods (if you want latest version)
按照这个方式安装,命令行提示如下:
➜ ~ sudo gem uninstall cocoapods
Successfully uninstalled cocoapods
➜ ~ sudo gem install cocoapods -v 1.7.5
Fetching cocoapods-core-1.7.5.gem
Fetching cocoapods-1.7.5.gem
Successfully installed cocoapods-core-1.7.5
Successfully installed cocoapods-1.7.5
Parsing documentation for cocoapods-core-1.7.5
Installing ri documentation for cocoapods-core-1.7.5
Parsing documentation for cocoapods-1.7.5
Installing ri documentation for cocoapods-1.7.5
Done installing documentation for cocoapods-core, cocoapods after 2 seconds
2 gems installed
➜ ~ pod setup
Setting up CocoaPods master repo
$ /usr/bin/git clone https://github.com/CocoaPods/Specs.git --progress --
master
Cloning into 'master'...
remote: Enumerating objects: 107, done.
remote: Counting objects: 100% (107/107), done.
remote: Compressing objects: 100% (102/102), done.
remote: Total 3522904 (delta 29), reused 3 (delta 3), pack-reused 3522797
Receiving objects: 100% (3522904/3522904), 688.96 MiB | 1.53 MiB/s, done.
Resolving deltas: 100% (2139862/2139862), done.
Checking out files: 100% (364643/364643), done.
CocoaPods 1.8.3 is available.
To update use: `sudo gem install cocoapods`
For more information, see https://blog.cocoapods.org and the CHANGELOG for this version at https://github.com/CocoaPods/CocoaPods/releases/tag/1.8.3
Setup completed
非常完美的解决了pod setup
一点反应都没有的问题:
知识点 | 说明 |
---|---|
ResourceDoc | 收集的一些iOS开发的资源,包括官方教程、视频、社区、插件、第三方库、文章等等, 绝大多数是基于Swift,中文资源优先。可惜的是停止更新了,详见:我为什么放弃学习iOS开发 。 |