Skip to content

Commit

Permalink
Update utilities
Browse files Browse the repository at this point in the history
  • Loading branch information
dypme committed Jul 29, 2022
1 parent 2644550 commit cc4f2f0
Show file tree
Hide file tree
Showing 31 changed files with 132 additions and 290 deletions.
84 changes: 40 additions & 44 deletions iOStarter.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Binary file not shown.
55 changes: 8 additions & 47 deletions iOStarter/Components/ErrorView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,35 +29,22 @@ class ErrorView: UIView {
return label
}()

private var refreshBtn: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.titleLabel?.font = UIFont.systemFont(ofSize: 14)
button.setTitle(L10n.Button.refresh, for: UIControl.State())
button.setTitleColor(UIColor.white, for: UIControl.State())
button.backgroundColor = .red
return button
}()

private var image: UIImage?
private var message: String
private var tapReload: (() -> Void)?

/// Initialize error view
/// - Parameters:
/// - image: image for error view
/// - message: Text to inform user what error happen
/// - action: Action to reload fetch data while error occur
init(image: UIImage? = nil, message: String, reloadAction action: (() -> Void)? = nil, tag: Int = 1431) {
init(image: UIImage? = nil, message: String, tag: Int = 1431) {
self.image = image
self.message = message
self.tapReload = action

super.init(frame: .zero)

self.tag = tag

setupMethod()
setupView()
setupLayout()
}
Expand All @@ -67,7 +54,7 @@ class ErrorView: UIView {
}

private func setupLayout() {
let hStackView = UIStackView(arrangedSubviews: [imageView, messageLbl, refreshBtn])
let hStackView = UIStackView(arrangedSubviews: [imageView, messageLbl])
hStackView.translatesAutoresizingMaskIntoConstraints = false
hStackView.axis = .vertical
hStackView.alignment = .center
Expand All @@ -84,28 +71,15 @@ class ErrorView: UIView {

imageView.widthAnchor.constraint(lessThanOrEqualToConstant: 130).isActive = true
imageView.heightAnchor.constraint(lessThanOrEqualToConstant: 130).isActive = true

refreshBtn.widthAnchor.constraint(equalToConstant: 150).isActive = true
refreshBtn.heightAnchor.constraint(equalToConstant: 40).isActive = true
}

/// Setup add function/ action in object (ex: add button action, add delegate, add gesture)
func setupMethod() {
refreshBtn.addTarget(self, action: #selector(reload(_:)), for: .touchUpInside)
}

func setupView() {
private func setupView() {
imageView.image = image
imageView.isHidden = image == nil

messageLbl.text = message

refreshBtn.isHidden = tapReload == nil

self.isUserInteractionEnabled = !refreshBtn.isHidden
self.backgroundColor = .clear

refreshBtn.rounded(value: 20)
}

private func setContentConstraint(in view: UIView) {
Expand All @@ -125,14 +99,6 @@ class ErrorView: UIView {
view.addSubview(self)
setContentConstraint(in: view)
}

/// Reload button function action
///
/// - Parameter button: Sender button
@objc func reload(_ button: UIButton) {
self.removeFromSuperview()
tapReload?()
}

}

Expand All @@ -145,22 +111,17 @@ extension UIView {
/// - message: Text to inform user what error happen
/// - tapReload: Action to reload fetch data while error occur
/// - tag: Mark of error view in superview
func setErrorView(image: UIImage? = nil, message: String, tapReload: (() -> Void)?, tag: Int = 1431) {
let topView = self.superview ?? self

let errorView = ErrorView(image: image, message: message, reloadAction: tapReload, tag: tag)

if !topView.subviews.contains(where: { $0.tag == tag }) {
errorView.show(in: topView)
func setErrorView(image: UIImage? = nil, message: String, tag: Int = 1431) {
let errorView = ErrorView(image: image, message: message, tag: tag)
if !self.subviews.contains(where: { $0.tag == tag }) {
errorView.show(in: self)
}
}

/// Stop animating activity indicator in superview of current view
/// - Parameter tag: Mark of error view in superview
func removeErrorView(tag: Int = 1431) {
let topView = self.superview ?? self

if let errorView = topView.subviews.first(where: { $0.tag == tag }) as? ErrorView {
if let errorView = self.subviews.first(where: { $0.tag == tag }) as? ErrorView {
errorView.removeFromSuperview()
}
}
Expand Down
31 changes: 14 additions & 17 deletions iOStarter/Components/LoadIndicatorView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ import UIKit
class LoadIndicatorView: UIView {

static let shared: LoadIndicatorView = {
// MARK: For deprecated keyWindow can use this property window
guard let window = UIApplication.shared.connectedScenes.compactMap({ $0 as? UIWindowScene }).flatMap({ $0.windows }).first(where: { $0.isKeyWindow }) else { fatalError("View not loaded") }
let loadingView = LoadIndicatorView(topView: window, tag: 1323)
let loadingView = LoadIndicatorView(parentView: window, tag: 1323)
loadingView.isUserInteractionEnabled = true
loadingView.backgroundColor = UIColor.black.withAlphaComponent(0.6)
loadingView.activityId.color = UIColor.white
Expand All @@ -31,7 +32,7 @@ class LoadIndicatorView: UIView {
return indicator
}()

private var topView: UIView?
private var parentView: UIView?

init() {
super.init(frame: .zero)
Expand All @@ -44,10 +45,10 @@ class LoadIndicatorView: UIView {
setupView()
}

convenience init(topView: UIView, tag: Int = 1328) {
convenience init(parentView: UIView, tag: Int = 1328) {
self.init()

self.topView = topView
self.parentView = parentView
self.tag = tag
}

Expand All @@ -70,14 +71,14 @@ class LoadIndicatorView: UIView {
activityId.stopAnimating()
activityId.startAnimating()

if let topView = self.topView {
topView.addSubview(self)
if let parentView = self.parentView {
parentView.addSubview(self)

self.translatesAutoresizingMaskIntoConstraints = false
self.topAnchor.constraint(equalTo: topView.topAnchor).isActive = true
self.leadingAnchor.constraint(equalTo: topView.leadingAnchor).isActive = true
self.trailingAnchor.constraint(equalTo: topView.trailingAnchor).isActive = true
self.bottomAnchor.constraint(equalTo: topView.bottomAnchor).isActive = true
self.topAnchor.constraint(equalTo: parentView.topAnchor).isActive = true
self.leadingAnchor.constraint(equalTo: parentView.leadingAnchor).isActive = true
self.trailingAnchor.constraint(equalTo: parentView.trailingAnchor).isActive = true
self.bottomAnchor.constraint(equalTo: parentView.bottomAnchor).isActive = true
}
}

Expand All @@ -92,19 +93,15 @@ class LoadIndicatorView: UIView {
extension UIView {
/// Start animating activity indicator in superview of current view
func startAnimatingIndicator(tag: Int = 1328) {
let topView = self.superview ?? self

let activityId = LoadIndicatorView(topView: topView, tag: tag)
if !topView.subviews.contains(where: { $0.tag == tag }) {
let activityId = LoadIndicatorView(parentView: self, tag: tag)
if !self.subviews.contains(where: { $0.tag == tag }) {
activityId.startAnimating()
}
}

/// Stop animating activity indicator in superview of current view
func stopAnimatingIndicator(tag: Int = 1328) {
let topView = self.superview ?? self

if let activityId = topView.subviews.first(where: { $0.tag == tag }) as? LoadIndicatorView {
if let activityId = self.subviews.first(where: { $0.tag == tag }) as? LoadIndicatorView {
activityId.stopAnimating()
}
}
Expand Down
2 changes: 1 addition & 1 deletion iOStarter/Supporting Files/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {

/// Setup notification settings
func setupNotification(application: UIApplication) {
NotificationHelper.shared.setupNotif(delegate: self, application: application)
NotificationHelper.shared.setupNotif(application: application)
}

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Expand Down
File renamed without changes.
File renamed without changes.
26 changes: 0 additions & 26 deletions iOStarter/Utilities/Extension/ExtUIApplication.swift

This file was deleted.

File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,16 @@ import Foundation
extension String {
/// Check email validity
var isValidEmail: Bool {
let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"

let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
let emailTest = NSPredicate(format:"SELF MATCHES %@", emailRegEx)
return emailTest.evaluate(with: self)
}

/// Check phone number validity
var isValidPhone: Bool {
do {
let detector = try NSDataDetector(types: NSTextCheckingResult.CheckingType.phoneNumber.rawValue)
let matches = detector.matches(in: self, options: [], range: NSMakeRange(0, self.count))
if let res = matches.first {
return res.resultType == .phoneNumber && res.range.location == 0 && res.range.length == self.count && res.phoneNumber == self
} else {
return false
}
} catch {
return false
}
let phoneRegex = "^[0-9+]{0,1}+[0-9]{5,16}$"
let phoneTest = NSPredicate(format: "SELF MATCHES %@", phoneRegex)
return phoneTest.evaluate(with: self)
}

var isValidPassword: Bool {
Expand All @@ -43,17 +34,20 @@ extension String {
return minCharacters && containsNumber && containsAlphanumberic
}

var isNotEmpty: Bool {
!self.isEmpty
}

/// Change date format to new format date
///
/// - Parameters:
/// - old: Current format
/// - new: Format that will change
/// - Returns: New format date
func dateChange(from old: String, to new: String) -> String {
let dateFormatter = DateFormatter()
dateFormatter.locale = LocalizeHelper.shared.locale
dateFormatter.dateFormat = old
if let date = dateFormatter.date(from: self) {
if let date = self.date(format: old) {
let dateFormatter = DateFormatter()
dateFormatter.locale = LocalizeHelper.shared.locale
dateFormatter.dateFormat = new
return dateFormatter.string(from: date)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ extension UITextField {
NSAttributedString.Key.foregroundColor: color.withAlphaComponent(0.6),
NSAttributedString.Key.font: self.font!
] as [NSAttributedString.Key : Any]
self.attributedPlaceholder = NSAttributedString(string: self.placeholder!,
attributes: attributeString)
self.attributedPlaceholder = NSAttributedString(string: self.placeholder!, attributes: attributeString)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ extension UIView {

/// Make view rounded with maximum radius
func circle() {
self.layoutIfNeeded()
self.layer.cornerRadius = min(self.frame.size.width, self.frame.size.height) / 2
self.rounded(value: min(self.frame.size.width, self.frame.size.height) / 2)
}

/// Make view rounded with specific radius value
Expand All @@ -45,7 +44,7 @@ extension UIView {
/// - Parameters:
/// - corners: Corners that will rounded
/// - radius: Radius of rounded
func roundCorners(_ corners: UIRectCorner, radius: CGFloat = 10) {
func roundCorners(_ corners: UIRectCorner, radius: CGFloat = 8) {
self.layoutIfNeeded()
let maskPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let maskLayer = CAShapeLayer()
Expand Down Expand Up @@ -80,6 +79,10 @@ extension UIView {
self.layer.borderWidth = width
}

func removeBorder() {
self.layer.borderWidth = 0
}

/// Unlinks all view from its superview and its window, and removes all from the responder chain
func removeAllSubviews() {
for aView in subviews {
Expand Down
10 changes: 5 additions & 5 deletions iOStarter/Utilities/Helper/ApiRequest/ApiComponents.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,31 @@ import Alamofire
class ApiComponents {
private(set) var url: URL
var method: HTTPMethod
private var parametersArr: [ApiParameter]
private var params: [ApiParameter]

init(path: String, method: HTTPMethod, parameters: [ApiParameter] = []) {
self.url = URL(string: ApiHelper.shared.BASE_URL + path)!
self.method = method
self.parametersArr = parameters
self.params = parameters
}

init(url: URL, method: HTTPMethod, parameters: [ApiParameter] = []) {
self.url = url
self.method = method
self.parametersArr = parameters
self.params = parameters
}

var parameters: Parameters {
var params = Parameters()
parametersArr.forEach { param in
params.forEach { param in
params.updateValue(param.value, forKey: param.key)
}
return params
}

var uploadParameters: UploadParameters {
var params = UploadParameters()
parametersArr.forEach { param in
self.params.forEach { param in
params.updateValue(param.value, forKey: param.key, mimeType: param.mimeType)
}
return params
Expand Down
5 changes: 1 addition & 4 deletions iOStarter/Utilities/Helper/ApiRequest/MimeType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -274,9 +274,6 @@ enum MimeType: String {

var generateFileName: String {
let uniqueName = UUID()
let formatter = DateFormatter()
formatter.dateFormat = "yyyyMMdd"
let date = formatter.string(from: Date())
return "\(self.rawValue.uppercased())_\(uniqueName)_\(date).\(self.rawValue)"
return "\(self.rawValue.uppercased())_\(uniqueName).\(self.rawValue)"
}
}
Loading

0 comments on commit cc4f2f0

Please sign in to comment.