-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Team-05 iOS JEJE, 만사] OAuth 로그인 화면 & Issue 전체 조회 화면 #27
base: team5
Are you sure you want to change the base?
Changes from 7 commits
61cbd60
45886f0
2ba9f5b
eec09a4
4298c0c
0acf2e8
bf9cfef
60a8c57
374c3c1
b2d30b9
f8c2542
2969620
28e0a02
5514d1b
d42b75b
721b468
e6d29d9
1b2463a
1e0a77b
5a95c0d
5f29c68
c0e8704
1320c78
091928e
01c5c48
6c138cc
e02e300
211788f
51fd2ca
f1002e6
755be9d
81b80e0
6023e53
3a2cba1
8929847
ffac99c
c7adeea
99a9403
d354bcb
1f7fe70
2d82996
a18473c
335f54e
fd93406
2f1a92b
6e5268a
051c7eb
17441af
dc57854
3ffa728
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// | ||
// EndPoint.swift | ||
// issueTrackerApp | ||
// | ||
// Created by 조중윤 on 2021/06/11. | ||
// | ||
|
||
import Foundation | ||
|
||
struct IssueEndPoint { | ||
static let scheme = "https" | ||
static let host = "f88e009a-3e2b-4862-838e-1f2cde9b95ed.mock.pstmn.io" | ||
static let basicPath = "/api/issues" | ||
// static let countPath = "/count" | ||
|
||
static func url() -> URL { | ||
var components = URLComponents() | ||
components.scheme = IssueEndPoint.scheme | ||
components.host = IssueEndPoint.host | ||
components.path = IssueEndPoint.basicPath | ||
return components.url! | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// | ||
// IssueNetworkController.swift | ||
// issueTrackerApp | ||
// | ||
// Created by 조중윤 on 2021/06/13. | ||
// | ||
|
||
import Foundation | ||
|
||
class IssueNetworkController { | ||
private var requests: [URL: AnyObject] = [:] | ||
|
||
init() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 생성자 사용하지 않는다면 제거하세요🤔 |
||
} | ||
|
||
func fetchIssues(completion: @escaping ([Issue]) -> Void) { | ||
let req = IssueRequest() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fetchIssues, deleteIssue 호출할 때마다 Request 객체 매번 생성하는 것보다 IssueNetworkController 생성하는 시점에서 한 번만 생성해서 사용해도 무방할거 같은데, 이 부분은 의견이 궁금합니다! |
||
let requestURL = req.fetchReq.url! | ||
requests[requestURL] = req | ||
|
||
req.execute { (result) in | ||
if let _ = result { | ||
self.requests[requestURL] = nil | ||
completion(result!) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
} | ||
} | ||
|
||
func deleteIssue(with issueId: Int, completion: @escaping (Status) -> Void) { | ||
let req = IssuePatchRequest() | ||
var requestURL = req.fetchReq.url! | ||
requestURL.appendPathComponent(String(issueId), isDirectory: false) | ||
requests[requestURL] = req | ||
|
||
req.execute { (status) in | ||
if let _ = status { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 부분도 위와 동일하게 처리할 수 있습니다! |
||
self.requests[requestURL] = nil | ||
completion(status!) | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// | ||
// IssuePatchRequest.swift | ||
// issueTrackerApp | ||
// | ||
// Created by 조중윤 on 2021/06/15. | ||
// | ||
|
||
import Foundation | ||
|
||
class IssuePatchRequest { | ||
let session = URLSession(configuration: .ephemeral, delegate: nil, delegateQueue: .main) | ||
var task: URLSessionDataTask? | ||
|
||
init() { | ||
} | ||
} | ||
|
||
extension IssuePatchRequest: JSONDataRequest { | ||
typealias ModelType = Status | ||
|
||
var fetchReq: URLRequest { | ||
let urlComponents = URLComponents(url: IssueEndPoint.url(), resolvingAgainstBaseURL: false)! | ||
var request = try! URLRequest(url: urlComponents, method: .patch) | ||
let body = ["delete": true] | ||
let bodyData = try? JSONSerialization.data( | ||
withJSONObject: body, | ||
options: []) | ||
request.httpBody = bodyData | ||
return request | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// | ||
// IssueNetworkRequest.swift | ||
// issueTrackerApp | ||
// | ||
// Created by 조중윤 on 2021/06/11. | ||
// | ||
|
||
import Foundation | ||
|
||
class IssueRequest { | ||
let session = URLSession(configuration: .ephemeral, delegate: nil, delegateQueue: .main) | ||
var task: URLSessionDataTask? | ||
|
||
init() { | ||
} | ||
} | ||
|
||
extension IssueRequest: JSONDataRequest { | ||
typealias ModelType = [Issue] | ||
|
||
var fetchReq: URLRequest { | ||
let urlComponents = URLComponents(url: IssueEndPoint.url(), resolvingAgainstBaseURL: false)! | ||
let request = try! URLRequest(url: urlComponents, method: .get) | ||
return request | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,15 +9,15 @@ import Foundation | |
|
||
protocol NetworkRequest: class { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 컴파일러 워닝에 걸릴거 같은데 확인하고 수정해주세요! |
||
associatedtype ModelType | ||
var urlRequest: URLRequest { get } | ||
var fetchReq: URLRequest { get } | ||
var session: URLSession { get } | ||
var task: URLSessionDataTask? { get set } | ||
func deserialize(_ data: Data?, response: URLResponse?) -> ModelType? | ||
} | ||
|
||
extension NetworkRequest { | ||
func execute(withCompletion completion: @escaping (ModelType?) -> Void) { | ||
task = session.dataTask(with: urlRequest) { [weak self] (data, response, error) in | ||
task = session.dataTask(with: fetchReq) { [weak self] (data, response, error) in | ||
completion( self?.deserialize(data, response: response) ) | ||
} | ||
task?.resume() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// | ||
// Status.swift | ||
// issueTrackerApp | ||
// | ||
// Created by 조중윤 on 2021/06/15. | ||
// | ||
|
||
import Foundation | ||
|
||
struct Status: Codable { | ||
let status: String | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// | ||
// NotificationNameExtension.swift | ||
// issueTrackerApp | ||
// | ||
// Created by 조중윤 on 2021/06/14. | ||
// | ||
|
||
import Foundation | ||
|
||
extension Notification.Name { | ||
static let didFilterIssueData = Notification.Name("didFilterIssueData") | ||
static let didReceiveIssueData = Notification.Name("didReceiveIssueData") | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// | ||
// IssueSelectTableViewController.swift | ||
// issueTrackerApp | ||
// | ||
// Created by 조중윤 on 2021/06/15. | ||
// | ||
|
||
import UIKit | ||
|
||
class IssueSelectTableViewController: UITableViewController { | ||
|
||
var issues: [Issue] = [] | ||
|
||
override func viewDidLoad() { | ||
super.viewDidLoad() | ||
|
||
self.configureTableView() | ||
self.configureBackBarButtonItem() | ||
self.configureRightBarButtonItem() | ||
} | ||
|
||
public func prepare(with issues: [Issue]) { | ||
self.issues = issues | ||
} | ||
|
||
private func configureTableView() { | ||
self.tableView.register(IssueCell.nib, forCellReuseIdentifier: IssueCell.identifier) | ||
self.tableView.allowsMultipleSelection = true | ||
} | ||
|
||
private func configureBackBarButtonItem() { | ||
self.navigationItem.hidesBackButton = true | ||
} | ||
|
||
private func configureRightBarButtonItem() { | ||
let rightBarButtonItem = UIBarButtonItem(title: "취소", image: nil, primaryAction: UIAction.init(handler: { (touch) in | ||
self.navigationController?.popViewController(animated: true) | ||
}), menu: nil) | ||
|
||
self.navigationItem.rightBarButtonItem = rightBarButtonItem | ||
} | ||
|
||
// MARK: - Table view data source | ||
|
||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { | ||
return self.issues.count | ||
} | ||
|
||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { | ||
|
||
guard let cell = self.tableView.dequeueReusableCell(withIdentifier: IssueCell.identifier) as? IssueCell else { return UITableViewCell() } | ||
cell.configureAll(with: issues[indexPath.row]) | ||
|
||
return cell | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
// | ||
// IssueViewModel.swift | ||
// issueTrackerApp | ||
// | ||
// Created by 조중윤 on 2021/06/14. | ||
// | ||
|
||
import Foundation | ||
|
||
protocol IssueViewModelProtocol { | ||
var issues: [Issue] { get } | ||
var filteredIssues: [Issue] { get set } | ||
func fetchAllIssue() | ||
func filterIssuesWithSearchText(_ string: String) | ||
func deleteIssue(at index: Int, completionHandler: @escaping () -> Void) | ||
} | ||
|
||
class IssueViewModel: IssueViewModelProtocol { | ||
var networkController: IssueNetworkController? | ||
var issues: [Issue] = [] { | ||
didSet { | ||
NotificationCenter.default.post(name: .didReceiveIssueData, object: nil) | ||
} | ||
} | ||
|
||
var filteredIssues: [Issue] = [] { | ||
didSet { | ||
NotificationCenter.default.post(name: .didFilterIssueData, object: nil) | ||
} | ||
} | ||
|
||
init(issueNetworkController: IssueNetworkController) { | ||
self.networkController = issueNetworkController | ||
} | ||
|
||
func fetchAllIssue() { | ||
// networkController?.fetchIssues(completion: { (issues) in | ||
// self.issues = issues | ||
// }) | ||
let label1 = Label(id: 1, title: "123", colorCode: "#912939") | ||
let label2 = Label(id: 1, title: "121233", colorCode: "#153239") | ||
|
||
|
||
let issue1 = Issue(id: 123, title: "sdf", description: "sdfsdfsdf", authorAvatarURL: "sdf", labelList: [label1, label2], issueNumber: 1, createdAt: "sdf", milestoneTitle: "milsteon1") | ||
|
||
let issue2 = Issue(id: 13, title: "ssdfsdfdf", description: "sdfsdfsdf", authorAvatarURL: "sdf", labelList: [label1, label2], issueNumber: 1, createdAt: "sdf", milestoneTitle: "milsteon1") | ||
|
||
self.issues = [issue1, issue2] | ||
} | ||
|
||
func filterIssuesWithSearchText(_ string: String) { | ||
self.filteredIssues = issues.filter({ (issue: Issue) -> Bool in | ||
return issue.title.lowercased().contains(string.lowercased()) | ||
}) | ||
} | ||
|
||
func deleteIssue(at index: Int, completionHandler: @escaping () -> Void) { | ||
let issueId = issues[index].id | ||
networkController?.deleteIssue(with: issueId, completion: { (res) in | ||
if res.status == "success" { | ||
self.issues.remove(at: index) | ||
completionHandler() | ||
} | ||
}) | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
외부에서 사용하지 않는다면 private 접근제어자 사용하세요🤔