Uh oh!
There was an error while loading. Please reload this page.
Conversation
| return json.arrayValue.map{ | ||
| Model.Issue(json: $0) | ||
| } | ||
| }) |
There was a problem hiding this comment.
뭔가 좀더 간단히 할 수 있을 것 같은데..
letresult= dataResponse.map{ $0.arrayValue }.map{Model.Issue(json: $0)}| } | ||
| typealias IssueResponsesHandler = (DataResponse<[Model.Issue]>) -> Void | ||
| static func repoIssues(owner: String, repo: String) -> (Int, @escaping IssueResponsesHandler) -> Void { |
There was a problem hiding this comment.
API. IssueResponsesHandler 보다 IssueResponsesHandler가 나아보이나요?
| if !GlobalState.instance.isLoggedIn { | ||
| let loginViewController = LoginViewController.viewController | ||
| DispatchQueue.main.asyncAfter(deadline: .now() + 0.0, execute: { [weak self] in | ||
| self?.window?.rootViewController?.present(loginViewController, animated: false, completion: nil) |
There was a problem hiding this comment.
여기야 말로 unowned로 써도 되겠네요?
아니면... 이렇게 회피? ㅋㅋㅋ
UIApplication.shared.delegate?.window?.rootViewController?.present(loginViewController, animated:false, completion:nil)| print(issue) | ||
| self.createdIssue = issue | ||
| self.performSegue(withIdentifier: "UnwindToIssues", sender: self) | ||
| case .failure(_): |
| static let tokenKey = "token" | ||
| static let ownerKey = "owner" | ||
| static let repoKey = "repo" | ||
| static let reposKey = "repos" |
| var token: String? { | ||
| get { | ||
| let token = UserDefaults.standard.string(forKey: constants.tokenKey) | ||
| return token |
| "body": body, | ||
| "state": state.display, | ||
| "user": ["id": user.id, "login": user.login, "acatar_url": (user.avatarURL?.absoluteString ?? "")] | ||
| ] as [String : Any] |
There was a problem hiding this comment.
그리고 결국 타입이 [String:Any] 라면 변수에 적어주는게 더 좋겠네요.
vardict:[String:Any]=["id": id,"number": number,"title": title,"comments": comments,"body": body,"state": state.display,"user":["id": user.id,"login": user.login,"acatar_url":(user.avatarURL?.absoluteString ??"")]]| enum State: String { | ||
| case open = "open" | ||
| case closed = "closed" | ||
| case none = "none" |
There was a problem hiding this comment.
String 을 상속받고 case 와 rawValue 가 같으면 rawValue 따로 안 써도 됩니다.
enumState:String{case open
case closed
case none
}| switch self { | ||
| case .open: return "opened" | ||
| case .closed: return "closed" | ||
| default: return "-" |
| static var cellFromNib: IssueCell { | ||
| get { | ||
| return Bundle.main.loadNibNamed("IssueCell", owner: nil, options: nil)?.first as! IssueCell |
There was a problem hiding this comment.
오류날 일은 없겠지만... 그래도 as!는 위험하니
guardlet cell =Bundle.main.loadNibNamed("IssueCell", owner:nil, options:nil)?.first as?IssueCellelse{assertionFailure()returnIssueCell()}
return cell| } | ||
| } | ||
| func update(data issue: Model.Issue) { |
| final class IssueCommentCell: UICollectionViewCell, CellProtocol { | ||
| @IBOutlet var bodyLabel: UILabel! |
| @IBOutlet var commentTextField: UITextField! | ||
| var owner: String = "" | ||
| var repo: String = "" |
There was a problem hiding this comment.
빈줄이 IBOutlet 두개 사이가 아니라 owner 와 commentTextField 사이에 들어가는게 더 보기 좋을 것 같네요
| var owner: String = "" | ||
| var repo: String = "" | ||
| var issue: Model.Issue! | ||
| var headerSize: CGSize = CGSize.zero |
| @IBAction func sendButtonTapped(_ sender: Any) { | ||
| let comment = commentTextField.text ?? "" | ||
| API.createComment(owner: owner, repo: repo, number: issue.number, comment: comment) { [weak self] (dataResponse: DataResponse<Model.Comment>) in | ||
| guard let `self` = self else { return } |
There was a problem hiding this comment.
이거에 대한 의견도 많죠.
전 self는 안 쓰자는 주의 ㅋ
[weak self] 를 놓쳤을때 찾기가 쉽지 않아서..
| default: | ||
| assert(false, "Unexpected element kind") |
There was a problem hiding this comment.
assertionFailure("Unexpected element kind")| } | ||
| override func prepare(for segue: UIStoryboardSegue, sender: Any?) { | ||
| if let detailViewController = segue.destination as? IssueDetailViewController,let issue = sender as? Model.Issue { |
There was a problem hiding this comment.
여기서는 segue.identifier 인가로 비교하는게 좋지 않나요?
There was a problem hiding this comment.
분기의 목적보다는 까려는 목적? 어케 생각하시나요?
| case UICollectionElementKindSectionHeader: | ||
| assert(false, "Unexpected element kind") | ||
There was a problem hiding this comment.
이렇게 사용하시면 release 빌드에서 오류납니다.
assert외에 다른 문장이 없으면 항상 break를 같이 넣어주세요
| estimatedLayout[key] = nil | ||
| } else { | ||
| estimatedLayout = [:] | ||
| } |
There was a problem hiding this comment.
개인 취향
guardlet key = indexPath else{ estimatedLayout =[:]return}estimatedLayout[key]=nil| func estimateLayoutAttributes(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes { | ||
| if layoutAttributes.isHidden { | ||
| return layoutAttributes | ||
| } |
There was a problem hiding this comment.
guard layoutAttributes.isHidden ==falseelse{return layoutAttributes }| if needRefreshDatasource { | ||
| datasource = [] | ||
| needRefreshDatasource = false | ||
| } |
There was a problem hiding this comment.
이거야 말로 guard를 써야 할때
guard needRefreshDatasource ==trueelse{return}
datasource =[]
needRefreshDatasource =false| var page: Int = 1 | ||
| var canLoadMore: Bool = true | ||
| fileprivate var estimatedSizes: [IndexPath: CGSize] = [:] | ||
| fileprivate let estimateCell: CellType = CellType.cellFromNib |
There was a problem hiding this comment.
멤버변수 선언이 정신이 없네요.
accessor 별로 분류 하거나 기능별로 분류하거나 뭔가 기준이 있으면 좋을 것 같아요
| var api: ((Int, @escaping IssueResponsesHandler) -> Void)? | ||
| func loadMore(indexPath: IndexPath) { | ||
| guard indexPath.item == datasource.count - 1 && !isLoading && canLoadMore else { return } |
| } | ||
| func load() { | ||
| guard isLoading == false else {return } |
| func load() { | ||
| guard isLoading == false else {return } | ||
| isLoading = true | ||
| api?(page, {[weak self] (response: DataResponse<[Item]>) -> Void in |
There was a problem hiding this comment.
api?(page){[weak self](response:DataResponse<[Item]>)->Void in| canLoadMore = false | ||
| loadMoreCell?.loadDone() | ||
| } |
| 가져온 사이즈를 인덱싱. | ||
| 그 사이즈를 리턴. | ||
| */ |
| @IBAction func unwindFromRepos(_ segue: UIStoryboardSegue) { | ||
| if let reposViewController = segue.source as? ReposViewController, let (owner, repo) = reposViewController.selectedRepo { |
| GlobalState.instance.token = "" | ||
| let loginViewController = LoginViewController.viewController | ||
| DispatchQueue.main.asyncAfter(deadline: .now() + 0.0, execute: { [weak self] in | ||
| self?.present(loginViewController, animated: true, completion: nil) |
There was a problem hiding this comment.
DispatchQueue.main.asyncAfter(deadline:.now()+0.0){[weak self] in| return .put | ||
| case .repoIssues, | ||
| .issueDetail | ||
| : |
There was a problem hiding this comment.
API는 한개씩 추가되니까 아래줄에 하나씩만 추가하려고요
| let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height) | ||
| UIGraphicsBeginImageContext(rect.size) | ||
| if let context = UIGraphicsGetCurrentContext() { |
| } | ||
| typealias IssueResponsesHandler = (DataResponse<[Model.Issue]>) -> Void | ||
| static func repoIssues(owner: String, repo: String) -> (Int, @escaping IssueResponsesHandler) -> Void { |
There was a problem hiding this comment.
API. IssueResponsesHandler 보다 IssueResponsesHandler가 나아보이나요?
| } | ||
| } | ||
| func update(data issue: Model.Issue) { |
| } | ||
| override func prepare(for segue: UIStoryboardSegue, sender: Any?) { | ||
| if let detailViewController = segue.destination as? IssueDetailViewController,let issue = sender as? Model.Issue { |
There was a problem hiding this comment.
분기의 목적보다는 까려는 목적? 어케 생각하시나요?
| return .put | ||
| case .repoIssues, | ||
| .issueDetail | ||
| : |
There was a problem hiding this comment.
API는 한개씩 추가되니까 아래줄에 하나씩만 추가하려고요
reqeust