12/08/2018, 18:07
e=mc^2
Năm 1905 một định luật vật lý kinh điển được Enstein giới thiệu và được cả thế giới công nhận sau đó: e=mc^2. Hơn một thế kỉ sau, có lẻ ở nơi tiên cảnh Enstein cũng không thể ngờ được rằng định lý của mình lại một lần nửa chính xác trong ngành công nghiệp IT đầy "cạm bẫy" hiện nay (lol). Có một ...
Năm 1905 một định luật vật lý kinh điển được Enstein giới thiệu và được cả thế giới công nhận sau đó: e=mc^2. Hơn một thế kỉ sau, có lẻ ở nơi tiên cảnh Enstein cũng không thể ngờ được rằng định lý của mình lại một lần nửa chính xác trong ngành công nghiệp IT đầy "cạm bẫy" hiện nay (lol).
TableView
Trong các ứng dụng iOS, TableView là một trong những UI được sử dụng phổ biến nhất và khi làm việc với tableView thì chúng ta thường gặp các đoạn code như sau:let nib = UINib.init(nibName: "TestCell", bundle: nil) tableView.register(nib, forCellReuseIdentifier: TestCell) guard let cell = tableView.dequeueReusableCell(withIdentifier: "TestCell", for: indexPath) as? TestCell else { return UITableViewCell() }
Chúng ta có thể làm gọn đọan code trên bằng cách sử dụng Protocol và Generic như sau:
protocol TableViewCellProtocol { static func getIdentifier() -> String static func getNib() -> UINib } extension TableViewCellProtocol where Self: UIView { static func getIdentifier() -> String { return String(describing: self) } static func getNib() -> UINib { return UINib(nibName: self.getIdentifier(), bundle: nil) } } extension UITableView: TableViewCellProtocol { func register<T:TableViewCellProtocol>(type: T.Type) { self.register(T.getNib(), forCellReuseIdentifier: T.getIdentifier()) } func dequeueCell<T:TableViewCellProtocol>(type: T.Type,indexPath: IndexPath) -> T { guard let cell = self.dequeueReusableCell(withIdentifier: T.getIdentifier(), for: indexPath) as? T else { return UITableView() } return cell } }Bây giờ khi muốn register hay dequeue TableViewCell ta chỉ cần:
tableView.register(type: TestCell.self) tableView.dequeueCell(for: indexPath, cellType: TestCell.self)Lưu ý : với cách trên thì chúng ta phải define cell identifier củng như UINib trùng với tên với className của TableViewCell.
Init ViewController
Khi muốn init 1 ViewController từ Storyboard ta thường dùng:let storyBoard = UIStoryboard(name: "Register", bundle: nil) let register1 = storyBoard.instantiateViewController(withIdentifier: "Register1ViewController") as! Register1ViewControllerTa có thể tạo một enum cho các Storyboard và dùng generic để init ViewController:
enum StoryBoard: String { case Main case Register ... var name: String { return rawValue } } extension UIViewController { static func initFrom(storyboard : StoryBoard) -> Self? { func instanceFromNib<T: UIViewController>() -> T? { let storyBoard = UIStoryboard(name: storyboard.name, bundle: nil) return storyBoard.instantiateViewController(withIdentifier: "(self)") as? T } return instanceFromNib() } }Bây giờ ta chỉ cần:
let register1 = Register1ViewController.initFrom(storyboard: .Register)
UserDefaults
Tương tự với init ViewController ta tạo một enum chứa các UserDefaults Key:enum UserDefaultsKey: String { case isLoggin ... } extension UserDefaults { static func set(_ value: Bool,forKey key: UserDefaultsKey) { let key = key.rawValue UserDefaults.standard.set(value, forKey: key) } static func bool(forKey key: UserDefaultsKey) -> Bool { let key = key.rawValue return UserDefaults.standard.bool(forKey: key) } }Bây giờ chỉ cần:
UserDefaults.set(true, forKey: .isLoggin) UserDefaults.bool(forKey: .isLoggin)Chúng ta có thể dùng getter setter để làm việc với UserDefault :
var isLoggin: Bool { get { return UserDefaults.bool(forKey: .isLoggin) } set { UserDefaults.set(newValue, forKey: .isLoggin) } }
Optional
Nếu bạn đã chán dùng như này:var a: Int? = nil let b = a ?? 0có thể dùng:
extension Optional { func or(_ defaultValue: Wrapped) -> Wrapped { return self ?? defaultValue } } let b = a.or(0)Nếu không muốn dùng if let hoặc guard let:
extension Optional { func then(_ completionHandle: (Wrapped) -> Void) { switch self { case .some(let wrappedValue): return completionHandle(wrappedValue) case .none: break } } } var phoneNumber: String? = "113" phoneNumber.then { self.phoneLabel.text = $0 }
self.phoneLabel.tex sẽ được execute khi phoneNumber khác nil.
Trên đây là một số cách giúp loại bỏ một số code dư thừa mình hay gặp. Ngoài ra còn có một số thư viện mình hay dùng để viết code rõ ràng, ngắn gọn hơn:Then
Reusable
Hi vọng bài viết sẽ có ích với các bạn.