[TIL] 年复一年意识到成长的四月
记录日常开发中遇到的 1. 新知 2. 对旧知识的新认知 3. 重新唤起的记忆 4. review 中遇到的一些有趣的问题
04/23
UTI - Uniform Type Identifier
同事在分享会中详细讲了 UTI,用过很多次,但大概一直都只懂三成吧,听完后对 UTI 的理解明显更系统化了一些XD
能一瞬间想起来的运用场景有:
- Share Extension
- Drag and Drop
- Pasteboard
简单来说,对于文本类型而言,扩展名可以是 .txt
或 .text
,而 MIME 类型是 text/plain
,当我们要处理文本类型时,必须将以上所有类型全部视为对象,这是一件非常缺乏效率的事情,而 UTI 就是用来处理这个问题的,他将所有类型都统一为了 public.text
,UTI 类型和其他所有类型相互兼容。
Ref:关于自定义 UTI 类型,UTI 类型的继承性 — https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/understandingutis/understandutisconc/understandutis_conc.html
04/20
autoreleasepool
最近做了一点 Objective-C 转 Swift,在 Objective-C 中我们常常会需要使用 autoreleasepool,但并不意味着遇到 Swift 之后 autoreleasepool
就不再需要考虑。当 Swift 调用 Objective-C 代码,亦或是 Objective-C 调用被标记为 @objc 的 Swift 方法时,如果方法返回的是 autorelease 的值,那 Swift 也会保持这个值的 autorelease 特性。
在 Objective-C 中,有时候会在循环中写 autoreleasepool
来避免内存爆炸,因为循环的持续会导致没有机会自动释放内存。
04/15
ZIPFoundation
https://thomas.zoechling.me/journal/2017/07/ZIPFoundation.html
A ZIP compression framework don't based on any 3rd party framework. Almost all of the swift ZIP framework based on minizip.
尽管这个框架十分简洁甚至无法完全满足要求,但作者的这篇文章还是很值得一读,在设计框架时考虑的一些点很有参考价值。
ZIP64
https://en.wikipedia.org/wiki/ZIP(fileformat)#ZIP64
标准 ZIP 有一些限制,例如不能容纳超过 65535 个文件(因为 eocd 中只有 2 bytes 用来存 entry 的信息。。),压缩文件大小不能超过 4G 之类,因此出现了 ZIP64 标准。
04/13
CRC32 (Cyclic redundancy check)
ZIP 压缩中使用的校验方式是 CRC32,是 CRC(循环冗余校验)方法中的其中一种。
记忆中第一次知道 CRC 是在密码学的课本上,奇偶校验,50% 的出错概率,还有校验和,也有不小的出错可能性,此外就是 CRC 了,因为高效且检错力很高,被广泛用在存储,压缩等之中。CRC32 是 CRC 校验中最被广泛使用的之一,但他并不是完美的,即便篡改了内容,用 CRC32 进行校验依然可能会得到相同的值。
题外话,如何在各种语言中使用 CRC32:https://rosettacode.org/wiki/CRC-32#Swift。Swift 的实现法可以说并不一定实用,他选择了直接调用 zlib 中的 crc32 方法w
Strange Date Format
e.g. 04/01, template = "Md"
en_US ⇒ 4/1
ja_JP ⇒ 4/1
en_JP ⇒ 04/01
Still don‘t know why Apple making this design..But we could resolve this unexpected problem by:
formatter.dateFormat = DateFormatter.dateFormat(
fromTemplate: " Md",
options: 0,
locale: Locale(identifier: "en_JP")
)?
.replacingOccurrences(of: "MM", with: "M")
.replacingOccurrences(of: "dd", with: "d")
04/12
SQL - Prepared Statement
INSERT INTO products (name, price) VALUES (?, ?);
通常这么做的优点是:
- 防止 SQL 注入
- 效率更高,避免了多次解析相同结构的 SQL 语句
- ...
04/08
Attributes in Swift
分为两类,分别是:
1. @attribute name
2. @attribute(attribute arguments)
今天写了写 @inline,回忆了几个常用的:
@inline 内联
在编译的阶段用函数体去替换函数调用。优点是可以减少函数调用的开销,但作为交换,binary size 会略有增大。
- @inline(_always) 强制内联(不是 100%,也有例外)
- @inline(never) 无论如何都不内联
@inlinable 可内联
和 @inline 看起来很像,但有着本质上的区别。@inlinable 可以用在 public 和 internal 的方法,计算属性等之上,这样在模块外被进行编译的时候,就会进行内联优化。虽然可以被优化,但 internal 依然是不可以被访问的,另外,当且仅但 internal 被标记为 @usableFromInline 的时候才会被作为对象。如果只存在一个模块,并没有只用 @inlinable 的必要。
@discardableResult 可忽略的返回值
允许有返回值的方法不返回任何值
@available
是一个带有参数的 attribute,用于指定最低 swift 版本,platform 的版本之类,例如我们会写 @available(swift 99) 来避免被 swift 调用,@available(iOS 14.0) 来使用 14.0 最新的 API。
Ref. https://docs.swift.org/swift-book/ReferenceManual/Attributes.html#
04/07
Access Photo Library
Plist
- NSPhotoLibraryAddUsageDescription
- NSPhotoLibraryUsageDescription
- NSCameraUsageDescription
Render a UIView to a UIImage
let renderer = UIGraphicsImageRenderer(size: view.bounds.size)
let image = renderer.image { context in
view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)
}
Take screenshot programmatically
https://developer.apple.com/library/archive/qa/qa1703/_index.html (Outdated..)
04/06
Multi-cursor editing in Xcode
- To add a new cursor, hold Control and SHIFT then click.
- Hold Control and SHIFT then ↑ or ↓
- Hold Option then drag cursor around.
Formatter
https://nshipster.com/formatter/
当不设置默认 template 的情况下,会按照各 locale
的默认模版来显示日期。
例如:
// JP: 2021/03/01
// KR: 2021.3.1.
let formatter = DateFormatter()
formatter.locale = locale
formatter.calendar = Calendar.autoupdatingCurrent
formatter.dateStyle = .short
formatter.timeStyle = .none
这应当被认为是一个好的实践,完全可以当且仅当必要的时候为 formatter
设置 template。
Detect user takes a screenshot
NotificationCenter.default.addObserver(
self,
selector: #selector(xxxxxx),
name: UIApplication.userDidTakeScreenshotNotification,
object: nil
)
根据文档可以知道,这个通知的 userInfo
中并不包含任何信息,一个有些令人绝望的消息。考虑两个方案来获得图片。
- 从相册读取第一张照片,多少有些 workaround 的意味,并且需要相册权限。
- 重新截取图片,潜在的问题是截图和系统截图可能存在差异。
04/05
Long polling
长轮询,与轮询的区别在于,后者是 client 定期去拉取更新,经常会得到空 response;而长轮询会 hold 住连接,直到 server 有更新才会返回。看似一种 push 的方式,本质上还是 pull。
04/02
XCTUnwrap()
Easy to read than guard
and let
..