-
[iOS] FMDB를 사용한 최근 장소 검색 기능 구현iOS/EARLY BUDDY | iOS 2020. 8. 15. 23:39
안녕하세요 :)
저번 포스팅에서는 FMDB를 사용한 간단한 것들을 알아봤는데요.
얼리버디에 그대로 도입하기에는 몇 가지 이슈들이 있었습니다.
- 검색어를 저장할 때 중복 체크 기능이 없음
- 검색했던 이력이 있는 주소들은 테이블 뷰 제일 상단으로 올라오지 않음
- 최근 검색한 순서대로 테이블 뷰에 뜨지 않고 데이터베이스 테이블에 저장된 순서대로 뜸
위의 세 가지들이 고쳐야 할 이슈들이었습니다.
이제부터 이슈들을 차곡차곡 고쳐나가 보겠습니다!
검색어 저장 시 중복 체크 기능
제가 구현해야 하는 기능은 중복된 검색어가 들어왔을 경우에 제일 상단으로 텍스트가 올라가야 하는 것입니다.
그래서 저는 테이블에 Location과 Time을 insert 해주고, 만약 중복된 텍스트가 들어올 경우에는 Time 부분만 update 해주도록 했습니다.
// MARK:- RecentLocation 테이블 생성 func createRecentLocation() { if !fileManager.fileExists(atPath: databasePath) { if recentLocationDB.open() { let createSql = "CREATE TABLE IF NOT EXISTS RecentLocation (ID INTEGER PRIMARY KEY AUTOINCREMENT, LOCATION TEXT, TIME DATETIME)" print(createSql) if !recentLocationDB.executeStatements(createSql) { print("Error: recentLocationDB execute Fail, \(recentLocationDB.lastError())") } recentLocationDB.close() } else { print("Error: recentLocationDB open Fail, \(recentLocationDB.lastError())") } } else { print("recentLocationDB is exist") } }
위의 코드는 전의 게시물과 바뀐 저의 테이블입니다.
createSql 부분을 보시면 테이블 생성할 때 ID, LOCATION, TIME을 저장합니다.
최근 검색 순서대로 테이블을 정렬할 때와 중복 시에 TIME을 업데이트하려고 추가했습니다!
// MARK:- 검색어 중복 체크 func checkDuplicate(text: String) -> Bool { if recentLocationDB.open() { let selectSql = "SELECT Location FROM RecentLocation WHERE Location = '\(text)'" do { let result = try recentLocationDB.executeQuery(selectSql, values: []) if result.next() { return true } } catch { print("Error") } } else { print("Error: recentLocationDB open Fail, \(recentLocationDB.lastError())") } return false }
위의 코드가 바로 검색어 중복 체크 함수입니다.
저는 검색창을 텍스트 필드로 구현했기 때문에 텍스트 필드에서 리턴키를 눌렀을 때 text를 해당 함수에 인자로 넣어줍니다.
그리고 전달받은 text와 같은 것이 테이블에 있을 경우 true를 리턴하는 함수입니다.
이렇게 중복 체크를 한 후에 최근 검색어 추가를 하도록 만들었습니다.
데이터가 중복될 경우 UPDATE, 없을 경우 INSERT
// MARK:- 최근 검색어 저장 func insertRecentLocataion(searchText: String) { if recentLocationDB.open() { if checkDuplicate(text: searchText) { let updateSql = "UPDATE RecentLocation SET TIME = DATETIME('NOW') WHERE Location = '\(searchText)'" print(updateSql) let result = recentLocationDB.executeUpdate(updateSql, withArgumentsIn: []) if !result { print("Error: recentLocationDB update Fail, \(recentLocationDB.lastError())") } } else { let insertSql = "INSERT INTO RecentLocation (LOCATION, TIME) values ('\(searchText)', DATETIME('NOW'))" let result = recentLocationDB.executeUpdate(insertSql, withArgumentsIn: []) if !result { print("Error: recentLocationDB add Fail, \(recentLocationDB.lastError())") } } } else { print("Error: recentLocationDB open Fail, \(recentLocationDB.lastError())") } }
네 위의 코드가 insert문이 있는 코드입니다!
우선, 전의 checkDuplicate(text:) 함수를 사용해서 분기 처리를 해줍니다.
만약 중복된 텍스트라면 UPDATE문을 사용해서 TIME을 DATETIME('NOW')로 설정합니다.
여기서 주의할 점은 WHERE문에 Location = '\(searchText)'처럼 조건을 걸어주어야 테이블 전체의 TIME이 바뀌지 않고 원하는 칼럼의 TIME만 업데이트됩니다.
중복되지 않은 텍스트는 INSERT 문으로 테이블에 넣어줍니다.
최근 검색한 순서대로 정렬하여 띄우기
// MARK:- 최근 검색어 검색 func searchRecentLocation(row: Int) -> String { var recentLocation = "" if recentLocationDB.open() { let selectSql = "SELECT LOCATION FROM RecentLocation ORDER BY TIME DESC LIMIT 1 OFFSET \(row)" do { let result = try recentLocationDB.executeQuery(selectSql, values: []) if result.next() { guard let resultString = result.string(forColumn: "LOCATION") else { return "" } recentLocation = resultString } } catch { print("Error") } } else { print("Error: recentLocationDB open Fail, \(recentLocationDB.lastError())") } print("RecentLocationText: \(recentLocation)") return recentLocation }
이제 최근 검색어 검색 부분입니다.
저는 테이블 뷰에 셀로 텍스트들을 띄울 것이기 때문에 row를 입력받고 String을 리턴하는 함수를 사용했습니다.
그리고 쿼리문을 보시면 LIMIT와 OFFSET이라는 것이 보입니다.
저것은 1개까지 보여주고 row의 OFFSET을 주어라 라는 것입니다.
SQLite에는 오라클 SQL처럼 ROWNUM이라는 것이 없습니다.
그래서 처음에는 ORDER BY TIME DESC를 한 후에 ROWID로 row와 같은 것을 가져오려고 했습니다.
하지만 ROWID는 말 그대로 ID, PRIMARY KEY이기 때문에 값이 고유해서 꼬였습니다.
그래서 OFFSET을 사용했는데요.
우선 ORDER BY로 최근 검색한 순서대로 SELECT이 될 텐데 OFFSET을 row로 할당했기 때문에 테이블 뷰에서 indexPath.row 값을 넣어주면 칼럼 OFFSET으로 해당 칼럼을 하나씩 가져오도록 구현됩니다.
마무리
그러면 위의 과정들이 모두 적용된 GIF를 보여드리면서 글 마무리하겠습니다 :)
감사합니다! :)
'iOS > EARLY BUDDY | iOS' 카테고리의 다른 글
[iOS] 테이블 뷰 셀 안에 컬렉션 뷰 넣기 (0) 2020.08.28 [iOS] FMDB 사용하기 (0) 2020.08.14 [iOS] Coordinator Pattern 적용 (0) 2020.07.31