Skip to content
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
aea9a63
[Jinsujin/issue-tracker#20] Feat: 새 이슈 생성 시 선택 옵션을 Option enum으로 분리
bibi6666667 Jun 27, 2022
ed0be9c
[Jinsujin/issue-tracker#20] Feat: 새 이슈 생성 시 저장소 선택 화면 구현
bibi6666667 Jun 27, 2022
3611e1a
[Jinsujin/issue-tracker#20] Fix: issue list api
Jinsujin Jun 27, 2022
3c6694a
[Jinsujin/issue-tracker#20] Feat: Repository 엔티티 추가 및 repository 요청 코…
bibi6666667 Jun 27, 2022
7753233
Merge branch 'feat#20' of https://github.com/Jinsujin/issue-tracker i…
Jinsujin Jun 27, 2022
60069e4
[Jinsujin/issue-tracker#20] Feat: OptionSelectViewController 생성을 Cont…
bibi6666667 Jun 27, 2022
fb53b06
[Jinsujin/issue-tracker#20] Refactor: Container에서 OptionSelectViewCon…
bibi6666667 Jun 28, 2022
a17829e
[Jinsujin/issue-tracker#20] Feat: 새 이슈 생성 시 API 요청하여 Repository 불러오기 …
bibi6666667 Jun 28, 2022
d14a0d7
[Jinsujin/issue-tracker#20] Feat: 이슈 만들기 버튼과 API 연결
Jinsujin Jun 28, 2022
09d8f7e
[Jinsujin/issue-tracker#20] Feat: 새 이슈 생성 기능 구현
bibi6666667 Jun 29, 2022
b425f41
[Jinsujin/issue-tracker#20] chore: 불필요한 코드 및 주석 제거
bibi6666667 Jun 29, 2022
547ac43
[Jinsujin/issue-tracker#24] Ref: 옵션 선택하는 화면에서 API 를 호출하도록 수정
Jinsujin Jun 29, 2022
d494374
[Jinsujin/issue-tracker#24] Ref: 선택한 아이템을 이전화면으로 넘길때 리스트에서 option 을 찾…
Jinsujin Jun 29, 2022
43aefc6
[Jinsujin/issue-tracker#24] Feat: 로그인 후, 첫 화면을 repo list 로 변경
Jinsujin Jun 29, 2022
e24536b
[Jinsujin/issue-tracker#24] Feat: 이슈 목록을 불러올때, issue tab 에서 생성한 이슈만 가…
Jinsujin Jun 29, 2022
c200084
Ref: Container 가 token 을 주입받도록 수정
Jinsujin Jun 30, 2022
a30d281
Ref: Container 에서 ViewController 인스턴스 생성시, token 을 주입하도록 함
Jinsujin Jun 30, 2022
4ec1a9f
Feat: 레포지토리 리스트 화면에서의 Model 생성과 연결
Jinsujin Jun 30, 2022
48e7ceb
Ref: navigation 의 largetitle 설정
Jinsujin Jun 30, 2022
94700a7
[Jinsujin/issue-tracker] Feat: NewIssueModel 계층 추가
bibi6666667 Jun 30, 2022
f4b1f07
[Jinsujin/issue-tracker] chore: 불필요한 코드 및 주석 삭제
bibi6666667 Jun 30, 2022
3200b4f
[Jinsujin/issue-tracker] OptionSelectModel 계층 추가
bibi6666667 Jun 30, 2022
bc006c4
[Jinsujin/issue-tracker] Feat: 새 이슈 생성 시 Label 붙이는 기능 추가
bibi6666667 Jun 30, 2022
5e8b77a
Feat: 선택한 옵션이 무엇인지에 따라서 다른데이터를 불러오도록 수정
Jinsujin Jun 30, 2022
d2675b2
Feat: assignees 를 불러오는 API작업중
Jinsujin Jun 30, 2022
b398019
[Jinsujin/issue-tracker] Feat: 새 이슈 생성 시 해당 저장소에 대한 Assignee 조회 구현
bibi6666667 Jul 1, 2022
b86ec49
[Jinsujin/issue-tracker] Feat: 제목, 내용, label, milestone, assignee를 포함…
bibi6666667 Jul 1, 2022
1ddb879
[Jinsujin/issue-tracker] 불필요한 코드, 주석 삭제 및 파일 분리
bibi6666667 Jul 1, 2022
d5c4855
Ref: GithubUserDefaults 의 static 제거
Jinsujin Jul 8, 2022
709b78b
Ref: Repos 바인딩을 Container 에 하도록 변경
Jinsujin Jul 8, 2022
cf39c51
Doc: readme.md 업뎃
Jinsujin Jul 8, 2022
94f6cb2
[Jinsujin/issue-tracker] #28 Container의 의존성을 관리하는 ContainerEnvironmen…
bibi6666667 Jul 19, 2022
2cf9ed0
[Jinsujin/issue-tracker #28] ReposModel의 의존성인 IssueService.requestRep…
bibi6666667 Jul 19, 2022
c5bca22
Revert "[Jinsujin/issue-tracker #28] ReposModel의 의존성인 IssueService.re…
bibi6666667 Jul 20, 2022
f1dc0ce
[Jinsujin/issue-tracker #28] ReposModel의 의존성인 IssueService.requestRep…
bibi6666667 Jul 19, 2022
d791820
[Jinsujin/issue-tracker] #28 IssueModel이 service 전체를 받지 않고, service에서…
bibi6666667 Jul 21, 2022
aaf1c2f
[Jinsujin/issue-tracker] #28 Feat: NewIssueModel에 service 전체 대신, 필요한 …
bibi6666667 Jul 21, 2022
7e9b7ba
[Jinsujin/issue-tracker] #28 Feat: OptionSelect에서 사용하는 service의 메서드들을…
bibi6666667 Jul 21, 2022
3dce5a4
[Jinsujin/issue-tracker] #28 Refactor: LoginVC와 LoginModel 분리 및 OAuth…
bibi6666667 Jul 22, 2022
2aa67de
[Jinsujin/issue-tracker] #28 Refactor: IssueVC 생성 시 필요한 작업을 viewDidLo…
bibi6666667 Jul 25, 2022
da4fa97
[Jinsujin/issue-tracker] #28 Refactor: OptionSelectVC 생성 시 필요한 설정 부분을…
bibi6666667 Jul 25, 2022
4d2672b
Merge branch 'develop' into bibi/refactor
bibi6666667 Jul 25, 2022
a54d231
Merge pull request #29 from Jinsujin/bibi/refactor
bibi6666667 Aug 9, 2022
7eb9168
Feat : AppDelegate를 위한 코디네이터인 AppCoordinator 생성 및 실행 시점 rootVC 판단 로직 분리
bibi6666667 Aug 9, 2022
50e1cb4
Feat: Container에 register, resolve 패턴 적용해 Login/Repos 화면 전환
bibi6666667 Aug 11, 2022
c43f970
Feat: ReposVC에 코디네이터와 컨테이너 적용
bibi6666667 Aug 16, 2022
7bf8c02
Feat: ReposViewController를 보여줄 때 ReposCoordinator를 사용하도록 변경
bibi6666667 Aug 19, 2022
1065a7b
Feat: IssueViewController 화면 흐름을 관리하는 IssueCoordinator 추가 #28
bibi6666667 Aug 31, 2022
93724ce
Feat: NewIssueViewController를 관리하는 NewIssueCoordinator 추가 및 새 이슈 생성에 …
bibi6666667 Aug 31, 2022
300373e
Feat: 모든 뷰컨에 coordinator 프로퍼티 추가 및 NewIssue 생성 시 뒤로가기 동작 구현 #28
bibi6666667 Aug 31, 2022
7170c83
Feat: OptionSelectViewController를 관리하는 OptionSelectCoordinator 추가 #28
bibi6666667 Aug 31, 2022
9f80da2
Feat : coordinator생성 시 register한 뒤, childCoordinators 관리할 때 활용 #28
bibi6666667 Sep 2, 2022
e3a03eb
Feat : 이슈생성, 옵션선택 후 coordinator에서 이전 화면으로 되돌아가며 reload호출 (동작하지 않음) #28
bibi6666667 Sep 2, 2022
c94cb85
Feat : OptionSelectVC를 coordinator로 연결 - 옵션마다 다른 화면 생성 #28
bibi6666667 Sep 2, 2022
6f7ac28
Merge branch 'bibi/refactor' of https://github.com/Jinsujin/issue-tra…
bibi6666667 Sep 2, 2022
7e2c599
Feat : 이슈 생성 요청과 이슈목록 요청 사이에 딜레이 추가, 받아온 이슈에 새로 생성한 이슈가 없다면 재요청 #28
bibi6666667 Sep 5, 2022
cf7c960
Chore : 미사용 메서드와 주석 삭제 #28
bibi6666667 Sep 5, 2022
00867fb
Chore : 불필요한 주석 및 코드 삭제 #28
bibi6666667 Sep 6, 2022
5865265
refactor: ViewController deinit이 호출되지 않는 문제 디버깅 #28
bibi6666667 Sep 15, 2022
75a66ca
refactor: 변수명을 적절하게 수정 #28
bibi6666667 Sep 15, 2022
264ed97
refactor: 불필요한 self 키워드 삭제 #28
bibi6666667 Sep 15, 2022
d37d8c9
refactor: 이슈 생성 요청 이후 새 이슈가 생성되었는지 확인한 다음 이슈 목록으로 되돌아가도록 변경 (뷰 미완성) #28
bibi6666667 Sep 15, 2022
55b3b87
refactor : 새 이슈 생성 -> 이슈 조회 흐름 수정. #28
bibi6666667 Sep 16, 2022
0d2db84
debug : 로그인 직후 앱으로 돌아왔을 때 저장소 목록이 나오지 않는 현상 디버깅(해결) #28
bibi6666667 Sep 21, 2022
6e2fcec
refactor : Container에서 뷰컨트롤러와 관련 코디네이터를 묶어 관리하고 삭제 작업도 처리하도록 변경 #28
bibi6666667 Sep 22, 2022
448b9dd
refactor : 뷰컨트롤러와 관련 코디네이터 이름을 담은 ViewControllerCoordinator 열거형을 사용해 …
bibi6666667 Sep 22, 2022
f44007b
chore : 불필요한 주석 및 print문 삭제 #28
bibi6666667 Sep 22, 2022
c5d1b0b
debug : IssueService 초기화를 위해 토큰 기본값을 넘기는 대신 옵셔널로 타입 수정 #28
bibi6666667 Sep 26, 2022
13517eb
Merge pull request #31 from Jinsujin/bibi/refactor
bibi6666667 Sep 30, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion IssueTracker/IssueTracker.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
005E48D62862AE91004BD5F6 /* Container.swift in Sources */ = {isa = PBXBuildFile; fileRef = 005E48D52862AE91004BD5F6 /* Container.swift */; };
005E48D828630635004BD5F6 /* NewIssueViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 005E48D728630635004BD5F6 /* NewIssueViewController.swift */; };
005E48DA28636064004BD5F6 /* Devider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 005E48D928636064004BD5F6 /* Devider.swift */; };
00AF8F282869A7060009674C /* Repository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00AF8F272869A7060009674C /* Repository.swift */; };
00BCB406285B01AA005E87BC /* Issue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00BCB405285B01AA005E87BC /* Issue.swift */; };
00BCB408285B0262005E87BC /* Label.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00BCB407285B0262005E87BC /* Label.swift */; };
00BCB40A285B027B005E87BC /* Milestone.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00BCB409285B027B005E87BC /* Milestone.swift */; };
Expand Down Expand Up @@ -68,6 +69,7 @@
005E48D52862AE91004BD5F6 /* Container.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container.swift; sourceTree = "<group>"; };
005E48D728630635004BD5F6 /* NewIssueViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewIssueViewController.swift; sourceTree = "<group>"; };
005E48D928636064004BD5F6 /* Devider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Devider.swift; sourceTree = "<group>"; };
00AF8F272869A7060009674C /* Repository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Repository.swift; sourceTree = "<group>"; };
00BCB405285B01AA005E87BC /* Issue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Issue.swift; sourceTree = "<group>"; };
00BCB407285B0262005E87BC /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = "<group>"; };
00BCB409285B027B005E87BC /* Milestone.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Milestone.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -145,9 +147,9 @@
981BD438285B123A00DDDE64 /* Issue */ = {
isa = PBXGroup;
children = (
988FA2E92864034C0058C333 /* OptionSelectViewController.swift */,
98130E1A285AC8A5001B6DA1 /* IssueViewController.swift */,
005E48D728630635004BD5F6 /* NewIssueViewController.swift */,
988FA2E92864034C0058C333 /* OptionSelectViewController.swift */,
00567EEA2861B43600F3E8EC /* Model */,
00567EE92861B42A00F3E8EC /* Service */,
981BD439285B124E00DDDE64 /* View */,
Expand Down Expand Up @@ -182,6 +184,7 @@
00BCB407285B0262005E87BC /* Label.swift */,
00BCB409285B027B005E87BC /* Milestone.swift */,
00BCB40B285B076B005E87BC /* State.swift */,
00AF8F272869A7060009674C /* Repository.swift */,
);
path = Entity;
sourceTree = "<group>";
Expand Down Expand Up @@ -437,6 +440,7 @@
00BCB40C285B076B005E87BC /* State.swift in Sources */,
988FA2EA2864034C0058C333 /* OptionSelectViewController.swift in Sources */,
00BCB406285B01AA005E87BC /* Issue.swift in Sources */,
00AF8F282869A7060009674C /* Repository.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
4 changes: 2 additions & 2 deletions IssueTracker/IssueTracker/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {

private let container = Container()

var window: UIWindow?

let container = Container()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

프라이빗을 푸신 이유가 싱글톤에서 접근하게 만들기 위해서 일까요??

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

앗..흔적이 남아있네요😅
Container를 써야 하는 곳은 많은데 객체는 하나만 만들고 싶어서, 싱글톤을 적용해보려 했다가
지난 PR에 static 객체에 접근하기보다는 다른 방법을 사용해보라고 하셨던게 생각나서 싱글톤 없이 해보려고 방향을 바꾸었습니다.
그러다가 (바로 아래와 같은) 더 안 좋은 상황이 발생한 것 같네요..🥲


func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// TODO: - 토큰 유효기간 판단
// 토큰저장할때: 토큰 & 토큰이 저장된 시간 & 유효시간(1일)
Expand Down
7 changes: 6 additions & 1 deletion IssueTracker/IssueTracker/Container.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@

import UIKit

import UIKit

struct Container {
enum Screen {
case login
case issue(token: String)
case newIssue
case optionSelect(token: String, repositories: [Repository])
}

func buildRootViewController() -> UIViewController {
Expand All @@ -30,9 +33,11 @@ struct Container {
let service = IssueService()
let model = IssueModel(service: service, token: token)
let viewController = IssueViewController(model: model)
return UINavigationController(rootViewController: vc)
return UINavigationController(rootViewController: viewController)
case .newIssue:
return NewIssueViewController()
case .optionSelect(let token, let repositories):
return OptionSelectViewController(token: token, options: repositories)
}
}
}
5 changes: 0 additions & 5 deletions IssueTracker/IssueTracker/Entity/Issue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@ struct Issue: Codable {
let repository: Repository
}

struct Repository: Codable {
let name: String
let owner: Owner
}

struct Owner: Codable {
let login: String
}
14 changes: 14 additions & 0 deletions IssueTracker/IssueTracker/Entity/Repository.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// Repository.swift
// IssueTracker
//
// Created by Bibi on 2022/06/27.
//

import Foundation


struct Repository: Codable {
let name: String
let owner: Owner
}
5 changes: 4 additions & 1 deletion IssueTracker/IssueTracker/GitHub/RequestURL.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ enum RequestURL: CustomStringConvertible {
case authorize
case accessToken
case issues
case userIssues
case createIssue(owner: String, repo: String)
case repos

Expand All @@ -15,10 +16,12 @@ enum RequestURL: CustomStringConvertible {
return "https://github.com/login/oauth/access_token"
case .issues:
return "https://api.github.com/issues"
case .userIssues:
return "https://api.github.com/user/issues"
case let .createIssue(owner, repo):
return "https://api.github.com/repos/\(owner)/\(repo)/issues"
case .repos:
return "https://github.com/user/repos"
return "https://api.github.com/user/repos"
}
}
}
19 changes: 15 additions & 4 deletions IssueTracker/IssueTracker/Issue/IssueViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ final class IssueViewController: UIViewController {
}))
button.setImage(UIImage(systemName: "plus"), for: .normal)

// button.layer.cornerRadius = 50 / 2

return button
}()

Expand All @@ -48,7 +46,7 @@ final class IssueViewController: UIViewController {
setupViews()
model.requestIssue()
model.updatedIssues = { [weak self] issues in
DispatchQueue.main.async { [weak self] in
DispatchQueue.main.async { [weak self] in
self?.collectionView.reloadData()
}
}
Expand All @@ -64,7 +62,14 @@ final class IssueViewController: UIViewController {
}

@objc func touchedAddButton() {
self.navigationController?.pushViewController(Container().buildViewController(.newIssue), animated: true)
guard let appdelegate = UIApplication.shared.delegate as? AppDelegate else {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이슈 뷰컨트롤러에서 앱에서 단하나만 존재하는 앱델리게이트 객체를 오브젝트화 시키고 있습니다.
윈도우를 넘기셨을때 드렸던 피드백이 기억나실까요??
해당 접근은 제 기준에서, 너무나도 많이 위험해보입니다.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

음.. 앱델리게이트는 앱이 죽을때까지 살아있는데 그걸 오브젝트로 만들어서 위험하겠군요.ㅠㅠ
Container를 하나만 만들고, 만들어 둔 곳에서 참조해서 쓰려고 이런 식으로 접근했는데 다른 방법을 찾아보겠습니다.

return
}
guard let viewController = appdelegate.container.buildViewController(.newIssue) as? NewIssueViewController else {
return
}
self.navigationController?.pushViewController(viewController, animated: true)
viewController.delegate = self

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

추가하신 일련의 작업을 글로 작성해주실 수 있을까요??

해당 부분을 작성해주신다면, 제 시야에선 어떤식으로 접근할 것인지 같이 보면 좋을 거 같네요 :)

사실 해당 작업은 제가 좋아하는 선배 개발자분과 제가 같이 했었던 작업인데 여러분들과 할 수 있는 기회가 많아서 개인적으론 매우 기쁩니다.

Copy link

@bibi6666667 bibi6666667 Jun 29, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

touchedAddButton() 말씀하시는 것 같아서 이 부분 글로 적어보겠습니다!

  • 이슈목록(IssueViewController)에서 +버튼을 누르면 해당 메서드가 실행된다
  • 메서드 실행 시 AppDelegate의 Container에 접근해, 새 이슈 화면(NewIssueViewController)를 생성해 가져온 다음,
  • 이슈목록(IssueViewController)의 navigationViewController에 새 이슈 화면(NewIssueViewController)를 push해 보여준다.
  • 마지막으로 push로 보여지는 새 이슈 화면(NewIssueViewController)의 delegate를 IssueViewController로 설정한다.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 부분에서 제가 보이는 시야는
AppDelegate에 포함된 객체를 접근하는게 아닌, 일련의 동작을 주입시켜주며 처리하는 방향이 보입니다.
그렇게 됐을때, IssueViewController는 AppDelegate, 화면 전환 로직을 모두 제거할 수 있게 됩니다.

}

private func setupNavigationBar() {
Expand Down Expand Up @@ -149,3 +154,9 @@ extension IssueViewController: UICollectionViewDelegateFlowLayout {
return CGSize(width: collectionView.frame.width, height: 200)
}
}

extension IssueViewController: NewIssueCreateDelegate {
func created() {
model.requestIssue()
}
}
99 changes: 87 additions & 12 deletions IssueTracker/IssueTracker/Issue/NewIssueViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,43 @@
//

import UIKit
import SwiftUI

protocol NewIssueCreateDelegate: AnyObject {
func created()
}

class NewIssueViewController: UIViewController {

weak var delegate: NewIssueCreateDelegate?

private let service = IssueService()

private let optionList = Option.allCases
private var selectedList = Array<String>(repeating: "", count: Option.allCases.count)

private var selectedRepo: Repository?

enum Option: CaseIterable {
case repository
case label
case milestone
case assignee

var description: String {
switch self {
case .repository:
return "저장소"
case .label:
return "레이블"
case .milestone:
return "마일스톤"
case .assignee:
return "담당자"
}
}
}

private lazy var navSegmentedControl: UISegmentedControl = {
let buttonList = ["마크다운", "미리보기"]
var control = UISegmentedControl(items: buttonList)
Expand Down Expand Up @@ -38,7 +72,6 @@ class NewIssueViewController: UIViewController {
return devider
}()

private let optionList = ["저장소", "레이블", "마일스톤", "담당자"]
private let optionTableCellIdentifier = "optionTableCellIdentifier"

private lazy var optionTable: UITableView = {
Expand Down Expand Up @@ -109,7 +142,6 @@ class NewIssueViewController: UIViewController {
make.top.equalTo(horizontalDevider.snp.bottom)
make.leading.trailing.equalTo(self.view.safeAreaLayoutGuide)
make.bottom.equalTo(optionTable.snp.top)

}
}

Expand All @@ -129,18 +161,53 @@ class NewIssueViewController: UIViewController {
}()

private func touchedCreateButton() {
// TODO: 이슈생성
//1. api 호출
//2. api 가 성공적으로 응답을 보내줬다면 =>
//2-1. 이전 화면으로 돌아가고
//2-2. 이슈 목록 조회 다시해서 보여주기
//3. api 가 실패했다면 => issue 생성실패 얼럿띄우기

guard let token = GithubUserDefaults.getToken(),
let selectedRepo = selectedRepo else {
return
}
guard let titleString = self.titleField.text,
!titleString.isEmpty else {
// TODO: - 타이틀 입력 값이 없다 => 얼럿
return
}

service.createIssue(title: titleString, repo: selectedRepo, accessToken: token) { boolResult in
if boolResult {
self.navigationController?.popViewController(animated: true)
self.delegate?.created()
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 부분 코드도 성격이 유사합니다.
코쿼분들의 코드를 보면, 성격을 나누는거에 포인트를 많이 두세요. 이상하다는건 아닙니다.
다만 이를 사용해서 자연스럽게 붙이는 작업도 나누는거 만큼 중요하다고 생각합니다.

해당 부분도 글로 정리해주시겠나요?

코맨트에 정리하신건 알지만, 다시한번 부탁드리겠습니다. 유사하게 작성하셔도 좋아요 :)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'성격을 나눈다'는 게 어떤 의미로 해주신 말씀인가요? guard let token = ..., guard let titleString = ...과 같은 부분일까요?
일단 touchedCreateButton() 이부분도 글로 정리해 보겠습니다!

  • 새 이슈 생성 화면에서 '저장'버튼을 클릭하면
  • 앱에 저장된 AccessToken과, 현재 선택된 저장소를 가져온다
  • 현재 입력된 이슈 제목 값을 가져온다 (제목이 비어있으면 return)
  • 제목, AccessToken, 선택된 저장소 정보를 가지고 Service를 통해 API에 이슈 생성 요청을 보낸다.
    • 이 결과가 true이면, navigationStack의 직전 화면으로 돌아가고,
    • 연결된 delegate에 이슈가 생성되었음을 알린다.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

객체가 담당하는 역할에 대해서 분리하는 걸 뜻했습니다.
작게 작게 나누는거에 초점을 두다 보니, 해당 자원이 필요할때, 막상 이상하게 접근하는 경우가 많았습니다.

NewIssueViewController의 경우도, 위 행동을 추상화 시킨다면, 버튼이 눌렸을때, 행동을 실행시키며
해당 행동은 NewIssueViewController를 만들 때 넣어주기만 하면 됩니다.

}
}
}

extension NewIssueViewController: UITableViewDelegate {

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
switch optionList[indexPath.row] {
case .repository:
// TODO: issueService의 requestRepos() 연결해서 저장소목록 보여주기
guard let appdelegate = UIApplication.shared.delegate as? AppDelegate,
let token = GithubUserDefaults.getToken() else {
return
}

service.requestRepos(accessToken: token) { result in
switch result {
case .success(let repositoryList):
guard let viewController = appdelegate.container.buildViewController(.optionSelect(token: token, repositories: repositoryList)) as? OptionSelectViewController else {
return
}
self.navigationController?.pushViewController(viewController, animated: true)
viewController.delegate = self
case .failure(let error):
print(error)
}
}


default:
break
}
}
}

extension NewIssueViewController: UITableViewDataSource {
Expand All @@ -152,8 +219,8 @@ extension NewIssueViewController: UITableViewDataSource {
let cell = tableView.dequeueReusableCell(withIdentifier: optionTableCellIdentifier,
for: indexPath)
var sidebarCell = UIListContentConfiguration.sidebarCell()
sidebarCell.text = optionList[indexPath.item]
sidebarCell.secondaryText = "선택내용"
sidebarCell.text = optionList[indexPath.item].description
sidebarCell.secondaryText = selectedList[indexPath.item]
sidebarCell.prefersSideBySideTextAndSecondaryText = true

cell.contentConfiguration = sidebarCell
Expand All @@ -162,3 +229,11 @@ extension NewIssueViewController: UITableViewDataSource {
}

}

extension NewIssueViewController: OptionSelectDelegate {
func selected(item: Repository) {
selectedList[0] = item.name
selectedRepo = item
self.optionTable.reloadData()
}
}
40 changes: 35 additions & 5 deletions IssueTracker/IssueTracker/Issue/OptionSelectViewController.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,30 @@
import UIKit
import SnapKit

class OptionSelectViewController: UIViewController {
protocol OptionSelectDelegate: AnyObject {
func selected(item: Repository)
}

private let dummy = ["bug", "feature", "document"]
class OptionSelectViewController: UIViewController {

weak var delegate: OptionSelectDelegate?

private let service = IssueService()
private var token: String?
private var options: [Repository]?

private let tableViewCellIdentifier = "tableViewCellIdentifier"

init(token: String, options: [Repository]) {
super.init(nibName: nil, bundle: nil)
self.token = token

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

토큰이 정말 필요한 값이였을까요??
사실 이부분도 다른 관점이 시작됩니다.
필요한걸 줄수만 있다면 과연 토큰이 필요할지 고민해보셨으면 좋겠습니다.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

제 생각에는 OptionSelectViewController에서 필요한건 [Repository] 인데 그럼 이것만 넣어주면 토큰이 필요없어지긴 할 것 같습니다!
그런데 그러면 OptionSelectViewController를 만들어주는 Container에서 API요청까지 해서 [Repository]를 넣어줘야 하는데, 컨테이너가 이 역할까지 해줘도 괜찮은 건가요?🤔

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ViewController는 즉 View의 경우 이벤트를 발생시키는 역할만 충실히 만족하며,
해당 부분 외의 작업은 다른 영역에서 담당하는게 유지보수 및 테스트하기 용이합니다.
위 작업을 진행하기 위해서 Container 즉 DIContainer에서 해당 작업을 처리하는게 어색하게 느껴지지 않습니다.
반대로 ViewController를 생성하는데 토큰이 필요한 점이 더 어색하게 느껴집니다.

self.options = options
}

required init?(coder: NSCoder) {
super.init(coder: coder)
}

override func viewDidLoad() {
super.viewDidLoad()
setupViews()
Expand All @@ -32,20 +51,31 @@ class OptionSelectViewController: UIViewController {

extension OptionSelectViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// TODO: - 선택한 옵션을 이전 ViewController 에 넘겨주기
guard let options = options else {
return
}
let selectedItem = options[indexPath.row]
delegate?.selected(item: selectedItem)
self.navigationController?.popViewController(animated: true)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

코디네이터 즉 컨테이너를 둔 상태에서 뷰컨끼리의 이동은 전부 추상화 될 수 있는 부분입니다.

}
}

extension OptionSelectViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dummy.count
guard let options = options else {
return 0
}
return options.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let options = options else {
return UITableViewCell()
}
let cell = tableView.dequeueReusableCell(withIdentifier: tableViewCellIdentifier,
for: indexPath)
var content = cell.defaultContentConfiguration()
content.attributedText = NSAttributedString(string: dummy[indexPath.row])
content.attributedText = NSAttributedString(string: options[indexPath.row].name)
cell.contentConfiguration = content
return cell
}
Expand Down
Loading