Bull’s Eye game
1、如何在项目中添加依赖
新建iOS工程后,在工程目录下运行pod init
,生成podfile文件后用vs code打开,之后添加需要依赖的库,添加完成后执行pod install
即可:
1 |
|
2、如何在Xcode中使用Git
-
创建一个新的Xcode工程,勾选
Create Git repository on my Mac
✅,此时Xcode就自动在项目中完成了Git仓库的初始化,如果创建工程时没有勾选,也可以手动使用git init
指令来实现。 -
添加远程仓库,xxx即为在Github中创建的仓库,这一步的目的是将本地仓库和远端的仓库连接起来
git remote add origin git@github.com:QAutumn/xxx.git
-
然后点击菜单栏中SouceControl里的Push,就可以愉快的提交代码了~
3、UIButton中的Configuration的用法
在初始化UIButton时,可以通过UIButton(configuration: UIButton.Configuration)
方法进行初始化,这样做的好处是可以定义一个全局的UIButton.Configuration,然后使用上述构造方法批量创建相同格式的UIButton。
如果在创建UIButton时没有使用上述构造方法,那么该button的默认Configuration是空的,此时如果想修改button中Configuration的某个属性,需要先手动创建一个Configuration,构造方法为
1 |
|
之后修改该config的相关属性,最后再将其赋值回btn的configuration属性即可。这里要说明的一点是,UIButton.Configuration本质上是一个结构体,所以可以直接这样修改:
1 |
|
但是如果使另外的变量等于当前的configuration,修改结束后要记得将该变量重新赋值回去。
4、UISlider控件的使用
首先介绍一下常用的一些属性和方法,详情🔎可以参考官方文档
Property | Discription |
---|---|
value | Slider的当前值 |
minimumValue | Slider的最小值,必须设定 |
maximumValue | Slider的最大值,必须设定 |
isContinuous | 滑块的值更改是否会生成连续的更新事件,若否,则只有松开手指后触发 |
minimumValueImage | 左边的小太阳 |
maximumValueImage | 右边的小太阳 |
UISlider使用addTarget方法进行事件绑定,根据isContinuous属性的不同,决定方法调用的次数。
5、通过封装方法设置UIImage的大小
1 |
|
6、项目结构
- 使用lazy var 的方式定义控件,控件的实现放到make xxx()方法中
- 将子视图的添加和位置、大小的调整封装到setupUI()方法中
1 |
|
7、UIAlert用法
1 |
|
8、设置背景ImageView
一开始用了一个比较复杂的方法,首先定义一个ImageView,设置好image属性后,在view中addsubview,然后再通过view.sendSubviewToBack(backgroundImageView)
方法将这个view移到最后,具体代码:
1 |
|
这种方法略微有点繁琐,也可以使用下面这种方法:
1 |
|
9、NSString用法
1 |
|
10、函数注释风格
1 |
|
Checklists
1、整体结构设计
2、Cell <-> indexPath
1 |
|
3、UINavigationController、UINavigationBar和UINavigationItem的关系
Navigation Controller
是一种容器视图控制器,通过属性viewControllers:[UIViewController]
来管理一个或多个child view controllers。
Navigation controller
管理着Navigation bar
和可选的 navigation toolbar
的创建、配置和显示。
一旦顶层的View Controller
发生改变,Navigation Controller
会对Navigation Bar
做出相应的调整,特别是,Navigation Controller
会更新Navigation bar
的左边、中间和右边的三个按钮BarButtonItems: [UIBarButtonItem]
。
每个Navigation bar
的tintColor属性都是由其自身设置的(独立的),Navigation bar
不会从其他View Controller
中继承该属性。
下图展示了Navigation Bar
的一些常用属性:
UINavigationltem
是Navigation bar
中展示的对象,主要包括 leftBarButtonItem,title,rightBarButtonItems(也就是两个按钮+中间的标题),如果左侧或右侧的按钮不止一个,那么可以使用setLeftBarButtonItems和setRightBarButtonItems方法来设置多个按钮。
当为UINavigationltem
添加对象的时候,必须使用UIBarButtonItem
对象,如果需要使用自定义的View,那么必须把这些View包裹到一个UIBarButtonItem
对象中才能够正常使用。
总结:
Navigation Controller
是View Controller
的容器。Navigation bar: [UINavigationBar]
是Navigation Controller
的一个属性,该属性随着View Controller
的push和pop自动产生和更新。Navigation bar
主要的作用是可以自定义样式,比如tintColor,setBackgroundImage等等,也可以通过isHidden属性设置是否隐藏Navigation Bar
。UINavigationltem
是View Controller
中的属性,也是Navigation bar
中展示的对象,负责Navigation bar
中按钮的配置。
以下是如何在项目中修改rootViewController
以及添加导航识图
的方法:
1 |
|
4、为UIBarButtonItem添加点击事件
分别设置UIBarButtonItem的 target
和 action
属性即可。
1 |
|
5、关于Navigation Bar 和 View 重叠的问题:
目前的解决方法是把View的top加了一个高度为navigationController?.navigationBar.frame.maxY
的偏移,不知道这种做法是否合适,也比较好奇为什么会出现这种重叠的问题,明明上一个界面还是好好的,跳转到这个界面后,重新写了一个Navigation Bar
就出现问题了……
1 |
|
6、UITextField用法
其实现在发现,所有的UI控件的套路基本都差不多,首先会有一些属性来定义常规功能,对UITextField
来说,常见的属性有placeholder
,text
,clearButtonMode
, leftView
, leftViewMode
等,详见🔎官方文档 。
-
如果需要将
UITextField
设置为第一响应者,也就是键盘拉起状态,可以调用becomeFirstResponder()
方法。UITextField
也会在用户点击时自动调用该方法。对应的,可以通过调用resignFirstResponder()
方法来请求系统取消键盘操作。通常,您会根据特定的交互操作取消键盘操作。例如,当用户点击键盘的Return键时,可能会取消键盘,此外当用户点击不支持键盘输入的新控件时,系统会取消键盘。
-
UITextField
通过UITextFieldDelegate
内置了很多delegate方法,这些方法可以允许我们对UITextField
进行更多自定义的操作,例如:-
当
UITextField
加载完成后,会自动调用textFieldDidBeginEditing(UITextField)
方法 -
当
UITextField
中的文本发生变化时,会调用textField(UITextField, shouldChangeCharactersIn: NSRange, replacementString: String) -> Bool
方法 -
当用户点击键盘上的
Return
按钮时,会调用textFieldShouldReturn(UITextField) -> Bool
方法 -
当用户点击
clearButton
时,会调用textFieldShouldClear(UITextField) -> Bool
方法举个栗子🌰:
1
2
3
4
5
6
7
8
9
10
11
12
13func textFieldDidBeginEditing(_ textField: UITextField) { print("did end begin") } func textFieldShouldReturn(_ textField: UITextField) -> Bool { self.view.endEditing(true) return true } func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { print(string) return true }
-
7、Delegate
delegate
是swift的三大设计模式之一,另外两个分别是target-action
和Model-View-Controller
。
delegation
的核心思想是:责任转移。简单来说就是,本来B该做的事情,现在交由A去做,并且设置A为B的代理。
创建delegation
的五个步骤是:
-
在B中创建一个
delegate protocol
。1
2
3protocol AddItemDelegate: AnyObject { func addItemComplete(_ cotroller: UIViewController,item: String) }
-
在B中添加一个名为
delegate
的变量,类型为刚才定义的protocol
,并将其设置成weak
。1
weak var delegate: AddItemDelegate? //这里要特别注意理解⚠️,delegate当前是一个遵循了AddItemDelegate协议的类的对象!!
-
在合适的时机(如用户按下按钮时)让B向其代理A发出消息
delegate?.methodName(self, . . .)
。1
2
3@objc func doneButtonClicked() { delegate?.addItemComplete(self, item: text) }
-
使A遵循
delegate protocol
中规定的方法。1
2
3
4
5
6extension CheckListsVC: AddItemDelegate { func addItemComplete(_ controller: UIViewController, item: String) { checkListItems.append(CheckListItem(name: item)) checkListsTableView.reloadData() } }
-
将B的代理设置为A。
1
addItemVC.delegate = self
8、Cell的默认配置
最近发现TableView
中的Cell
不需要每次都重新创建一个xxxCell
,然后自定义里面的各种View
,其实对于一些简单的Cell
,完全可以使用Configuration
来进行初始化。
首先可以通过cell.defaultConfiguration
来获取到当前Cell
的默认配置:
1 |
|
9、UITableViewDelegate
相比于UITableViewDatasouce
中的cellForRow
和numberOfRowsInSection
方法, UITableViewDelegate
中包含有大量的方法,很多delegate
方法,如果不知道的话,可能会导致自己写出相当不优雅的代码,比方说,cell
的默认配置defaultConfiguration()
中含有一个accessoryType
属性,该属性可以定义cell
最右侧的Button图标,可是如何为这个按钮绑定一个事件呢?
查阅文档🔎发现cell拥有accessoryView
这个属性,所以尝试了一下给这个View
添加一个手势事件,但是发现不行,目前推测可能是因为收拾冲突🤔,偶然间发现UITableViewDelegate
有一个accessoryButtonTappedForRowWith
方法专门用来处理accessory
被点击时的情况:
1 |
|
教训:以后要多看文档,养成delegate思维,避免做重复的无用功。
Mylocations
1、获取当前位置的gps坐标
1 |
|
但是在此之前,需要向系统申请读取当前位置GPS的权限:
1 |
|
同时需要在Info.plist中添加一条:
1 |
|
此时APP已经可以正常获取GPS位置了,但是还需要一些额外的代码来处理错误,比如用户没有给予权限:
1 |
|
2、将gps坐标转换成地理位置
这里加深了一下对比包的理解,placemark和error都是方法返回来的参数,而不是自己定义的。
好比说,我规定placemarks 和error的类型,你执行完reverseGeocodeLocation这个方法后,给我两个这个类型的参数
然后我再拿着这两个参数去做别的事情。
这也正是闭包的初衷:一……就……。
一返回结果,就用这个结果去做别的事。
1 |
|
3、在单个ViewController中隐藏NavigationBar
在使用navigationController进行push & pop的过程中,可能会需要在某些界面中隐藏navigationBar,对于需要隐藏navigationBar的ViewController来说,需要在viewWillAppear界面中将navigationController的isNavigationBarHidden设置为true:
1 |
|
注意,如果只是单纯这样写,会导致所有页面的NavigationBar都被隐藏,这很容易理解,因为只有一个navigationController嘛,所以我们还需要在该viewController被弹出时重新将isNavigationBarHidden的值设置成false:
1 |
|
####