Swift 4 Snippets

ClassName, FileRW, VideoPlayer, VideoPicker, ExcelFilePicker, FileCrypto, dateFormatter, Notification, GradientView, ShowAlertController, LoadingView, AddAnchorConstraints

1
2
3
4
5
extension NSObjectProtocol {
static var className: String {
return String(describing: Self.self)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
protocol FileRW {
func readFile(_ url: URL?) -> Data?
func saveFile(_ data: Data, name: String, ext: String) -> URL?
}
extension FileRW {
func readFile(_ url: URL?) -> Data? {
guard let url = url else { return nil }

do {
return try Data(contentsOf: url)
} catch {
print("read encryted data err")
return nil
}
}

func saveFile(_ data: Data, name: String, ext: String) -> URL? {
let tempDirectoryURL = NSURL.fileURL(withPath: NSTemporaryDirectory(), isDirectory: true)

let targetURL = tempDirectoryURL.appendingPathComponent("\(name).\(ext)")

do {
try data.write(to: targetURL)
return targetURL
} catch {
return nil
}

}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
extension VideoPlayer {
func playVideo(url: URL, view: UIView? = nil, playerViewController: AVPlayerViewController? = nil) {
let player = AVPlayer(url: url)
if let view = view {
// let playerLayer = AVPlayerLayer(player: player)
// playerLayer.frame = view.bounds
// view.layer.addSublayer(playerLayer)
// player.play()
// OR
let avpvc = AVPlayerViewController()
addChild(avpvc)
view.addOverlay(avpvc.view)
// avpvc.view.frame = view.bounds
// view.addSubview(avpvc.view)
avpvc.didMove(toParent: self)
avpvc.player = player
avpvc.player?.play()
} else if let avpvc = playerViewController {
avpvc.player = player
avpvc.player?.play()
} else {
let avpvc = AVPlayerViewController()
avpvc.player = player
self.present(avpvc, animated: true) {
avpvc.player?.play()
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
protocol VideoPicker {
var imagePickerController: UIImagePickerController { get }
func openVideoPicker()
func generateThumbnail(_ url: URL?) -> UIImage?
}
extension VideoPicker where Self: UIViewController {

func openVideoPicker() {
if let delegate = self as? UINavigationControllerDelegate & UIImagePickerControllerDelegate {
imagePickerController.delegate = delegate
}

imagePickerController.navigationBar.tintColor = systemPinkColor
imagePickerController.videoQuality = .type640x480
imagePickerController.sourceType = .savedPhotosAlbum
imagePickerController.mediaTypes = ["public.movie"]
imagePickerController.modalPresentationStyle = .overCurrentContext
show(imagePickerController, sender: nil)
}

func generateThumbnail(_ url: URL?) -> UIImage? {
guard let url = url else { return nil }

let asset = AVURLAsset(url: url, options: nil)
let imgGenerator = AVAssetImageGenerator(asset: asset)
if let cgImage = try? imgGenerator.copyCGImage(at: CMTime(seconds: 2, preferredTimescale: 60) , actualTime: nil) {
return UIImage(cgImage: cgImage)
} else {
return nil
}
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
protocol FilePicker {
func selectExcelFile()
}
extension FilePicker where Self: UIViewController {
private var excelDocumentTypes: [String] {
return ["com.microsoft.Excel.xls", "org.openxmlformats.spreadsheetml.sheet"]
}

func selectExcelFile() {
let dpvc = UIDocumentPickerViewController (documentTypes: excelDocumentTypes, in: .import)
dpvc.view.tintColor = systemPinkColor

if let delegate = self as? UIDocumentPickerDelegate {
dpvc.delegate = delegate
}
present(dpvc, animated: true, completion: nil)
}

func selectedUrl(_ urls: [URL]) -> URL? {
guard let url = urls.first, let vals = try? url.resourceValues(forKeys: [.typeIdentifierKey]), let id = vals.typeIdentifier,
excelDocumentTypes.contains(id)
else { return nil }
return url
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
protocol FileCrypto {
func encrypt(_ data: Data, pw: String) -> Data
func decrypt(_ data: Data, pw: String) -> Data?
}
let pw = "xxxx-xxxx-xxxx"
extension FileCrypto {
func encrypt(_ data: Data, pw: String) -> Data {
return RNCryptor.encrypt(data: data, withPassword: pw)
}

func decrypt(_ data: Data, pw: String) -> Data? {
do {
return try RNCryptor.decrypt(data: data, withPassword: pw)
} catch {
return nil
}
}

}
1
2
3
4
5
6
7
8
9
10
extension TimeInterval {
var yyyymmdd: String {
let date = Date(timeIntervalSince1970: self)
let dateFormatter = DateFormatter()
// dateFormatter.timeStyle = DateFormatter.Style.medium //Set time style
dateFormatter.dateStyle = DateFormatter.Style.medium //Set date style
let localDate = dateFormatter.string(from: date)
return localDate
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
// self.enableRemoteNotificationFeatures()
// self.forwardTokenToServer(token: deviceToken)
let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
print("deviceToken: ", token)
}

public static func registerForPushNotifications() {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) {
(granted, error) in
print("Permission granted: \(granted)")
// 1. Check if permission granted
guard granted else { return }
// 2. Attempt registration for remote notifications on the main thread
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import UIKit
import CoreGraphics

@IBDesignable
public class GradientView: UIView {

@IBInspectable var fromColor: UIColor = .clear
@IBInspectable var toColor: UIColor = .clear {
didSet {
gradientOfView(colours: [fromColor, toColor])
}
}

override public func layoutSubviews() {
super.layoutSubviews()

gradientOfView(colours: [fromColor, toColor])
}

let grad = CAGradientLayer()

func gradientOfView(colours: [UIColor]) {
grad.removeFromSuperlayer()

var cgColours = [CGColor]()

for colour in colours {
cgColours.append(colour.cgColor)
}
grad.frame = bounds
grad.colors = cgColours
layer.addSublayer(grad)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public protocol ShowAlertController {

}

public extension ShowAlertController where Self: UIViewController {

public func alert(_ title: String? = nil, _ message: String? = nil, sender: UIBarButtonItem? = nil, buttons: [ (title:String, handler: (() -> Void)? )]? = nil) {
let alertC = UIAlertController(title: title, message: message, preferredStyle: .alert)
buttons?.forEach { button in
let style = (button.handler == nil ? UIAlertAction.Style.cancel : .default)
alertC.addAction(UIAlertAction(title: button.title, style: style) { _ in
button.handler?()
})
}

if let popoverController = alertC.popoverPresentationController {
popoverController.barButtonItem = sender
}

self.present(alertC, animated: true)
}

public func toast(_ message: String, delay: Double = 1, sender: UIBarButtonItem? = nil, completion: (() -> Void)?) {
let alertC = UIAlertController(title: nil, message: message, preferredStyle: .alert)

if let popoverController = alertC.popoverPresentationController {
popoverController.barButtonItem = sender
}

self.present(alertC, animated: true)

DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + delay) {
alertC.dismiss(animated: true, completion: completion)
}

}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public protocol LoadingView {
var progressView: UIProgressView { get }
var coverView: UIView { get }
}

public extension LoadingView where Self: UIViewController {

func startLoading() {
let v = coverView

v.backgroundColor = .white

let pv = progressView
pv.progress = 0
v.addConstraints(pv, l: 0, r: 0, t: navigationController?.navigationBar.bounds.height ?? 0, h: 2)

let aiv = UIActivityIndicatorView(style: .gray)
aiv.startAnimating()
v.addConstraints(aiv, cx: 0, cy: 0)

view.addOverlay(v)
}

func stopLoading() {
coverView.removeFromSuperview()
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public extension UIView {
public func addOverlay(_ subView: UIView) {
addConstraints(subView, l: 0, r: 0, t: 0, b: 0)
}

public func addConstraints(_ subView: UIView, l:CGFloat? = nil, r: CGFloat? = nil, t: CGFloat? = nil, b:CGFloat? = nil, h: CGFloat? = nil, w: CGFloat? = nil, cx: CGFloat? = nil, cy: CGFloat? = nil) {
addSubview(subView)
subView.translatesAutoresizingMaskIntoConstraints = false
// let margins = layoutMarginsGuide
if let l = l {
subView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: l).isActive = true
}
if let r = r {
subView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: r).isActive = true
}
if let t = t {
subView.topAnchor.constraint(equalTo: topAnchor, constant: t).isActive = true
}
if let b = b {
subView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: b).isActive = true
}
if let h = h {
subView.heightAnchor.constraint(equalToConstant: h).isActive = true
}
if let w = w {
subView.widthAnchor.constraint(equalToConstant: w).isActive = true
}
if let cx = cx {
subView.centerXAnchor.constraint(equalTo: centerXAnchor, constant: cx).isActive = true
}
if let cy = cy {
subView.centerYAnchor.constraint(equalTo: centerYAnchor, constant: cy).isActive = true
}

}
}