diff --git a/ios-contact-manager-ui/ios-contact-manager-ui/Base.lproj/Main.storyboard b/ios-contact-manager-ui/ios-contact-manager-ui/Base.lproj/Main.storyboard index 7aa1e0ed..bdda7a8b 100644 --- a/ios-contact-manager-ui/ios-contact-manager-ui/Base.lproj/Main.storyboard +++ b/ios-contact-manager-ui/ios-contact-manager-ui/Base.lproj/Main.storyboard @@ -1,9 +1,9 @@ - + - + @@ -18,7 +18,7 @@ - + @@ -46,12 +46,24 @@ + + + + + + Title + Title + + + + + - + @@ -64,13 +76,14 @@ + - + diff --git a/ios-contact-manager-ui/ios-contact-manager-ui/Model/AddressBook.swift b/ios-contact-manager-ui/ios-contact-manager-ui/Model/AddressBook.swift index 918eba83..ea380bac 100644 --- a/ios-contact-manager-ui/ios-contact-manager-ui/Model/AddressBook.swift +++ b/ios-contact-manager-ui/ios-contact-manager-ui/Model/AddressBook.swift @@ -9,39 +9,70 @@ import Foundation class AddressBook { - private var contacts: [[Contact]] = Array(repeating: [], count: 27) - private var contactsForDisplay: [[Contact]] = [[Contact]]() - - func getFirstLetterIndex(_ name: String) -> Int { - let firstLetter = Array(name)[0].uppercased() - let index = firstLetter.unicodeScalars.map { Int($0.value)}[0] - return index >= 65 && index <= 90 ? Int(index - 65) : 26 - } + private var contacts = [Contact]() + private var filteredContacts: [Contact]? + private var searchText: String? func addContact(_ newContact: Contact) { - let index = getFirstLetterIndex(newContact.name) - contacts[index].append(newContact) - contacts[index].sort(by: {$0.name < $1.name}) + contacts.append(newContact) + contacts.sort(by: {$0.name < $1.name}) } - func deleteContact(_ section: Int, _ row: Int) { - contacts[section].remove(at: row) + func deleteContact(_ row: Int) { + contacts.remove(at: row) } - func changeContact(_ section: Int, _ row: Int, _ changedContact: Contact) { - contacts[section][row] = changedContact + func changeContact(_ row: Int, _ changedContact: Contact) { + contacts[row] = changedContact } - func showContact(_ section: Int, _ row: Int) -> Contact { - return contactsForDisplay[section][row] + func showContact(_ row: Int) -> Contact { + guard let input = searchText, let filtered = filteredContacts else { + return contacts[row] + } + + if filtered.isEmpty && input.isEmpty { + return contacts[row] + } + + if !input.isEmpty { + return filtered[row] + } + + return contacts[row] } - func getSectionSize() -> Int { - contactsForDisplay = contacts.filter{ !$0.isEmpty } - return contactsForDisplay.count + func getRowSize() -> Int { + + guard let input = searchText, let filtered = filteredContacts else { + return contacts.count + } + + if filtered.isEmpty && input.isEmpty { + return contacts.count + } + + if !input.isEmpty { + return filtered.count + } + + return contacts.count } - func getRowSize(_ section: Int) -> Int { - return contactsForDisplay[section].count + func searchContact(_ input: String) { + searchText = input + filteredContacts = [] + + for contact in contacts { + if contact.name.lowercased().contains(input.lowercased()) { + filteredContacts?.append(contact) + } + } + + for contact in contacts { + if contact.phoneNumber.replacingOccurrences(of: "-", with: "").contains(input.replacingOccurrences(of: "-", with: "")){ + filteredContacts?.append(contact) + } + } } } diff --git a/ios-contact-manager-ui/ios-contact-manager-ui/NewContactViewController.swift b/ios-contact-manager-ui/ios-contact-manager-ui/NewContactViewController.swift index 22826424..7b2e0ce0 100644 --- a/ios-contact-manager-ui/ios-contact-manager-ui/NewContactViewController.swift +++ b/ios-contact-manager-ui/ios-contact-manager-ui/NewContactViewController.swift @@ -26,12 +26,12 @@ class NewContactViewController: UIViewController { phoneNumberTextField.delegate = self } - func navigationSetting() { + private func navigationSetting() { navigationBar.isTranslucent = false navigationBar.shadowImage = UIImage() } - func keyboardSetting() { + private func keyboardSetting() { nameTextField.keyboardType = .namePhonePad ageTextField.keyboardType = .numberPad phoneNumberTextField.keyboardType = .phonePad @@ -39,34 +39,34 @@ class NewContactViewController: UIViewController { } extension NewContactViewController { - @IBAction func tappedCancelButton(_ sender: UIButton) { - cancelAlert() + @IBAction private func tappedCancelButton(_ sender: UIButton) { + showCancelAlert() } - @IBAction func tappedSaveButton(_ sender: UIButton) { - guard let name = nameCheck() else { + @IBAction private func tappedSaveButton(_ sender: UIButton) { + guard let name = checkName() else { invalidAlert(invalid: nameTextField) return } - guard let age = ageCheck() else { + guard let age = checkAge() else { invalidAlert(invalid: ageTextField) return } - guard let number = numberCheck() else { + guard let number = checkNumber() else { invalidAlert(invalid: phoneNumberTextField) return } saveAlert(Contact(name: name, phoneNumber: number, age: age)) } - func cancelAlert() { + private func showCancelAlert() { let alert = UIAlertController(title: title, message: "정말 취소하겠습니까?", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "예", style: .destructive, handler: { _ in self.dismiss(animated: true)})) alert.addAction(UIAlertAction(title: "아니오", style: .default, handler: nil)) present(alert, animated: true) } - func saveAlert(_ contact: Contact) { + private func showSaveAlert(_ contact: Contact) { let text: String = "이름: \(contact.name), \n 나이: \(contact.age), \n 연락처: \(contact.phoneNumber) \n 저장하시겠습니까?" let alert = UIAlertController(title: title, message: text, preferredStyle: .alert) alert.addAction(UIAlertAction(title: "예", style: .default, handler: { _ in @@ -76,28 +76,28 @@ extension NewContactViewController { present(alert, animated: true) } - func nameCheck() -> String? { + private func checkName() -> String? { guard let name = nameTextField.text else { return nil } - return name == "" ? nil : name.components(separatedBy: " ").joined() + return name.isEmpty ? nil : name.components(separatedBy: " ").joined() } - func ageCheck() -> Int? { + private func checkAge() -> Int? { guard let ageText = ageTextField.text, let age = Int(ageText) else { return nil } return age } - func numberCheck() -> String? { + private func checkNumber() -> String? { guard let number = phoneNumberTextField.text else { return nil } return number.count >= 11 && number.filter { $0 == "-" }.count == 2 ? number : nil } - func invalidAlert(invalid: UITextField) { + private func invalidAlert(invalid: UITextField) { var text: String switch invalid { @@ -123,7 +123,6 @@ extension NewContactViewController: UITextFieldDelegate { if range.location == 2 && number.last != "-" { number.insert("-", at: number.index(number.startIndex, offsetBy: 2)) - print(number.count) } if range.location == 6 && number.last != "-" { diff --git a/ios-contact-manager-ui/ios-contact-manager-ui/ViewController.swift b/ios-contact-manager-ui/ios-contact-manager-ui/ViewController.swift index 666204d2..6355d459 100644 --- a/ios-contact-manager-ui/ios-contact-manager-ui/ViewController.swift +++ b/ios-contact-manager-ui/ios-contact-manager-ui/ViewController.swift @@ -10,8 +10,9 @@ import UIKit class ViewController: UIViewController { @IBOutlet weak var tableView: UITableView! + @IBOutlet weak var searchBar: UISearchBar! - var cellIdentifier: String = "cell" + private let cellIdentifier: String = "cell" var addressBook: AddressBook = AddressBook() override func viewDidLoad() { @@ -20,33 +21,38 @@ class ViewController: UIViewController { initialSetting() } - func initialSetting() { + private func initialSetting() { self.tableView.dataSource = self + self.searchBar.delegate = self } } extension ViewController: UITableViewDataSource { - func numberOfSections(in tableView: UITableView) -> Int { - addressBook.getSectionSize() - } - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - addressBook.getRowSize(section) + addressBook.getRowSize() } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) - let contactData: Contact = addressBook.showContact(indexPath.section, indexPath.row) - + let contactData: Contact = addressBook.showContact( indexPath.row) cell.textLabel?.text = contactData.name + "(\(contactData.age))" cell.detailTextLabel?.text = contactData.phoneNumber return cell } + + func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { + if editingStyle == .delete { + addressBook.deleteContact(indexPath.row) + defer { + tableView.deleteRows(at: [indexPath], with: .automatic) + } + } + } } extension ViewController { - @IBAction func TappedAddButton(_ sender: UIBarButtonItem) { + @IBAction private func TappedAddButton(_ sender: UIBarButtonItem) { guard let newContactViewController = storyboard?.instantiateViewController(withIdentifier: "NewContactViewController") as? NewContactViewController else { return } newContactViewController.delegate = self self.present(newContactViewController, animated: true) @@ -56,6 +62,13 @@ extension ViewController { extension ViewController: SendDelegate { func sendContact(newContact: Contact) { self.addressBook.addContact(newContact) - self.tableView.reloadData() + tableView.reloadData() + } +} + +extension ViewController: UISearchBarDelegate { + func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { + addressBook.searchContact(searchText) + tableView.reloadData() } }