Skip to content

Commit

Permalink
feat: 다이나믹 타입 적용, 폰트 스타일 적용, 검색바 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
maxhyunm committed Sep 16, 2023
1 parent f57a6d9 commit 6c3541f
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 24 deletions.
34 changes: 28 additions & 6 deletions Diary/Controller/DiaryDetailViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,30 @@ final class DiaryDetailViewController: UIViewController, AlertDisplayable, Share
}

textView.text = "\(title)\n\(body)"
setupFontStyle(title: title, body: body)
}

private func splitTitleAndBody() -> (title: String, body: String) {
let contents = textView.text.components(separatedBy: "\n")
guard !contents.isEmpty,
let title = contents.first else {
return (title: "", body: "")
}

let body = contents.dropFirst().joined(separator: "\n")

return (title: title, body: body)
}

private func setupFontStyle(title: String, body: String) {
let attributeString = NSMutableAttributedString(string: textView.text)
attributeString.addAttribute(.font,
value: UIFont.preferredFont(forTextStyle: .title1),
range: (textView.text as NSString).range(of: title))
attributeString.addAttribute(.font,
value: UIFont.preferredFont(forTextStyle: .body),
range: (textView.text as NSString).range(of: body))
textView.attributedText = attributeString
}

private func setupNavigationBarButton() {
Expand Down Expand Up @@ -190,14 +214,12 @@ extension DiaryDetailViewController: UITextViewDelegate {
}

func textViewDidChange(_ textView: UITextView) {
let contents = textView.text.components(separatedBy: "\n")
guard !contents.isEmpty,
let title = contents.first else { return }
let splitText = splitTitleAndBody()

let body = contents.dropFirst().joined(separator: "\n")
diary.title = splitText.title
diary.body = splitText.body

diary.title = "\(title)"
diary.body = body
setupFontStyle(title: splitText.title, body: splitText.body)
}
}

Expand Down
42 changes: 42 additions & 0 deletions Diary/Controller/DiaryListViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ final class DiaryListViewController: UIViewController {
private let tableView: UITableView = {
let tableView = UITableView()
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.separatorStyle = .singleLine

return tableView
}()
Expand Down Expand Up @@ -113,6 +114,13 @@ extension DiaryListViewController: UITableViewDataSource {

return cell
}

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let searchBar = UISearchBar()
searchBar.delegate = self

return searchBar
}
}

extension DiaryListViewController: UITableViewDelegate, ShareDisplayable {
Expand Down Expand Up @@ -181,5 +189,39 @@ extension DiaryListViewController: CLLocationManagerDelegate {

latitude = location.latitude
longitude = location.longitude

locationManager.stopUpdatingLocation()
}
}

extension DiaryListViewController: UISearchBarDelegate {
func searchDiary(with keyword: String) {
if keyword.count > 0 {
do {
let fetchedDiaries = try CoreDataManager.shared.filterDiary(keyword)
diaryList = fetchedDiaries.filter { $0.title != nil }
tableView.reloadData()
} catch CoreDataError.dataNotFound {
let cancelAction = UIAlertAction(title: ButtonNamespace.confirm, style: .cancel)
showAlert(title: CoreDataError.dataNotFound.alertTitle,
message: CoreDataError.dataNotFound.message,
actions: [cancelAction],
preferredStyle: .alert)
} catch {
let cancelAction = UIAlertAction(title: ButtonNamespace.confirm, style: .cancel)
showAlert(title: CoreDataError.dataNotFound.alertTitle,
message: CoreDataError.unknown.message,
actions: [cancelAction],
preferredStyle: .alert)
}
}

if keyword.count == 0 {
readCoreData()
}
}

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
searchDiary(with: searchText)
}
}
36 changes: 26 additions & 10 deletions Diary/Model/CoreData/CoreDataManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@ import CoreData

class CoreDataManager {
static let shared = CoreDataManager()

lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "Diary")
container.loadPersistentStores(completionHandler: { (_, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()

private init() {}

func fetchDiary() throws -> [Diary] {
Expand All @@ -24,6 +35,21 @@ class CoreDataManager {
}
}

func filterDiary(_ keyword: String) throws -> [Diary] {
let request: NSFetchRequest<Diary> = Diary.fetchRequest()
let predicate = NSPredicate(format: "title CONTAINS[cd] %@ OR body CONTAINS[cd] %@", keyword, keyword)
request.predicate = predicate
let sortByDate = NSSortDescriptor(key: "createdAt", ascending: false)
request.sortDescriptors = [sortByDate]

do {
let diaries = try persistentContainer.viewContext.fetch(request)
return diaries
} catch {
throw CoreDataError.dataNotFound
}
}

func createDiary() -> Diary {
let newDiary = Diary(context: persistentContainer.viewContext)
newDiary.id = UUID()
Expand All @@ -39,16 +65,6 @@ class CoreDataManager {
persistentContainer.viewContext.delete(diary)
try saveContext()
}

lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "Diary")
container.loadPersistentStores(completionHandler: { (_, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()

func saveContext () throws {
let context = persistentContainer.viewContext
Expand Down
25 changes: 17 additions & 8 deletions Diary/View/DiaryListTableViewCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,35 @@ final class DiaryListTableViewCell: UITableViewCell {
private let titleLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.adjustsFontForContentSizeCategory = true
label.font = .preferredFont(forTextStyle: .body)
label.setContentCompressionResistancePriority(.required, for: .vertical)
label.setContentHuggingPriority(.required, for: .vertical)

return label
}()

private let dateLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.adjustsFontForContentSizeCategory = true
label.font = .preferredFont(forTextStyle: .callout)
label.setContentCompressionResistancePriority(.required, for: .horizontal)
label.setContentHuggingPriority(.required, for: .horizontal)
label.setContentCompressionResistancePriority(.required, for: .vertical)
label.setContentHuggingPriority(.required, for: .vertical)

return label
}()

private let bodyLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.adjustsFontForContentSizeCategory = true
label.font = .preferredFont(forTextStyle: .caption2)
label.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
label.setContentCompressionResistancePriority(.required, for: .vertical)
label.setContentHuggingPriority(.required, for: .vertical)

return label
}()
Expand All @@ -41,6 +50,8 @@ final class DiaryListTableViewCell: UITableViewCell {
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
imageView.setContentHuggingPriority(.required, for: .horizontal)
imageView.setContentCompressionResistancePriority(.required, for: .vertical)
imageView.setContentHuggingPriority(.required, for: .vertical)

return imageView
}()
Expand Down Expand Up @@ -70,23 +81,21 @@ final class DiaryListTableViewCell: UITableViewCell {
accessoryType = .disclosureIndicator

NSLayoutConstraint.activate([
titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 5),
titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8),
titleLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20),
titleLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -40),
titleLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -30),

dateLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 8),
dateLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20),
dateLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -5),
dateLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -8),

weatherIconImageView.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 8),
weatherIconImageView.leadingAnchor.constraint(equalTo: dateLabel.trailingAnchor, constant: 15),
weatherIconImageView.centerYAnchor.constraint(equalTo: dateLabel.centerYAnchor),
weatherIconImageView.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: 0.05),
weatherIconImageView.heightAnchor.constraint(equalTo: weatherIconImageView.widthAnchor),
weatherIconImageView.heightAnchor.constraint(equalTo: contentView.heightAnchor, multiplier: 0.3),
weatherIconImageView.widthAnchor.constraint(equalTo: weatherIconImageView.heightAnchor),

bodyLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 8),
bodyLabel.leadingAnchor.constraint(equalTo: weatherIconImageView.trailingAnchor, constant: 15),
bodyLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -40),
bodyLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -30),
bodyLabel.centerYAnchor.constraint(equalTo: dateLabel.centerYAnchor)
])
}
Expand Down

0 comments on commit 6c3541f

Please sign in to comment.