All videos downloaded from Network Model are stored in both memory(NSCache) and disk(FileManager).
- Hash the key using the
SHA-2
method provided byCryptoKit
. - Check if this encrypted key exists in either memory cache or disk cache.
- If found in memory cache, return the url path of the file location.
- If found in disk cache, return the url path of the file location and store data in memory cache.
- If not found in neither of them, request to download the video.
func queryDataFromCache(key: String, fileExtension: String?, completion: @escaping (_ data: Any?) -> Void){
if let data = dataFromMemoryCache(key: key) {
completion(data)
} else if let data = dataFromDiskCache(key: key, fileExtension: fileExtension) {
storeDataToMemoryCache(data: data, key: key)
completion(data)
} else {
completion(nil)
}
}
func storeDataToCache(data: Data?, key: String, fileExtension: String?) {
dispatchQueue?.async {
self.storeDataToMemoryCache(data: data, key: key)
self.storeDataToDiskCache(data: data, key: key, fileExtension: fileExtension)
}
}
func clearCache(completion: @escaping (_ size: String) -> Void){
dispatchQueue?.async {
self.clearMemoryCache()
let size = self.clearDiskCache()
DispatchQueue.main.async {
completion(size)
}
}
}
private func sha2(key: String) -> String {
let inputData = Data(key.utf8)
let hashed = SHA256.hash(data: inputData)
let hashString = hashed.compactMap { String(format: "%02x", $0) }.joined()
return hashString
}
Home page is mainly build with a table view that has full screen cells HomeTableViewCell
. The cells contains multiple UIButtons and UILabel to present information acquired from viewmodel.
A table view that contains comment information. I used a tap gesture and a pan gesture to handle the dismiss of the comment popup view.
Resource: Downloading Video While Streaming using AVAssetResourceLoaderDelegate and URLSession
I used to UITapGestureRecognizer
to detect single taps and double taps. By using gesture's property numberOfTapsRequired
, I am able to distinguish between different user interactions.
I am using MVVM with RxSwift in this module. The ViewModel manages all logic in network and user interaction bindings.
In this module, the UI structure is pretty simple. I utilized a customized UIView
to display previewView and AVPlayerLayer
. In the MediaPostViewController
, I used stackviews to organize elements
CameraManager
manages capture session, its configurations, video file outputs, and devices' permissions. When it starts the recording, the RecordButton
starts to animate until the recording ends. The video file is stored in a temporary directory on the device and will be removed once users shoot a new video.
Upload videos by calling videoRef.putFile(from: videoURL, metadata: nil)
from Firebase Storage and save video file to Photo Library.
ProfileViewController
is presented by a collection view with customized collection view flow layout (ProfileCollectionViewFlowLayout). When the slidebar reaches the status bar, the collection view holds its frame and the ProfileHeaderView's frame, in order to make them "stick" on the top of the screen.
I used UIScrollViewDelegate
to acquire the contentOffset.y
of the collection view and then use this variable to manipulate the CGAffineTransform
(scaleX:, y:) of the profileBackgroundImgView
.
func scrollViewDidScroll(_ scrollView: UIScrollView) {
/// Y offsets of the scroll view
let offsetY = scrollView.contentOffset.y
if offsetY < 0 {
stretchProfileBackgroundWhenScroll(offsetY: offsetY)
} else {
profileBackgroundImgView.transform = CGAffineTransform(translationX: 0, y: -offsetY)
}
}
// Stretch Profile Background Image when scroll up
func stretchProfileBackgroundWhenScroll(offsetY: CGFloat) {
let scaleRatio: CGFloat = abs(offsetY)/500.0
let scaledHeight: CGFloat = scaleRatio * profileBackgroundImgView.frame.height
profileBackgroundImgView.transform = CGAffineTransform.init(scaleX: scaleRatio + 1.0, y: scaleRatio + 1.0).concatenating(CGAffineTransform.init(translationX: 0, y: scaledHeight))
}
By tapping on the Trash
icon, we can clear all data in the memory cache and the disk cache.
- Using Firebase Cloud Firestore to store basic information
- Using Firebase Storage to store videos