Kireilign - TiepNC/Note GitHub Wiki
FontApp
Chưa có base font để có thể lấy ra font mặc định trong design, hiện tại toàn gõ tên font để lấy
leftButton.titleLabel?.font = UIFont.init(name: isAnswered ? "NotoSansCJKjp-Regular" : "NotoSansCJKjp-Bold" , size: 18)
rightButton.titleLabel?.font = UIFont.init(name: isAnswered ? "NotoSansCJKjp-Bold" : "NotoSansCJKjp-Regular", size: 18)
Hướng giải quyết:
1. Tạo base AppFonts:
Khi sử dụng thì gọi tới AppFonts để lấy font mong muốn. Trong file Xib thì chọn font tương ứng, hoặc tạo base class cho mỗi view, button, label... trỏ tới app font.
2. Sử dụng Swizzling để khi app sử dụng systemFont sẽ tự động sử dụng app font.
Link: Auto convert systemFont to AppFont in Swift
Khi sử dụng cách này thì trong file xib và code gọi systemfont sẽ tự động lấy font của app mình.
Color palette:
Hiện tại đã có Color.swift để có thể tiện cho việc tái sử dụng và thay đổi trong code. Nhưng trong file xib hiện tại là chọn màu. Nếu mà design thay đổi thì phải biết file nào dùng màu đó và vào chỉnh sửa.
Hướng giải quyết:
Từ XCode 9, iOS 11 Apple đã ra tính năng Color Assets. Khi sử dụng tính năng này, ở file xib ta có thể tạo color palette, và có thể dễ dàng tái sử dụng cũng như thay đổi.
Link: Color Assets
Environments
Hiện tại sử dụng #if để check environment rất nhiều chỗ, rất khó cho việc thêm environment hay chỉnh sửa. Các secret key đang hard code.
AppsFlyerTracker.shared().appsFlyerDevKey = "private_key"
#if DEV
AppsFlyerTracker.shared().appleAppID = "abc"
#else
AppsFlyerTracker.shared().appleAppID = "def"
#endif
Hướng giải quyết:
Ta sẽ tạo file sử dụng xcconfig cho từng môi trường để set các giá trị tương ứng, có thể ẩn ignore secret key nếu muốn.
Ví dụ môi trường Dev ta sẽ tạo file Development.xcconfig
AppleAppID = 123456
AppsFlyerKey = DEV_SECRET_KEY
Ví dụ môi trường Staging ta sẽ tạo file Staging.xcconfig
AppleAppID = 654321
AppsFlyerKey = STAGING_SECRET_KEY
...
URLs.swift
Hiện tại url được hard code rất nhiều chỗ, ta sẽ tạo base url, có thể kết hợp với xcconfig.
Tạo các schemes để việc chuyển đổi môi trường dễ dàng hơn:
String, Localize
Các string về message, title,... lúc thì bỏ vào StringApp.swift lúc thì hard code. Không thể tái sử dụng, cũng như khó chỉnh sửa. (Nếu mà khách hàng yêu cầu thêm làm đa ngôn ngữ thì mất rất nhiều thời gian)
titleLabel.space(value: 8, text: "予約情報の確認に\nご協力お願いいたします", font: UIFont(name: "NotoSansCJKjp-Bold", size: 18) ?? UIFont.boldSystemFont(ofSize: 18), color: UIColor.hex("#677780"))
descriptionLabel.space(value: 8, text: "ご入力いただいたメールアドレスで\n複数の予約情報が見つかりました。\n以下より初診予約情報を選択して\n次へとお進みください。", font: UIFont(name: "NotoSansCJKjp-Regular", size: 14) ?? UIFont.systemFont(ofSize: 14), color: UIColor.hex("#555555"))
Attributed:
Hiện tại ta đang sử dụng thẳng trong User Interface Builder (Xib), nếu làm đa ngôn ngữ thì việc sửa lại hết các attribute này tốn rất nhiều thời gian.
Hướng giải quyết:
Di chuyển hết vào file StringApp.swift, và sử dụng tính năng Localize, plural localize trong XCode. Và những cái như label, button, ta nên tạo ra một file custom như LocalizableLabel. Để sau này có hỗ trợ việc đa ngôn ngữ thì chỉ cần chỉnh sửa một chỗ.
Có thể phát triển tool dịch từ tiếng nhật ra tiếng anh, cho lúc dev debug :]
User Default and Manager
Lúc thì gọi trực tiếp trên view, lúc thì gọi thông qua UserDefaultManager.
Hướng giải quyết:
Di chuyển hết các đoạn code gọi trực tiếp trên view, vào các Manager và Helper để dễ dàng quản lý.
Base Navigator
Hiện tại muốn biết một màn hình đi đâu phải vào đọc hết code.
Hướng giải quyết:
Tạo ra một File Navigator cho mỗi màn hình. Với hiện tại app đang có tính năng analytics, tracker màn hình nào đến màn hình nào. Có thể giảm bớt một lượng code ở màn view controller, và việc tracker màn hình dễ dàng hơn.
protocol HomeNavigator: BaseNavigation {
func showAScreen()
func showBScreen()
func backToPreviousScreen()
}
class HomeNavigatorImpl: BaseNavigatorImpl, HomeNavigator {
func showAScreen() { }
func showBScreen() { }
func backToRootScreen() { }
}
Image:
Hard code ảnh rất nhiều
Hướng giải quyết:
Tạo ra một file ImagesApp.swift.
Enum về view type:
Enum về view type thì nên để ở view controller, vì nó chỉ sử dụng ở view. Hiện tại đang di chuyển tất cả các enum vào file enum.swift.
Vài chỗ thiếu [weak self] ở DispatchQueue.async và delegate.
Comment code mà không để lý do tại sao comment
if SettingManager.shared.isLogin {
formOrderTabbarView.isHidden = true
marginRightTabbarContainerViewLC.isActive = true
marginLeftFormOrderTabbarViewLC.isActive = false
hiddens[Tabbar.myPage.rawValue] = true
// hiddens[5] = true
// hiddens[Tabbar.lifeLog.rawValue] = true
// tabbarContainerView.roundingCorners = [.topLeft, .topRight]
// tabbarContainerView.roundingCorners = [.topLeft, .topRight]
} else {
formOrderTabbarView.isHidden = false
marginRightTabbarContainerViewLC.isActive = false
marginLeftFormOrderTabbarViewLC.isActive = true
hiddens[Tabbar.myPage.rawValue] = false
// hiddens[Tabbar.lifeLog.rawValue] = false
// hiddens[Tabbar.lifeLog.rawValue] = false
// tabbarContainerView.roundingCorners = .topLeft
// tabbarContainerView.roundingCorners = .topLeft
}
Cocoapod:
Podfile: Có một vài thư việc trong podfile không dùng tới, khiến thời gian compile lâu hơn
Những gì đã học được 🎉 🎉 🎉 :
Protocol extension for viewcontroller:
Sử dụng Protocol extension để chia code gọn hơn, dễ dàng tái sử dụng.
extension AlertViewController where Self: UIViewController {
Codable:
Sử Codable để tự động Encode và Decode json từ response trả về.
Analytics:
Sử các analytics để thu thập và phân tích thông tin, hành động của người dùng. Với dev dễ dàng hơn trong việc debug crash trên production.
Sử dụng DispatchGroup để đợi nhiều tác vụ hoàn thành.
Ưu tiên công việc:
Sắp xếp độ ưu tiên của công việc để thực hiện trước và sau. Nếu đang làm nữa chừng một công việc nào đó, nhưng có một công việc quan trọng hơn, ưu tiên cao hơn như bug production..., thì phải ưu tiên công việc đó trước.
Ứng phó với việc đợi API:
Chủ động hơn trong việc, không đợi api làm xong mới làm, trong lúc đó ta có thể mock api để có thể làm trước UI, và logic.
Ứng phó với deadline:
Nếu không thể điều chỉnh hạn chót của công việc, mình sẽ linh động chọn cách làm nào phù hợp với thời gian nhất.
Hỏi chính là cách để học:
Sau khi comform hỏi cách giải quyết cùng với team lead thì ngoài vấn đề đang gặp phải còn học thêm được nhiều trường hợp khác.