Skip to content
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

[Pigbag] Step04 - 2 image추가 로직, View Factory 리팩토링 #106

Open
wants to merge 12 commits into
base: pigbag
Choose a base branch
from

Conversation

piggyse
Copy link

@piggyse piggyse commented Mar 18, 2022

  • 작업목록
  • ViewFactory Static으로 처리
  • Plane과 대비되는 Image파일 생성
  • PHPicker를 이용 앨범에서 사진 가져오기.
  • 가지고 온 사진 화면에 그리기(여러장 가능)

  • 키워드: UTType, NSItemProviderReading, MiME

  • 고민 및 해결

  • UIView를 상속하는 Custom View를 만들때 생성자에는 우리가 원하는 값 모두를 매개변수에 넣을 수 없기때문에(required init 때문에)
    어떻게 하면 View를 초기에 생성할때 모든 속성을 다 주고 만들 수 있을까? 고민이 있었습니다.
    고민 끝에, 결국 생성을 담당하는 곳은 Factory이기에 처리를 Factory에 맡겨야 겠다는 생각이 들었고,
    새로운 타입을 만들고 억지로 Protocol을 만들어서 엮기보다는 UIView자체를 이용하자는 결론에 이르렀습니다.
    Factory에서 UIView를 리턴을 하되 함수의 매개변수에는 모델들이 채택하는 프로토콜을 넣었습니다.
    적절한 함수명과함께 static메서드 별로 다른 사각형뷰를 리턴을 한다면 각각의 타입을 만든것이랑 동일 한 효과를 낼수 있다고 생각했습니다.
    이후, ViewController에서 사용할때 typealias를 이용해서 UIView라는 네이밍보다는 좀더 구체적인 네이밍을 주려고 시도했습니다.

  • 고민 및 시도

  • 이번 Step을 진행하면서 기존에 있던 로직과 겹치는 부분이 상당수 있다는 것을 확인했습니다.(뷰에서 사각형 선택,테두리바꾸기 등등..)
    현재 제 로직에서 위처럼 부분들을 추상화 하려면 Dictaionary의 Key값을 프로토콜과 같은 형태로 바꾸어야 할것 같아 시도 해봤으나
    잘 되지 않았습니다. 조금 더 고민해야 될것 같습니다.

let key = Point(x: x, y: y)
func addRectangle() -> PlaneRectangle{
let rect = RectangleFactory.makePlaneRectangle()
rectangles.append(rect)
Copy link
Author

Choose a reason for hiding this comment

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

Plane이 생성의 역할을 하는게 맞다고 생각해 Factory를 이용해 생성을 했습니다.
다만, 이렇게 인스턴스를 이용한게 아닌 Static메서드를 이용해서 생성을 하는 경우 Plane은 Factory를 몰라도 된다
성립이 되는지는 잘 모르겠습니다..

Copy link
Contributor

Choose a reason for hiding this comment

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

Static 메소드를 사용하면 오히려 더 RectangleFactory 타입과 분리하기 어려워지죠. 다형성도 동작하지 않으니까요
그래서 RectangleFactory를 대신할 프로토콜로 접근해보는 게 좋습니다.

Copy link
Author

Choose a reason for hiding this comment

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

프로토콜을 사용해서 다시 시도해보겠습니다!

self?.image.addRectangle(imageData: data)
}
}
}
Copy link
Author

Choose a reason for hiding this comment

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

한번에 여러 사진을 가지고 오기위해 함수들을 이용해서 데이터를 가지고 오려 시도했습니다.

let x = Double(touch.location(in: self.view).x)
let y = Double(touch.location(in: self.view).y)
let point = Point(x: x, y: y)
plane.findSeletedRectangle(point: point)
Copy link
Author

Choose a reason for hiding this comment

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

사각형의 origin대신 좌표값을 넘겨주는 것으로 수정했습니다.

Copy link
Contributor

@godrm godrm left a comment

Choose a reason for hiding this comment

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

Plane과 Image의 관계를 꼭 개선해보셨으면 합니다.

Comment on lines +13 to +28
static func makePlaneRectangleView(sourceRectangle: Rectangleable) -> UIView {
let source = sourceRectangle as! PlaneRectangle
let rectangleView = UIView(frame: .zero)
rectangleView.frame = setUpFrameWithRectangle(source)
rectangleView.backgroundColor = setupBackgroundColor(rgb: source.rgb, alpha: source.alpha)
return rectangleView
}

//IamgeView
static func makeImageRectangleView(sourceRectangle: Rectangleable) -> UIImageView {
let source = sourceRectangle as! ImageRectangle
let rectangleView = UIImageView(frame: .zero)
rectangleView.frame = setUpFrameWithRectangle(source)
rectangleView.image = setupImage(imageData: source.imageData)
return rectangleView
}
Copy link
Contributor

Choose a reason for hiding this comment

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

다음에는 여기서 return 타입을 추상화해 보는 것도 좋은 시도가 될 것 같습니다.
UIView와 UIImage를 생성하지만 받는 쪽에서 구체 타입을 최소한으로 알고 다룰 수 있도록 하는거죠.

Copy link
Author

Choose a reason for hiding this comment

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

넵 !시도해보겠습니다

import PhotosUI

typealias RectangleView = UIView
typealias imageURLData = Data
Copy link
Contributor

Choose a reason for hiding this comment

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

타입 이름은 Alias를 해도 대문자로 표기해주세요

Comment on lines 18 to +19
private var plane = Plane()
private var image = Image()
Copy link
Contributor

Choose a reason for hiding this comment

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

아직 Image라는 타입을 살펴본 건 아니지만 local reasoning을 해보자면, plane과 대등하게 이미지만 관리하는 타입처럼 보입니다.
Plane에서 통합해서 관리하는 것은 어떨까요?

Comment on lines +200 to +220
private func configureImageNotificationCenter() {
NotificationCenter.default.addObserver(
self,
selector:#selector(addImageRectangleView),
name: Image.NotificationName.didAddRectangle,
object: image)

NotificationCenter.default.addObserver(
self,
selector: #selector(findSelectedImageRectangle),
name: Image.NotificationName.didFindRectangle,
object: image )

NotificationCenter.default.addObserver(
self,
selector: #selector(changeIamgeAlpha),
name: Image.NotificationName.didchangeRectangleAlpha,
object: image )


}
Copy link
Contributor

Choose a reason for hiding this comment

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

여기만 들여쓰기가 좀 다르네요.

Comment on lines +223 to +232
guard let newImageRectangle = notification.userInfo?[Image.UserInfoKey.addedRectangle] as? ImageRectangle else { return }

DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
let rectangleView = RectangleViewFactory.makeImageRectangleView(sourceRectangle: newImageRectangle)
self.imageRectangleViews[newImageRectangle.imageData] = rectangleView

self.view.addSubview(rectangleView)
self.bringButtonViewToFront()
}
Copy link
Contributor

Choose a reason for hiding this comment

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

이렇게 되면 상당 부분 addRectangleView()와 비슷한 코드가 중복되지 않나요?
RectangleViewFactory도 같이 쓰고 self.view.addSubview()도 동일한 것 같은데, 일반화시킬 수 있는 부분은 없을까요?

Comment on lines +238 to +253
seletedRectangleView?.layer.borderWidth = .zero

guard let seletedRectangle = notification.userInfo?[Image.UserInfoKey.foundRectangle] as? ImageRectangle else { return }

let rectangleView = self.imageRectangleViews[seletedRectangle.imageData]
self.seletedRectangleView = rectangleView

seletedRectangleView?.layer.borderWidth = 2.0
seletedRectangleView?.layer.borderColor = UIColor.blue.cgColor
seletedRectangleView?.layer.borderColor = UIColor.red.cgColor

self.detailView.alphaLabel.text = "\(seletedRectangle.alpha?.value ?? 0.0)"
self.detailView.alphaSlider.value = seletedRectangle.alpha?.value ?? 0.0
self.detailView.alphaLabel.text = "\(seletedRectangle.alpha.value)"
self.detailView.alphaSlider.value = seletedRectangle.alpha.value

self.detailView.backgroundColorButton.setTitle("\(seletedRectangle.rgb?.hexValue ?? "")", for: .normal)
self.detailView.backgroundColorButton.setTitle("NONE", for: .normal)
self.detailView.backgroundColorButton.alpha = 0.3
self.detailView.backgroundColorButton.isEnabled = false
Copy link
Contributor

Choose a reason for hiding this comment

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

이 함수도 findSelectedRectangle와 상당부분 비슷하지 않나요?

Comment on lines 11 to +14
class Image {

private var rectangles:[Point:ImageRectangle] = [:]
private var selectedRectangle:ImageRectangle?
private var imageRectangles:[ImageRectangle] = []
private var selectedImageRectangle:ImageRectangle?
Copy link
Contributor

Choose a reason for hiding this comment

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

아래 코드들을 자세히 보지 않아도 상당 부분 Plane과 겹치는 게 보이는 것 같습니다.
PlaneRectangle을 따로 두지 않고 ImageRectangle을 추상화해서 한꺼번에 다루도록 개선해보세요

let key = Point(x: x, y: y)
func addRectangle() -> PlaneRectangle{
let rect = RectangleFactory.makePlaneRectangle()
rectangles.append(rect)
Copy link
Contributor

Choose a reason for hiding this comment

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

Static 메소드를 사용하면 오히려 더 RectangleFactory 타입과 분리하기 어려워지죠. 다형성도 동작하지 않으니까요
그래서 RectangleFactory를 대신할 프로토콜로 접근해보는 게 좋습니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants