Applecider
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # 동기화 메모장 [STEP3/4] Jiseong, Toni, 애플사이다 ## STEP3 구현내용 및 고민한 점 ### 구현 내용 - 클라우드 (Dropbox) 연동을 위해 Cocoa Pod 및 SwiftyDropbox 라이브러리를 활용했습니다. - 코어데이터를 다른 기기와 동기화 할 수 있도록 DropBoxManager 타입 및 uploadToDropBox/downloadFromDropBox 메서드를 구현했습니다. - 클라우드 다운로드 시점 : 앱 실행 시 초기화면에서 DropBox Safari ViewController를 present하고, DropBox 로그인이 성공했을 때 다운로드 하도록 구현하였습니다. (추후 로그인 실패 후 다시 로그인 시도를 할 수 있도록 버튼을 추가할 예정입니다.) - 클라우드의 데이터를 다운로드하여 저장하는 위치는 PersistentContainer의 `defaultDirectoryURL`으로 설정했고, overwrite 모드로 구현하였습니다. - 클라우드 업로드 시점 : 메모 추가/삭제할 때, 메모 업데이트할 때 (`textViewDidEndEditing` 메서드) 업로드를 하도록 구현하였습니다. - 메모를 추가/삭제/수정할 때 (사용자가 메모를 작성한 뒤) 클라우드에 저장되어있는 데이터와 사용자의 CoreData에 저장되어 있는 데이터는 일치하므로 클라우드의 데이터를 다운받을 때 Overwrite를 하여도 문제가 없도록 구현하였습니다. ## STEP4 구현내용 및 고민한 점 ### SearchBar 추가 - 메모 목록 상단에 SearchBar를 구현했습니다. 사용자의 입력값을 제목 또는 본문에 포함하고 있는 메모를 검색결과로 보여주도록 했습니다. - 이를 위해 `Custom TableViewController`인 `searchResultViewController` 타입을 추가했습니다. 그리고 MaterTableViewController에서 초기화했고, 생성자 주입을 통해 MaterTableViewController의 DataSource의 memos를 전달하도록 했습니다. 그리고 서치바에 텍스트를 입력할 때마다 호출되는 updateSearchResults 메서드 내부에서 searchResultViewController의 searchMemo 메서드를 호출하여 메모를 필터링했습니다. ```swift final class MasterTableViewController: UITableViewController { private(set) var memoDataSource: MasterTableViewDataSourceProtocol? weak var delegate: MemoSelectionDelegate? lazy var searchResultViewController = SearchResultTableViewController(memos: memoDataSource?.retrieveMemos(), delegate: delegate) // ... } ``` - 처음에는 searchResultViewController와 masterTableViewController가 모두 동일한 memos 배열 데이터를 사용하므로 기존의 DataSource를 두 ViewController 모두 사용하도록 시도했습니다. 그런데 이 과정에서 타입캐스팅을 위해 DataSource가 ViewController를 알고 있어야하는 문제가 있었고, 의존성이 다시 높아진다고 판단하여 이 방법을 사용하지 않았습니다. ### Dark Mode 미지원 레이블 추가적으로 지원 테이블 뷰의 텍스트들은 DarkMode를 지원했지만, DetailView의 텍스트뷰의 텍스트는 지원이 안되고 있어 이를 수정해주었습니다. ```swift // 수정 전 let titleAttributes = [NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .title1)] let bodyAttributes = [NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .body)] // 수정 후 let titleAttributes = [NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .title1), NSAttributedString.Key.foregroundColor: UIColor.label] let bodyAttributes = [NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .body), NSAttributedString.Key.foregroundColor: UIColor.label] ``` ## 해결하지 못한 점 ### 1. DropBox 업로드/다운로드 오류 `uploadToDropBox` 메서드로 클라우드 업로드 (overwrite)를 할 때, 처음에는 문제가 없었는데 갑자기 DropBox의 3개 sqlite 파일 중 1개 (CloudNotes.sqlite)만 업데이트가 안되는 문제가 발생했습니다. CoreData가 저장된 `Application Support` 폴더 내부의 파일을 확인해봤는데, CoreData 파일은 정상적으로 업로드된 것을 확인했습니다. 그리고 업로드 response 출력문을 확인했을 때 3개 파일 모두 정상적으로 업로드된 것을 확인했습니다. ![](https://i.imgur.com/TK1ZijW.png) 왜 DropBox 폴더에서만 이러한 문제가 발생하는지 파악하고자 콘솔창의 에러문구를 모두 검색해봤지만 해결할 수 없었습니다. ``` // 다운로드 시 발생 CoreData: error: -executeRequest: encountered exception = I/O error for database at /Users/hyojuson/Library/Developer/CoreSimulator/Devices/05F35EA9-9E39-492C-8223-F54BBC92A49F/data/Containers/Data/Application/5D565A17-0D9F-4738-A637-D2A9DA49FFE9/Library/Application Support/CloudNotes.sqlite. SQLite error code:6922, 'disk I/O error' with userInfo = { NSFilePath = "/Users/hyojuson/Library/Developer/CoreSimulator/Devices/05F35EA9-9E39-492C-8223-F54BBC92A49F/data/Containers/Data/Application/5D565A17-0D9F-4738-A637-D2A9DA49FFE9/Library/Application Support/CloudNotes.sqlite"; NSSQLiteErrorDomain = 6922; } [error] error: (6922) I/O error for database at /Users/hyojuson/Library/Developer/CoreSimulator/Devices/05F35EA9-9E39-492C-8223-F54BBC92A49F/data/Containers/Data/Application/5D565A17-0D9F-4738-A637-D2A9DA49FFE9/Library/Application Support/CloudNotes.sqlite. SQLite error code:6922, 'disk I/O error' // 다운로드 및 업로드 시 발생 [logging] BUG IN CLIENT OF libsqlite3.dylib: database integrity compromised by API violation: vnode unlinked while in use: /Users/hyojuson/Library/Developer/CoreSimulator/Devices/05F35EA9-9E39-492C-8223-F54BBC92A49F/data/Containers/Data/Application/5D565A17-0D9F-4738-A637-D2A9DA49FFE9/Library/Application Support/CloudNotes.sqlite-wal ``` 커밋을 되돌리거나, 조원 모두가 실행을 해봐도 같은 오류가 발생하였습니다. ### 2. 메모 추가 직후 검색 기존에 있던 메모를 검색하는 작업은 괜찮았지만 새 메모를 추가직후에 해당 메모는 검색이 안되는 버그가 있습니다. ### 3. 메모 검색 후 삭제 특정 메모를 검색한 뒤 메모를 삭제하면 코어데이터나, 검색창을 끈 뒤의 테이블뷰에서는 정상적으로 삭제가 되는데 검색창을 띄운 상태에선 삭제가 되지 않는 버그가 있습니다. ## 궁금한 점 ### `Download`와 `Upload`의 시점 클라우드를 이용한 메모이기에, 어떤 시점에서 클라우드를 통해 데이터를 주고 받을 지에 대한 고민을 해보았습니다. 아무래도 모든 메모는 사용자가 직접 수정 또는 추가하기 전에 가장 최신버전의 메모에 기입을 해야한다고 생각을 해서, `Download`는 앱의 `Scene Delegate`에 구현을 해주었습니다. 그리고 반대로, 사용자가 모든 메모의 작성이 끝나면 `Upload`가 되어야한다고 생각을 했기에, 실제 메모를 적을 수 있는 `textView`의 `Delegate`인 `textViewDidEndEditing 에 구현을 해주었습니다. 이렇게 저희가 생각한 다운로드 및 업로드의 시점이 적절한지 여쭙고 싶습니다.

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully