我将整个项目的复习拆分成了几个部分, 每完成一部分我都会提交一次代码, 大家根据所复习到的部分, 检出对应的分支来看代码就可以了, 代码中的注释已经十分详尽了, 有问题或者疑惑大家可以随时留言沟通.
项目地址
涵盖的知识点:
1.loadView的复习、loadView,viewDidLoad,viewDidUnload三者之间的联系
2.Swift下设置约束(原生/SnipKit)
3.核心动画的复习
4.iOS-单例的正确写法
5.iOS-Swift 和Objective-c 混编
6.自定义封装网络请求 Alamofire
7.模态带有导航栏的控制器
知识点1. loadView
1. 什么时候被调用?
-- 每次访问UIViewController的view(比如controller.view、self..view)而且view为nil,loadView方法就会被调用。控制器的view是懒加载的,什么时候使用,什么时候才创建, 如果已经创建,怎么调用都不会再创建了。
2. 作用:创建控制器的view
3. loadView执行逻辑:
-- 3.1 当前控制器是否从StoryBoard当中加载, 如果是,就加载storyboard中的view
-- 3.2 有没有xib来描述控制器的view,如果有,就加载xib当中的view
-- 3.3 如果都不是,就用UIView 创建一个
4. loadView,viewDidLoad,viewDidUnload三者之间的联系
- 4.1 第一次访问UIViewController的view时,view为nil,然后就会调用loadView方法创建view
- 4.2 view创建完毕后会调用viewDidLoad方法进行界面元素的初始化
- 4.3 当内存警告时,系统可能会释放UIViewController的view,将view赋值为nil,并且调用viewDidUnload方法
- 4.4 当再次访问UIViewController的view时,view已经在3中被赋值为nil,所以又会调用loadView方法重新创建view
- 4.5 view被重新创建完毕后,还是会调用viewDidLoad方法进行界面元素的初始化
知识点2. Swift下设置约束
注意:
1.代码addSubview, 如果想使用相对布局, 记得要设置subView 的translatesAutoresizingMaskIntoConstraints 为false, 否则会有autoresize 生成的constraints , 导致冲突, 也就是代码设置的约束不管用了.
2.而在Interface Builder 中Use autoLayout, IB 生成的控件的translatesAutoresizingMaskIntoConstraints 自动就被置位false了.
3.第三方约束工具SnipKit 自动帮助我们设置了.
2.1 系统原生设置约束的方法:
/** addConstraints参数说明:
参数1: 添加约束的对象
参数2: 添加约束的对象的哪个属性
参数3: 约束关系
参数4: 设置约束参考的对象
参数5: 设置约束参考的对象的哪个属性
参数6: 倍数
参数7: 偏移量
*/
addConstraints([NSLayoutConstraint(item: feedImageView, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1, constant: 0)])
2.2 第三方框架SnipKit (和OC 下的Masonry 一样)
addSubview(maskImageView)
maskImageView.snp_makeConstraints { (make) in
make.center.equalTo(self)
}
注: 添加约束的时候尽量不要写在layoutSubViews中, Swift会报错, 因为layoutSubViews会被多次调用, 所以多次添加约束, 就报错了. OC条件下是可以的.
知识点3. 核心动画习下的isRemovedOnCompletion属性
// 设置 首页圆圈图片做动画
private func setFeedImageViewAnim() {
// 核心动画
let anim = CABasicAnimation(keyPath: "transform.rotation")
// 设置toValue
anim.toValue = Double.pi * 2
// 设置时长
anim.duration = 20
// 设置重复次数
anim.repeatCount = MAXFLOAT
// 默认是YES, 代表动画执行完毕后就从图层上移除, 图形就恢复到动画执行前的状态. 当切换控制器或者前后台时, 默认动画会被移除 -> 这里阻止这个操作
anim.isRemovedOnCompletion = false
// 添加动画
feedImageView.layer.add(anim, forKey: nil)
}
知识点4. OC 中的单例(可参考: iOS-单例的正确写法)
OC 中的单例.png
知识点5. Swift 中的单例 (static全局访问点) (可参考: iOS-单例的正确写法)
Swift 中的单例
知识点6. iOS-Swift 和Objective-c 混编
知识点7. 自定义封装网络请求 Alamofire
import UIKit
import Alamofire
/// Swift 中枚举不仅支持Int 类型, 还支持字符串和其它基本类型等
enum RequestMethod: String{
case get = "get"
case post = "post"
}
class HNetworkTools: NSObject {
/// 定义全局的网络访问点
static let shared: HNetworkTools = {
let tools = HNetworkTools()
return tools
}()
// MARK: 定义网络请求的公共方法
func request(urlString: String, method: RequestMethod, parameters: Any?, success: @escaping (Any?)->(), failure: @escaping (Any?)->()) {
Alamofire.request(urlString, method: getRequestMethod(method: method), parameters: parameters as? Parameters, encoding: URLEncoding.default, headers: nil).responseJSON { (response) in
switch response.result {
case .success(let json):
success(json)
case .failure(let error):
debugPrint(error.localizedDescription)
failure(error)
}
}
}
// MARK: 获取网络请求方式
private func getRequestMethod(method: RequestMethod) -> (HTTPMethod) {
if method == .get {
return HTTPMethod.get
} else {
return HTTPMethod.post
}
}
}
注1:
Swift 中枚举不仅支持Int 类型, 还支持字符串和其它基本类型等
注2:Alamofire.request
得到的结果类型为DataRequest;DataRequest.responseJSON
得到的类型是DataResponse.
注3: 上段代码中.success(let json)
或者.failure(let error)
可能会难以理解, 点击response.result 的result 我文件中就一目了然了.
public struct DataResponse<Value> {
...
/// The result of response serialization. 响应序列化的结果。
/// 点击Result 跳转至头文件, 是一个枚举类型->也就是success 和failure
public let result: Result<Value>
/// Returns the associated value of the result if it is a success, `nil` otherwise. 如果成功,则返回结果的关联值,否则返回“nil”。
/// 其实就是你想得到数据信息, 如果success 时, 就通过上面.success(value), 将得到的信息传递出去; 如果failure, 就通过下面. failure(value), 将得到的错误信息传递出去.
public var value: Value? { return result.value }
/// Returns the associated error value if the result if it is a failure, `nil` otherwise. 如果结果为失败,则返回关联的错误值,否则返回“nil”。
public var error: Error? { return result.error }
}
知识点8. 模态带有导航栏的控制器
func present() {
let presentVc: UIViewController = UIViewController()
presentVc.view.backgroundColor = HRandomColor()
// 这里可以修改 presentVc被推出的形式, 或者转场动画
presentVc.modalPresentationStyle = .fullScreen
presentVc.modalTransitionStyle = .coverVertical
self.present(HNavigationController(rootViewController: presentVc), animated: true) {
print("模态带有导航栏的控制器")
}
}
.End
网友评论