iOS开发-周复盘·分享-20180727
今天给大家分享下面几点内容。
【1】在swift中,如何实现数组的深拷贝。
【2】如何一键 让 tableview header 取消悬停。
【3】为什么我们明明设置了headerview,它却迟迟不出现?
【4】如何优雅地刷新 tableview cell 里的内容?
【5】如何优雅地卸载 cocoaPod ?
【6】如何解决如下报错:“ ld: 3 duplicate symbols for architecture … … error: linker command failed with exit code 1 (use -v to see invocation) ” ?
【7】如果优雅地实现 date 与 string 的互相转换(双向)。
下面我们来一个一个说。
【1】在swift中,如何实现数组的深拷贝。
——————
「在上一讲《iOS开发-每周五复盘·分享-20180713》里的第【8】点,我们谈到了:
一句话概括·Swift数组的值拷贝与引用传递的区别:
只有在数组长度发生变化时,才会发生 值拷贝,否则都是 引用传递。
今天我们来详细说一说:“ 在swift中,如何实现数组的深拷贝 ”」
——————
接着上一讲的话来说,“只有在数组长度发生变化时,才会发生 值拷贝,否则都是 引用传递”,而现在说的这个“数组的深拷贝”,指的就是上面说的 值拷贝 。
在swift中,如何实现数组的深拷贝(值拷贝)。
对于由“整形数组、字符型数组,等简单数据类型”作为元素,组成的数组,适用于上一讲说的:“只有在数组长度发生变化时,才会发生 值拷贝,否则都是 引用传递”,详见上一讲的分享文章:《iOS开发-每周五复盘·分享-20180713》。 此处不再赘述。
而对于由“类的实例”作为元素,组成的数组,上述方式就不适用了。
你会发现,即使你改变了数组长度,没有直接 a=b,而是a.append(…),a数组和b数组之间依旧发生的是引用传递,不是深拷贝(值拷贝)。
即:a数组和b数组始终指向同一片内存区域,不管修改a的元素还是b的元素,都会把另一个数组里的元素同步修改掉(因为是指向同一片内存区域,数据只有一份,没有拷贝)。
那么如果我们就是需要这类「 由“类的实例”作为元素,组成的数组 」,做深拷贝(值拷贝),要怎么办呢?
可以这么办:
方案一:
把 「由“类的实例”作为元素,组成的数组」里面的类改为结构体(class -> 改为 -> struct),即可解决这个数组无法拷贝的问题。
ps.
熟悉结构体struct和类class的区别的同学都知道:
class A {…}
let a = A()
let a2 = a
//vs
struct B {…}
let b = B()
let b2 = b
上述代码中,
a和a2,指向的是同一片内存区域,它们之间发生的操作是 “引用传递”
而,
b和b2,指向的是同两片不同的内存区域,它们之间发生的操作是 “深拷贝(值拷贝)”
方案二:
在你定义的类里面,增加一个自定义的 copySelf方法:
class A {
var name: String? = nil
…
func copySelf() -> A {
let a = A()
a.name = self.name
…
return a
}
}
let a = A()
let a2 = a.copySelf()
这样,就可以实现:
a和a2,指向同两片不同的内存区域,使得它们之间发生的操作是 “深拷贝(值拷贝)”了。
【2】如何一键 让 tableview header 取消悬停。
——————
「当我们的需求,不需要 tableview header 自动悬停功能时,该如何一键处理解决?」
——————
使用过 tableView 里面的 headerView 的同学都是知道,该 headerView 会自带一个默认属性,就是当 tableView 滑上去时,它会自动悬停在屏幕上方,不会跟着tableView 的 cell 一起被滑上去,
而当 tableView 滑回来(下来)时,当滑倒该 headerView 对应的 section 的 row == 0 那一行出现时,它又会自动跟着 tableView 一起滑下来,恢复出在原来对应 section 顶部的位置。
当我们的需求和这个一样时,那这个 tableView 的 headerView 自带的自动悬停功能(属性)会极大的方便我们开发。
但是,若我们的需求和这个不一样,不允许 headerView 自动悬停,该怎么办呢?
有两种解决方案:
方案一:
不使用 headerView ,把该行的内容,用一个自定义的 cell 来实现。
方案二:(推荐)
设置 tableview 的 style 属性(UITableViewStyle) 为 .grouped 即可
(其默认值为 .plain)
【3】为什么我们明明设置了headerView,它却迟迟不出现?
——————
「使用过 tableView 里的 headerView 的同学,可能遇到过这个问题,就是:
“ 我们明明设置了headerView,它却迟迟不出现 ”,怎么解决呢?」
——————
原因分析:
我们都知道,要设置 tableView 里的 headerView ,需要在 tableViewDelegate 里的
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {}
这个代理方法里做相应设置。
但为什么,我们明明在这里面设置了headerView,它却迟迟不出现呢?
那是因为:
headerview 的 viewForHeaderInSection 代理,会被 heightForHeaderInSection 代理约束。
即,不管你在 viewForHeaderInSection 里怎么设置 headerview 的 frame、样式 ,等等,它都会在最后一步,被 heightForHeaderInSection 代理,在约束一遍。
也就是说,如果在 heightForHeaderInSection 代理里,你没有设置 headerview 的高度(默认值为0),或者,把它设为了零。
那么 headerview 肯定是 不管你在viewForHeaderInSection里怎么设置,都是不会出现的。
解决方案:
//同时设着下述两个代理里的实现内容:
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {}
//该 height 设为 所需 headerview 的实际 height 值
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {}
【4】如何优雅的刷新 tableview cell 里的内容?
——————
「使用过 tableview 的同学都知道,如果要刷新 tableview cell 里的内容,
可以调用 tableview.reloadData()方法。
那么有没有更优雅的实现方式,不需要去做 reload 操作就可以实现,tableview cell 里的内容得以刷新的效果呢?」
——————
答案是肯定的:
解决方案:
比如,实现如下功能:
“在点击某一行后,修改改行的已读状态(取消显示小红点)”
不使用 tableview.reloadData() 方法的
实现代码如下:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as? Cell
…
…
…
if dataArryIndex < mCellArray.count {
mCellArray.count[indexPath.row] = cell
}
}
return cell!
}
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let dataArryIndex = indexPath.row
if dataArryIndex < mCelllArray.count {
mCellArray[dataArryIndex]?.setReadStatus(true)
}
}
【5】如何优雅地卸载 cocoaPod ?
——————
「使用 “cocoapods-deintegrate”」
——————
使用方式:
终端命令行,输入如下命令即可:
sudo gem install cocoapods-deintegrate
pod deintegrate
ps.
该 cocoapods-deintegrate 的 github地址:
https://github.com/CocoaPods/cocoapods-deintegrate
【6】如何解决如下报错:“ ld: 3 duplicate symbols for architecture … … error: linker command failed with exit code 1 (use -v to see invocation) ” ?
——————
「为什么会这个错呢?主要原因是,在 project.pbxproj 中重复引用了同一个文件」
——————
解决方案:
打开 project.pbxproj 文件,
找到你重复引用的文件(该文件的文件名,在你的报错信息里有显示,对应着找即可),
删除重复,只保留一份。
ps.
该报错,常出现于合并分支解决冲突后(没解决好,重复引用了同一个文件)。
【7】如果优雅地实现 date 与 string 的互相转换(双向)
——————
「如何优雅的实现呢?」
——————
实现方案如下:
static func timeStampToString(_ timeStamp: String, format: String) -> String {
if let timeInterval: TimeInterval = TimeInterval(timeStamp) {
let date = Date(timeIntervalSince1970: timeInterval)
let formatter = DateFormatter()
formatter.dateFormat = format
return formatter.string(from: date)
}
return ""
}
static func StringToTimeStamp(_ currDate: String, currformat: String, locale: String = "en_US_POSIX") -> TimeInterval?{
var result: TimeInterval? = nil
let formatter = DateFormatter()
formatter.dateFormat = currformat
formatter.locale = Locale(identifier: locale)
if let date = formatter.date(from: currDate) {
let dateStamp = date.timeIntervalSince1970
result = dateStamp
}
return result
}
static func StringToString(currDate: String, currformat: String = "MMM dd, yyyy hh:mm:ss a", targetformat: String = "MM-dd HH:mm") -> String {
var targetDateAfterformat = ""
if let transferResult = BaseTimeProcessingUtility.StringToTimeStamp(currDate, currformat: currformat) {
targetDateAfterformat = BaseTimeProcessingUtility.timeStampToString(transferResult, format: targetformat)
}
return targetDateAfterformat
}
——————
~ ^_^ ~
—— zeroOS 复盘于 2018/07/29
「zeroOS·简书号」
© 著作权归作者所有