Algorithm
本周选择的算法题是:Palindrome Number
规则如下:
Determine whether an integer is a palindrome. An integer is a palindrome when it reads the same backward as forward.
Example 1:
Input: 121
Output: true
Example 2:
Input: -121
Output: false
Explanation: From left to right, it reads -121. From right to left, it becomes 121-. Therefore it is not a palindrome.
Example 3:
Input: 10
Output: false
Explanation: Reads 01 from right to left. Therefore it is not a palindrome.
Follow up:
Coud you solve it without converting the integer to a string?
Solution
我实现的方案:
class Solution:
def isPalindrome(self, x: int) -> bool:
if x < 0:
return False
reverse_number = 0
temp = x
while temp != 0:
reverse_number = reverse_number * 10 + temp % 10
temp //= 10
return x == reverse_number
Runtime:72 ms,快过 61.77%。
Memory:14.2 MB,低于 6.50%。
看了下官方的 Solution,发现不用将数字完全 reverse,只需要 reverse 一半即可,这样时间复杂度和空间复杂度都能得到降低,而且不会有溢出的风险:
class Solution:
def isPalindrome(self, x: int) -> bool:
if x < 0 or (x != 0 and x % 10 == 0):
return False
reverse_number = 0
while x > reverse_number:
reverse_number = reverse_number * 10 + x % 10
x //= 10
return x == reverse_number or x == reverse_number // 10
Runtime:60 ms,快过 93.18%。
Memory:14.1 MB,低于 6.50%。
Review
Application Security Musts for every iOS App
关于 iOS App 存储安全的话题。主要观点如下:
敏感数据直接存到 UserDefaults 是不安全的
UserDefaults 就是一个简单的 plist 文件而已,它存储在应用的 Preferences 文件夹下,你可以很容易通过 iMazing 这类程序查看它的内容,明文存进 UserDefaults 的内容没有任何安全性可言。
Keychain 比 UserDefaults 更安全
Apple 提供了一个内置的安全服务 - Keychain,它的特点如下:
- 数据并不存在 App 的沙盒中,就算 App 被删除了,Keychain 中的数据依然存在
- 可以实现 group 间的共享
- 数据是经过 Keychain 加密存放的
进一步提高安全性
放进 Keychain 就万事大吉了吗?当然不是,明文存储还是有风险的:
- 如果攻击者破解了 Keychain 的安全机制,那存储的敏感数据自然就会有暴露的风险
- 如题攻击者通过网络抓包等方式,嗅探到你的请求参数,而它又是明文传输的,这也增加了暴露的风险
所以,在存储敏感数据时,无论存到哪里,最好将其加密存储。
只进行 MD5 可能是不够的,攻击者可以提前计算好容易被用作密码的 MD5 摘要,然后使用彩虹表攻击,为了避免这种攻击方式,我们可以采用这样的存储策略:
func saveEncryptedPassword(_ password: String, for account: String) {
let salt = Array("salty".utf8)
let key = try! HKDF(password: Array(password.utf8), salt: salt, variant: .sha256).calculate().toHexString()
keychainService.save(key, for: account)
}
- 加盐存储
- 计算 hash
- 使用像 HKDF(基于 HMAC 的 KDF 算法)这样的算法
这样可以进一步提高本地存储的安全性。除此之外,客户端和服务器之间通信时,要确保算法的一致性,为了防止攻击者模拟请求,可以通过 timestamp 等数据动态生成盐或者签名算法。
Tip
git-lfs
不能直接 track 一个目录,如果有想要 track 类似 *.framework
这样的情况,可以用:
git lfs track **/*.framework/*
Share
分享几个关于 Xcode 编译优化的辅助功能
在 Xcode 里显示编译时长
defaults write com.apple.dt.Xcode ShowBuildOperationDuration -bool YES
设置好后就能看到总的编译时长了
找出 导致编译慢的代码(Swift)
在 Other Swift Flags
里设置如下 flag:
-Xfrontend -warn-long-function-bodies=<millisecond>
-Xfrontend -warn-long-expression-type-checking=<millisecond>
在编译时就能看到一些警告信息了:
设置 Build active architecture Only
一般来说,在 Debug 时设置为 YES,Release 时设置为 NO