티스토리 뷰

안녕하세요. 

저번에 말씀드렸던 것처럼 아래 글 2탄으로 돌아왔습니다. 

2024.04.22 - [iOS개발/Swift 기능] - Swift 패턴 잠금 만들기 (with. CCGestureLock )

 

Swift 패턴 잠금 만들기 (with. CCGestureLock )

안녕하세요. 오늘은 오랜만에 재밌어 보이는 기능을 들고 왔습니다. 혹시 이런 거 보신 적 있나요? (패턴잠금, 영어로는 Gesture Lock 등 부르는 표현은 다양합니다.) 이거 한번 만들어 보고 싶었는

world-of-larooly.tistory.com

 

그래서 오늘 할거는 뭐냐 

바로 이겁니다 

저번 꺼랑 뭔가 다르죠?

자 저번 포스트의 연장선이기 때문에

라이브러리를 연결하는 방법은 이전 포스트를 참고해주세요. 

 

추가로 이번에 제가 준비한 건 버튼에 쓰일 이미지 3개입니다.  

저는 인터넷에 있는 이미지 3개를 다운 받아서 준비했습니다. 

 

이런 식으로 넣어주면 준비완료입니다!

귀엽죠?

이제 저번에 데려온(?) 라이브러리를 조금 수정해서 

이미지를 사용할 수 있게 바꿀 겁니다.

 

저번에는 import UIKit 만 잔뜩 해 주었지만

이번에는 실제 코드를 좀 수정해주셔야합니다. 

- 귀찮으시거나 따라하기 어려우시면 아래 파일을 받은 후 교체해주세요. 

CCGesture_이미지_추가.zip
0.01MB

 

지난번에 추가해 주신 부분에 보시면 

저렇게 Classes 라는 폴더가 있을겁니다.

선택된 부분이 보이시나요?

CCGestureLockSensor, CCGestureLock를 조금 수정해서 사용할겁니다. 

 

먼저 CCGestureLockSensor 부터 수정할께요. 

(귀찮으신 분들은 올려드린 파일로 교체해서 사용하셔도 됩니다.)

 

 

1. CCGestureLockSensor

  • SensorAppearance 속성 추가 및 init /update 함수 추가 
class RingAppearance: Appearance {
            
    var radius: CGFloat
    var width : CGFloat
    var color : UIColor
    var backImg : UIImage? // 이미지 추가

    init(radius: CGFloat, width: CGFloat, color: UIColor) {
        self.radius = radius
        self.width = width
        self.color = color
    }
    // 이미지 관련 추가
    init(radius: CGFloat, width: CGFloat, color: UIColor,image : UIImage?) {
        self.radius = radius
        self.width = width
        self.color = color
        self.backImg = image
    }

    func update(radius: CGFloat?, width: CGFloat?, color: UIColor? ) {
        self.radius = radius ?? self.radius
        self.width = width ?? self.width
        self.color = color ?? self.color
    }
    // 이미지 관련 추가 
    func update(radius: CGFloat?, width: CGFloat?, color: UIColor? , image : UIImage? ) {
        self.radius = radius ?? self.radius
        self.width = width ?? self.width
        self.color = color ?? self.color
        self.backImg = image ?? self.backImg
    }
}
  • update 함수 수정 
func update(type: SensorAppearance.RingType, radius: CGFloat?, width: CGFloat?, color: UIColor? ,backImg : UIImage?) {
//        appearance[type].update(radius: radius, width: width, color: color) // 이미지 처리 추가
    appearance[type].update(radius: radius, width: width, color: color,image: backImg)

    image = createSensorImage()

}
  • 이미지 처리 함수 추가 (createSensorImage 에서 사용 할 함수입니다.)
    • 그냥 이미지를 넣으면 크기가 굉장히 크게 나옵니다.
    • 그래서 width 를 이용해 크기를 조절 가능하게 하기 위해 추가해줍니다. 
    • createSensorImage 함수 근처에 넣어주세요.
// 이미지 크기 관련 함수 추가
private func resizeImage(image : UIImage , width : CGFloat)-> UIImage?{

    let scale = width / self.size!.width
    let newHeight = self.size!.height * scale

    let size = CGSize(width: width, height: newHeight)
    let render = UIGraphicsImageRenderer(size: size)
    let renderImage = render.image { context in
        image.draw(in: CGRect(origin: .zero, size: size))
    }

    let rect = CGRect(x: (self.size!.width-width)/2, y: (self.size!.height-newHeight)/2, width: width, height: newHeight)

    let newImage = renderImage
    UIGraphicsBeginImageContextWithOptions(self.size!, false, 1.0)
    newImage.draw(in: rect)
    let resizeImg = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return resizeImg

}
  • createSensorImage 함수 수정
    • 처음 부분 주석으로 감싸진 부분만 추가해주시면 됩니다.
 private func createSensorImage() -> UIImage? {
        // 이미지 처리를 위한 함수 추가
        // 여기서부터
        if(appearance.outerRing.backImg != nil && self.size != nil){
            return resizeImage(image: appearance.outerRing.backImg!, width: appearance.outerRing.width)
        }
        if(appearance.innerRing.backImg != nil && self.size != nil){
            return resizeImage(image: appearance.innerRing.backImg!, width: appearance.innerRing.width)
        }
        //여기까지 추가
        if let size = self.size {
            
            UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
            if let context = UIGraphicsGetCurrentContext() {
                
                var image: UIImage?
                context.saveGState()
                .
                .
                .

 

 

2. CCGestureLock

  • setSensorAppearance 함수 수정 
public func setSensorAppearance(type: RingType,
    radius: CGFloat? = nil,
    width:  CGFloat? = nil,
    color:  UIColor? = nil,
    image : UIImage? = nil,forState state: GestureLockState) {
    // 이미지 관련 변수 추가
    guard radius != nil || width != nil || color != nil || image != nil else {
        return
    }
    if let setting = appearance.settings[state] {
        setting.sensor.update(type: type, radius: radius, width: width, color: color, backImg: image)
    }
    collectionView.reloadData()

}

 

참고로 여기는 이거 하나만 고쳐주시면 됩니다. 

그럼 원래 화면(UIViewController)로 돌아와서 적용해봐야겠죠? 

* 적용 방법

lockView.setSensorAppearance(type: .outer,width: 25,image: UIImage(named: "nor_btn"), forState: .normal)

 

* UIViewController 적용 코드 예시

override func viewDidLoad() {
    super.viewDidLoad()

    self.setGestureLock()
    self.setActionGesture()
}
@IBAction func resetGesture(_ sender: Any) {
    self.lockView.gestureLockState = .normal // 리셋
}
func setGestureLock(){
    // 갯수 설정 (가로 , 세로) 
    lockView.lockSize = (numHorizontalSensors: 3, numVerticalSensors : 4)
	// 이미지 및 사이즈 설정
    lockView.setSensorAppearance(type: .outer,width: 50,image: UIImage(named: "nor_btn"), forState: .normal)
    lockView.setSensorAppearance(type: .outer,width: 50,image: UIImage(named: "on_btn"), forState: .selected)
    lockView.setSensorAppearance(type: .outer,width: 50,image: UIImage(named: "off_btn"), forState: .error)

    // 여기는 선 색 
    lockView.setLineAppearance(width: 2, color: .blue,forState: .normal)
    lockView.setLineAppearance(width: 10, color: .green,forState: .selected)
    lockView.setLineAppearance(width: 10, color: .red,forState: .error)

}
func setActionGesture(){
    // 다 그린 후 액션 설정
    lockView.addTarget(self, action: #selector(gestureComplete), for: .gestureComplete)

}
@objc func gestureComplete(gestureLock : CCGestureLock){
    let lockNum = lockView.lockSequence
    print(lockNum)//[0, 3, 6, 9, 10, 11, 8, 5, 2, 7]
  
    let correct : [NSNumber] = [0,1,4,5]
    if(lockNum == correct){// 번호 맞음
        gestureLock.gestureLockState = .selected
    }else{ // 번호 틀림
        gestureLock.gestureLockState = .error
    }
}

 

이제 이렇게 하시면 

아래처럼 보이게 됩니다. 

귀엽죠?

참고로 중간 중간 초기화는 버튼 눌러서 한겁니다(자동X)

 

여기까지 CCGestureLock 을 이용해서 만들어 보았습니다.

개인적으로 원 말고 다양하게 사용해보고 싶어서 

시도해 본 건데 재밌는 것 같아요.

 

다른 분들에게 도움이 되었으면 좋겠네요. 

그럼 오늘도 파이팅입니다. 

댓글