Notice
Recent Posts
Recent Comments
Link
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

iOS 개발일지

0904 9주차 마무리 - 2차 평가과제 본문

SeSAC iOS 데뷔과정 2기

0904 9주차 마무리 - 2차 평가과제

Lia's iOS 2022. 9. 5. 01:14
iOS 앱 개발자 데뷔 과정 9주차 마무리 - 2차 평가과제

 

 

 

 

- Memo App

코드에 대한 자세한 설명보다는 진행하며 새로 사용해 본 메서드, 프로퍼티, 핵심 기능 위주로 작성

 

- 등록일이 일주일 이내일 때 요일로 표기

    private func regdateFormat(regdate: Date) -> String {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy.MM.dd" // 초 단위로 비교하지 않도록 포맷
        
        let startDate = formatter.date(from: formatter.string(from: regdate)) ?? Date()
        let endDate = formatter.date(from: formatter.string(from: Date())) ?? Date()
        guard let interval = Calendar.current.dateComponents([.day], from: startDate, to: endDate).day else { return "" }

        switch interval {
        case 0:formatter.dateFormat = "a hh:mm"
        case 1...6: formatter.dateFormat = "E요일"
        default: formatter.dateFormat = "yyyy.MM.dd a hh:mm"
        }
        
        return formatter.string(from: regdate)
    }

 

 

 

 

-  UISearchController

검색중일 때만 실행하고 싶은 코드는 모두 isSearch 의 Bool 값을 통해 조건문으로 작성하면 된다.

    private var isSearch: Bool { // MARK: 서치뷰로 옮기기?
        let searchController = navigationItem.searchController
        let isActive = searchController?.isActive ?? false
        let isSearchBarHasText = searchController?.searchBar.text?.isEmpty == false
        return isActive && isSearchBarHasText
    }
    
        private func configureSearchBar() {
        let searchController = UISearchController(searchResultsController: nil)
        searchController.searchBar.placeholder = "검색"
        searchController.hidesNavigationBarDuringPresentation = false // 검색하는 동안 네비게이션에 가려지지 않게
        searchController.searchBar.setValue("취소", forKey: "cancelButtonText") // cancel을 취소로 변경
        searchController.searchResultsUpdater = self // 프로토콜 채택
        
        navigationItem.hidesSearchBarWhenScrolling = false // 스크롤 할때 사라지지 않게 (+ 뷰 떴을 떄 바로바로 보이게)
        navigationItem.searchController = searchController
    }
    
    
    
    == RealmRepositoty==
    
        func fetchFilter(text: String) -> [UserMemo] {
        var results: [UserMemo] = []
        results.append(contentsOf: localRealm.objects(UserMemo.self).filter("memoTitle CONTAINS[c] '\(text)'"))
        results.append(contentsOf: localRealm.objects(UserMemo.self).filter("memoContent CONTAINS[c] '\(text)'"))

        return results.uniqueArrItems() // 중복 제거
    }

 

 

 

- 배열 내의 중복된 요소 제거

extension Array where Element: Hashable {
    func uniqueArrItems() -> [Element] {
        var dictAdded = [Element: Bool]()
        
        return filter {
            dictAdded.updateValue(true, forKey: $0) == nil
        }
    }

    mutating func removeDuplicates() {
        self = self.uniqueArrItems()
    }
}

 

 

 

-  다크모드 대응

final class ColorSet {
    static let shared = ColorSet()
    private init() {}
    
    let popupBackgroundColor: UIColor = UIColor(named: "popupBackgroundColor") ?? .blue
    let buttonColor: UIColor = .systemOrange
    lazy var backgroundColor: UIColor = darkMode(lightColor: .systemGray5, darkColor: .black)
    lazy var viewObjectColor: UIColor = darkMode(lightColor: .white, darkColor: .darkGray)
    lazy var whiteAndBlack: UIColor = darkMode(lightColor: .white, darkColor: .black)
    lazy var blackAndWhite: UIColor = darkMode(lightColor: .black, darkColor: .white)
    
    private func darkMode(lightColor: UIColor, darkColor: UIColor) -> UIColor {
        if #available(iOS 13, *) {
            return UIColor { (traitCollection: UITraitCollection) -> UIColor in
                if traitCollection.userInterfaceStyle == .light {
                    return lightColor
                } else {
                    return darkColor
                }
            }
        } else {
            return lightColor
        }
    }
}

 

 

 

-  NavigationController 를 통한 툴바 구성

    private func configureToolbar() {
        navigationController?.isToolbarHidden = false // 툴바 꺼내주기
        let writeButton = UIBarButtonItem(image: UIImage(systemName: "square.and.pencil"), style: .plain, target: self, action: #selector(writeButtonTapped))
        let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil) // Space 구성
        toolbarItems = [flexibleSpace, writeButton] // 배열에 Space를 먼저 넣어주면 버튼이 오른쪽으로 붙게 된다
    }

 

 

 

- TextView : 사용자의 Return Key Event 인식 (제목 구분)

아직 완성 못했음 버그주의...^^

줄바꿈 버그는 content가 원인인 것 같고, 마지막 글자가 저장되지 않는 현상은 메서드의 특성인지...?ㅜㅜ

// MARK: 버그 - 마지막 글자 하나가 저장이 안되는 현상 + 줄바꿈이 불필요하게 하나씩 더 들어가는 현상
extension WriteViewController: UITextViewDelegate {
    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        let cuttingLine = mainView.userTextView.text.components(separatedBy: "\n") // 줄바꿈 기준으로 문자열 자르기
        memoTitle = cuttingLine[0] + "\n" // 0번째 인덱스를 제목으로 저장
        print("Title: " + memoTitle!)
        
        let content = cuttingLine[1...].reduce("") { str, i in str + i + "\n"} // 배열 형태인 String 합치기
        memoContent = content
        print("Content: " + content)
        
        return true
    }
}

 

 

 

-  줄바꿈 (공백) 무시하고, 글자가 있는 첫 줄의 문자열만 가져오기

components로 문자열을 잘라서 판단하기 때문에, 동작하는 원리는 위와 비슷하다.

            let cuttingLine = tasks[indexPath.row].memoContent?.components(separatedBy: "\n") // 내용에 줄바꿈
            이 있어도
            let str = cuttingLine?.filter { $0.count > 0 } // 글자만 가져오고
            cell.contentLabel.text = str?.first ?? "추가 텍스트 없음" // 확실하게 아무 내용도 없을 때만 기본텍스트 표시

 

 

 

-  Tableview HeaderView

이것도... 아직 완성 못했음 버그주의...^^

      // MARK: 버그 - 메모가 없어도 헤더가 보이는 현상
    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
            let headerView = UIView() // 헤더 갯수만큼 필요하기 때문에 MemoListView 에서 선언 불가
            let headerLabel = UILabel()

            headerLabel.frame = CGRect(x: 10, y: 10, width: 500, height: 30)
            headerLabel.font = UIFont.boldSystemFont(ofSize: 22)

            if isSearch {
                headerLabel.text = "\(searchResults.count)개 찾음"
                headerView.addSubview(headerLabel)
                return headerView
            } else {
                if section == 0 {
                    if fixMemoTasks != nil {
                        headerLabel.text = "고정된 메모"
                    } else {
                        headerLabel.text = "메모"
                    }
                } else {
                    headerLabel.text = "메모"
                }
                headerView.addSubview(headerLabel)
                return headerView
            }
        }

 

 

 

-  UILable Text 특정 키워드 (ex. 검색 키워드) 만 속성 변경하기

        func searchTextColor(str: String?) {
            guard let searchText = searchText else { return }
            guard let str = str else { return }
            
            let attributeStr = NSMutableAttributedString(string: str)
            attributeStr.addAttribute(.foregroundColor, value: ColorSet.shared.buttonColor, range: (str.lowercased() as NSString).range(of: searchText.lowercased()))
            
            if searchResults[indexPath.row].memoTitle.contains(str) {
                cell.titleLabel.attributedText = attributeStr
            }
            
            guard let content = searchResults[indexPath.row].memoContent else { return }
            if content.contains(str) {
                cell.contentLabel.attributedText = attributeStr
            }
        }