IOS에서 DB를 사용하는 방법은 Sqlite 와 Realm이 있다.

Realm은 속도가 빠르고, 높은 용량을 요구하여 대용량 데이터를 다룰 때 사용하는 방법이다.

Sqlite는 그 반대로 내장된 라이브러리라서 가볍게 사용하기 좋다. 

 

Swift로 간단히 데이터를 저장하기 위해 Sqlite의 사용법을 알아보도록 한다.

 

1. Swift에 sqlite import를 해준다. 

import SQLite3

 

2. 변수 및 테이블 명 (전역 변수로 선언해 준다.)

    var db:OpaquePointer?
    let TABLE_NAME : String = "DaDaTable"

 

2. Table 생성

func createTable(){
        let fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent("DSDatabase.sqlite")
        
        
        if sqlite3_open(fileURL.path, &db) != SQLITE_OK {
            print("table not exsist")
        }
        
        let CREATE_QUERY_TEXT : String = "CREATE TABLE IF NOT EXISTS \(TABLE_NAME) (id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT, subline, date TEXT)"

        print(CREATE_QUERY_TEXT)
        if sqlite3_exec(db, CREATE_QUERY_TEXT, nil, nil, nil) != SQLITE_OK {
            let errMsg = String(cString:sqlite3_errmsg(db))
            print("db table create error : \(errMsg)")
        }
    }

 

3. 데이터 삽입

func insert(_ title : String,_ subline : String, _ date : String ){
        var stmt : OpaquePointer?
        
        let INSERT_QUERY_TEXT : String = "INSERT INTO \(TABLE_NAME) (title, subline, date) Values (?,?,?)"

        if sqlite3_prepare(db, INSERT_QUERY_TEXT, -1, &stmt, nil) != SQLITE_OK {
            let errMsg = String(cString: sqlite3_errmsg(db)!)
            print("error preparing insert:v1 \(errMsg)")
            return
        }
        
        let SQLITE_TRANSIENT = unsafeBitCast(-1, to: sqlite3_destructor_type.self)
        
        if sqlite3_bind_text(stmt, 1, title, -1, SQLITE_TRANSIENT) != SQLITE_OK{
            let errMsg = String(cString : sqlite3_errmsg(db)!)
            print("failture binding name: \(errMsg)")
            return
        }

        if sqlite3_bind_text(stmt, 2, subline, -1, SQLITE_TRANSIENT) != SQLITE_OK{
            let errMsg = String(cString : sqlite3_errmsg(db)!)
            print("failture binding name: \(errMsg)")
            return
        }

        
        if sqlite3_bind_text(stmt, 3, date, -1, SQLITE_TRANSIENT) != SQLITE_OK{
            let errMsg = String(cString : sqlite3_errmsg(db)!)
            print("failture binding name: \(errMsg)")
            return
        }
        
        if sqlite3_step(stmt) != SQLITE_DONE {
            let errMsg = String(cString : sqlite3_errmsg(db)!)
            print("insert fail :: \(errMsg)")
            return
        }
    }

 

4. 데이터 검색

func selectValue(){
        
        let SELECT_QUERY = "SELECT * FROM \(TABLE_NAME)"
        var stmt:OpaquePointer?
        
        
        if sqlite3_prepare(db, SELECT_QUERY, -1, &stmt, nil) != SQLITE_OK{
            let errMsg = String(cString: sqlite3_errmsg(db)!)
            print("error preparing insert: v1\(errMsg)")
            return
        }
        
        while(sqlite3_step(stmt) == SQLITE_ROW){
            let id = sqlite3_column_int(stmt, 0)
            let title = String(cString: sqlite3_column_text(stmt, 1))
            let subline = String(cString: sqlite3_column_text(stmt, 2))
            let date = String(cString: sqlite3_column_text(stmt, 3))
        
            print("read value id : \(id) title : \(title) subline : \(subline) date : \(date)")
        }
  
    }

 

5. 업데이트

    func update(_ index:String, _ title : String,_ subline : String, _ date : String){
        let UPDATE_QUERY = "UPDATE \(TABLE_NAME) Set title = '\(title)', subline = '\(subline)', date= '\(date)' WHERE id == \(index)"
        var stmt:OpaquePointer?
        print(UPDATE_QUERY)
        if sqlite3_prepare(db, UPDATE_QUERY, -1, &stmt, nil) != SQLITE_OK{
            let errMsg = String(cString: sqlite3_errmsg(db)!)
            print("error preparing update: v1\(errMsg)")
            return
        }
        
        if sqlite3_step(stmt) != SQLITE_DONE {
            let errMsg = String(cString : sqlite3_errmsg(db)!)
            print("update fail :: \(errMsg)")
            return
        }
        
        sqlite3_finalize(stmt)
        print("update success")
               
    }

 

6. 데이터 삭제

func delete(_ index:String){
//        readValues()
        let DELETE_QUERY = "DELETE FROM \(TABLE_NAME) WHERE id = \(index)"
        var stmt:OpaquePointer?
        
        print(DELETE_QUERY)
        if sqlite3_prepare_v2(db, DELETE_QUERY, -1, &stmt, nil) != SQLITE_OK{
            let errMsg = String(cString: sqlite3_errmsg(db)!)
            print("error preparing delete: v1\(errMsg)")
            return
        }
        
        if sqlite3_step(stmt) != SQLITE_DONE {
            let errMsg = String(cString : sqlite3_errmsg(db)!)
            print("delete fail :: \(errMsg)")
            return
        }
        sqlite3_finalize(stmt)
                
    }

간단히 데이터를 저장하기 위해선 sqlite가 적합하다. 

대용량 데이터를 처리하기 위해선 Realm을 사용하는데 이 후 정리하는 시간을 갖도록 하겠다.

fireBase import 시 에러가 발생하는 경우가 있다.

PodFIle을 연동하고 프로젝트 실행 시 import구문에서 에러가 발생하는 경우가 있다.

이떄 해결방안으로는

1. Pods 폴더를 삭제한다.
2. .xcworkspace 파일을 삭제한다.

다시 podFile을 install해본다.

$ pod install


이후 .xcworkspace로 프로젝트를 실행한다.

(.xcodeproj로 실행 시 똑같이 import 오류가 발생한다.)

XCode에서 FireBase를 연동해보자.

 

설명에 앞서 Firebase란...? 
이전에 개인이 모바일 앱을 개발하는 경우 서버와 관련된 부분을 전부개발하여야 했으나, Google에서 Firebase라는 일종의 서버를 제공함으로 개발자에게 편의를 제공한다.
제공하는 기능으로는 데이터를 저장, 실시간 데이터 동기화, 사용자 인증, 데이터 분석, A/B Testing등을 제공하여 앱의 퀄리티와 안전성 편의성을 제공해 준다.

 

연동 하는 기본 조건은 아래와 같다.

 

  • Xcode 12.2 이상
  • CocoaPods 1.10.0 이상
  • 프로젝트에서 iOS 10 이상을 타겟팅해야 한다.

 

1. CocoaPods를 설치 하자

(CocoaPodsfks? XCode에서 외부 라이브러리를  관리 해 주는 모듈)

 

※ CocoaPods 참고 : cocoapods.org/

 

1) 터미널에서 CocoPads를 설치한다.

$ sudo gem install cocoapods

에러 없이 정상적으로 설치된 후 아래 내용을 진행한다.

 

2) CocoaPads가 잘 설치 되었는지 확인한다.

$ pod --version

정상적으로 설치되어 있는 경우 CocoaPads의 버전을 보여준다.

 

2. 설치한 CocoaPads로 FireBase를 설치한다.

 

1) FireBase 홈페이지 접속

console.firebase.google.com/

 

우측 상단의 콘솔로 이동을 선택 한다.

 

2) Project를 등록한다.

 

 

 

 

3) IOS 시작하기 선택 후 생성한 프로젝트의 번들아이디를 등록해준다.

 

 

XCode의 번들 아이디

 

 

4) GoogleService-info.plist를 다운로드 받는다.

다운된 plist파일을 이미지 처럼프로젝트 내로 드레그&드롭한다.

 

 

5) 프로젝트 경로의 터미널에서 PodFile을 생성한다.

 

$ pod init

 

5) Pod파일이 생성되 었다면, PodFile 내에 Firebase/Analytic 을 추가 해준다.

 

pod `Firebase/Analytics`

 

6) PodFile에 내용추가 후 pod install 을 실행한다.

 

$ pod install

7) Pods 폴더가 생성되고, Firebase 홈페이지에 나온 가이드처럼 소스를 추가해준다.

 

프로젝트의 AppDelegate 파일에 FIrebase import 추가

import Firebase

func application에 Firebase.configure()를 추가

FirebaseApp.configure()

 

9) 소스에 위 내용을 추가 후 Firebase 홈페이지에서 next 선택을 하면, Application을 실행 시켜 달라는 문구가 나오는데 Xcode에서 앱을 실행 시켜서 정상적으로 연동이 되는지 확인을 한다.

 

 

※ CocoaPad를 다운로드 받고 AppDelegate 파일에 import Firebase를 했을 때 오류가 발생하는 부분이 있다. 

오류 발생 시 참고

magicofdream.tistory.com/19

프로젝트 생성 후 네트워크 통신 시 동작되지 않는 문제가 발생한다.

안드로이드의 Manifest에 Internet 권한을 주는것 처럼 ios에서도 권한을 추가 해야한다.

plist에 App Transport Security Settings >> Allow Arbitrary Loads : YES 로 추가 해주면 되지만, 

XCode 버전에 따라 옵션이 없는 경우가 있어 이경우에는 수동으로 권한을 추가해 주어야 한다.

plist 메뉴에서 Open As > Source Code 를 선택 하면 xml형식의 소스 코드를 볼수 있다.

 

 

 


다음 옵션을 수동으로 추가하면, 정상적으로 사용할수 있다.

   <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key><true/>
    </dict>

 

그 외에도 ios 기능 이용 시 plist에 권한을 추가해 주어야 하는 것들이 있는데, 스터디 하면서 하나씩 정리하는 시간을 가져야겠다.

'swift' 카테고리의 다른 글

[Swift] Sqlite 사용법  (2) 2021.05.28
[swift] Cocoapads import 에러  (0) 2021.05.10
[Swift] FireBase 연동  (0) 2021.05.10
[Swift] Objective-C 연동하기(bridging header)  (0) 2021.05.04
[Swift] Struct와 Class 정리  (0) 2021.04.26

Swift 프로젝트에서 Objective-C의 함수를 사용하는 방법에 대해 정리한다.

 

1. 가장 먼저 Swift 프로젝트 생성 한다.

 

2. 생성한 Swift 프로젝트에서 New File...선택 후 Objective-c 파일 추가 선택

 

3. 초기 Objective-C 파일 생성 시 bridging header를 생성 하겠느냐는 팝업이 뜨는데 이때 Create Bridging Header 를 선택해준다.

 

 

(아래 구조로 .h, .m bridging header가 생성된다)

4. Objective-C Class에 원하는 함수에 대해 기능을 작성한다.

 

Swift Class 에서 Objective-c에 구현된 함수를 호출할 수 있다.

 

5. Bridge header 에 생성한 Objective-c Classheader bridging header에 import한후 Swift에서 사용할수 있다.

 

 

 

'swift' 카테고리의 다른 글

[Swift] Sqlite 사용법  (2) 2021.05.28
[swift] Cocoapads import 에러  (0) 2021.05.10
[Swift] FireBase 연동  (0) 2021.05.10
[swift] 통신 시 인터넷 권한 추가 (info.plist 설정하기)  (0) 2021.05.07
[Swift] Struct와 Class 정리  (0) 2021.04.26

Swift에서는 코드를 구현할때 Struct와 Class로 필요한 형식과 용도에 맞게 묶어서 코딩을 한다.

Struct와 Class의 공통점

1. 데이터(Property)와 기능(Method)에 대해 정의 할 수 있다.

- 값을 저장하기 위해 Property를 정의
- 기능을 제공하기 위해 Method를 정의

 

2. 확장(Extension)이 가능하다
초기 구현된 내용에 새로운 기능 추가를 하여 하용할수 있다. (키워드 extention)

 

3. 서브스크립트(subscript) 사용할 수 있다.

- “.”을 이용해 하위의 프로퍼티에 접근 가능하다

 

4. 프로토콜 사용이 가능하다.

- Java의 Interface와 비슷한 개념

(추후 이 부분에 대해서도 정리가 필요)

 

5. 초기화를 정의하여 초기상태 설정이 가능하다.

- init를 이용하여 Property의 초기값을 설정 할수 있다.

Struct와 Class의 차이점

1. Struct는 value type이고, class는 reference type 이다.

- value type은 별도의 메모리에 값이 복사되어 사용된다.

- reference type 값이 복사 되는 것이 아니라 참조하고 있는 메모리의 주소를 사용한다.

 

2. Struct는 Stack에 할당하고, class는 heap에 할당 된다.

- Struct는 Stack에 할당하여 속도가 빠르다.

- Class는 Heap에 할당하여 속도가 느리다.

 

3. Struct는 상속을 할 수 없고, Class는 상속을 할수 있다.(Class에서도 단일 상속만 가능)

Structure를 써야 하는 경우.

1. 두 object의 같다, 다르다를 비교해야 하는 경우
2. Copy된 각 객체들이 독립적인 상태를 가져야 하는 경우
3. 코드에서 오브젝트의 데이터를 여러 스레드 걸쳐 사용할 경우

Class를 써야 하는 경우

1. 두 Object의 인스턴스 자체가 같음을 확인해야 할때
2. 하나의 객체가 필요하고, 여러 대상에 의해 접근되고 변경이 필요한 경우

 

struct와 class에 대한 swift 참고 url.

 

developer.apple.com/swift/blog/?id=10

docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html

개발 시 공식 문서의 내용을 먼저 참고하는 습관을 갖자.

+ Recent posts