2022년 9월 23일 금요일

라즈베리파이-노트북으로 화면 출력하고 연결하기


라즈베리파이와 노트북이 같은 와이파이 이거나 랜케이블로 연결되어있을 가능함 

사용보드 : 라즈베리파이 3 모델 B + 


Step 1 Raspberry Pi Imager 

마이크로 sd 카드에 라즈베리 파이 운영체제 인스톨하기 https://www.raspberrypi.com/software/ 


호스트네임 설정 체크 : raspberrypi.local 

SSH 사용 체크 

사용자 이름 비밀번호 설정 체크 

사용자이름 : Pi

비밀번호

무선 LAN 설정 체크 

SSID: 노트북이 연결되어있는 와이파이  

비밀번호 : 와이파이 비밀번호 


Step 2 PuTTY 


$ ifconfig  

eth0: inet부분은 노트북과 라즈베리파이가 랜선으로 연결할 필요

wlan0: inet 부분은 노트북과 라즈베리파이가 와이파이로 연결할 필요 

$ sudo raspi-config 

구성도구 (configuration tool) 


Step 3 xming 

PuTTY 연결되어 있을 GUI (그래픽 인터페이스) 필요할 사용 

Category : Connection > SSH > X11 > X11 forwarding, Enable X11 forwarding 체크 


$ pcmanfm 

파일편집기 


Step 4 xrdp 

라즈베리파이 운영체제 GUI(그래픽 인터페이스

윈도우 원격제어 앱을 통해 사용 


$ sudo update 

$ sudo upgarde 

$ sudo apt-get install xrdp



Step 5 윈도우 원격 데스크톱 연결 

위에서 확인한 라즈베리파이 IP 입력하여 접속 

xrdp 로그인 



참고 

https://wikidocs.net/3197

https://blog.xcoda.net/94

https://blog.naver.com/nohdi1991/222866075639

2019년 11월 13일 수요일

가로방향 스크롤뷰(Horizontal ScrollView)


상황 
  • 콜렉션뷰를 사용하지 않고 스크롤뷰를 이용해 가로방향 스크롤 이미지뷰 구성 (programmatically) 
방법
  • 코드 상에서 스크롤뷰에 이미지뷰 생성 
  • 이미지 갯수에 맞춰서 스크롤뷰 콘텐츠 사이즈 구성 
  • horizontal indicator 숨김 
  • paging 처리 
내용


설명 
  • X포지션을 스크롤뷰의 프레임 넓이에 비례하도록 함 
  • leftSpace 는 전체 스크롤뷰 프레임 넓이에서 이미지뷰 사이즈(여기서는 2/3)를 뺀 절반 값 
  • 이미지뷰의 프레임에서 x값은 xPosition + 왼쪽 여백으로 지정 
  • 스크롤뷰의 콘텐츠 사이즈는 상위뷰(슈퍼뷰 혹은 콘텐츠뷰, 바디뷰) 프레임 넓이의 배수로 설정 
  • 스크롤뷰에 이미지뷰를 추가함 

2019년 9월 22일 일요일

쓸어내려 모달 해제하기 (Drag Down to Dismiss Modal)

상황 
  • 모달로 뷰를 하나 띄웠을 때 아래로 끌어당겨 모달을 해제하려고 함 
  • 이때 잡아 당길 경우 모달로 띄워진 뷰가 아래로 끌어내려지면서 뒤에는 이전 뷰가 보임 
  • 터치를 끝냈을때 (손을 떼었을 때 ) 100~200포인트로 설정하여 그 이하는 다시 모달 뷰가 화면을 덮고 그 이상은 dismiss 함 
방법 
  • PanGestureRecognizer를 이용함 
  • 최초 터치 시작점을 설정하고, 상태값이 변할 경우 y 값만큼 프레임을 내려 뷰를 끌어 당김 
  • 터치가 끝났을 때 (손을 떼었을때) 최초 터치 시작점에서 마지막 지점까지 y 값의 변화정도를 계산하여 150 보다 클 경우 화면을 내리고(모달을 해지하고) 그 이하일 경우 다시 모달 뷰로 화면을 덮음 
과정 
  • 스토리보드에서 모달을 세그웨이로 지정할 경우, 스토리보드 상에서 세컨드 뷰 컨트롤러의 Presenstation 항목을 Full Screen이 아닌 Over Full Screen으로 변경함( 화면을 끌어당겼을 때 첫번째 뷰가 그 밑에 깔림) 
  • 만약 코드 상에서 performSegue 등으로 화면을 전환할 경우 
  • 또는 이처럼 모달을 띄울 경우 guard let modalToThirdView = self.storyboard?.instantiateViewController(withIdentifier: "ThirdView") else { return }
  • awakeFromNib에서 모달스타일을 overFullScreen으로 변경해 줌
내용





참고: 1.


화면

아래로 당겨서 뷰 내리기 (Pull Down to Dismiss View)



상황
  • 테이블뷰나 웹뷰처럼 스크롤뷰가 작동하는 경우 아래로 당겨서 뷰를 해제하려고 함 (테이블 뷰는 스크롤뷰를 상속받았고, WKWebView는 scrollView가 프로퍼티로 존재함) 
방법 
  • UIPanGestureRecognizer를 이용함 
  • 중복되는 제스처를 처리하기 위해 UIGestureRecognizerDelegate를 채택 후 위임
내용


추가확인사항 
  • sender.isEnabled = false , sender.isEnabled = true 이처럼 불리언 값을 한번 변경해주지 않으면 해당 위치에 로그가 연속적으로 찍힘
  • 웹뷰일 때는 웹뷰의 스크롤뷰 프로퍼티로 접근함 if recognizer.state == .began && webView.scrollView.contentOffset.y == 0 { (…)} 
  • 뷰가 사라지는 시점이 터치를 끝낸 시점이 아니라 애니메이션 효과가 도중에 발생함 
참고: 1

길게 터치하여 팝업뷰 띄우기(LongPressGuesture to Show PopupView)

상황
  • 이미지뷰 하나를 탭하면( 짧게 터치하면 Push 혹은 전체화면 모달로 화면을 전환하고, 길게 터치할 경우 팝업뷰를 띄우고자 함) 
방법 
  • 팝업뷰를 윈도우 바깥으로 이동함 (PopUpView CenterY와 SuperView Center Y의 constant를 1000으로 지정) 
과정 
  • 이미지뷰에 제스쳐가 인식할 수 있도록 isUserInteractionEnabled 값을 True로 설정 
  • 이미지뷰에 탭 재스처로 뷰컨트롤러를 Push함
  • 팝업뷰와 슈퍼뷰의 Center Y 컨스트레인트를 아울렛으로 지정하고 롱 프레스 제스쳐 실행시 constant를 0으로 변경 및 애니메이션 효과 추가 
내용 



참고 1, 2

네비게이션바와 관련된 스와이프 제스쳐

상황 
  • 네비게이션 컨트롤러를 임베드할 경우 Push로 뷰가 쌓임.(스택) 
  • 이때 네비게이션 바가 숨겨졌을 때 뒤로 가게되는 스와이프 기능이 동작하지 않는 경우가 있음 
방법 
  • 네비게이션 바를 숨기는 두가지 다른 방법에 의한 차이로 추정됨 
내용 
  • 네비게이션 바가 다음과 같은 방법으로 숨겨질 경우 뒤로가는 스와이프 동작에 문제 없음 
self.navigationController?.navigationBar.isHidden = true 
  • 다음 방법의 경우는 작동하지 않아 코드를 한 줄 추가 함 
self.navigationController?.isNavigationBarHidden = true
self.navigationController?.interactivePopGestureRecognizer?.delegate = nil

참고: 1

화면가장자리를 스와이프 하여 화면 전환하기 (EdgePanGesture for ViewTransition)

상황 
  • 탭바 기반의 앱에서 전체매뉴 탭 혹은 설정화면 탭의 경우 탭바를 숨김 
  • 이때 상단의 네비게이션 바의 왼쪽 아이템으로 탭 전환이 가능하지만 화면 왼쪽 가장자리 끝부분을 스와이프하여 첫번째 탭으로 이동하고자 함 
방법 
  • UIScreenDegePanGuestureRecognizer를 이용 
내용
    func setEdgePanGesture() {
        let edgePanGesture = UIScreenEdgePanGestureRecognizer(target: self, action: #selector(moveToFirstTab(_:)))
        edgePanGesture.edges = UIRectEdge.left
        view.addGestureRecognizer(edgePanGesture)
    }
    
    @objc func moveToFirstTab(_ recognizer: UIScreenEdgePanGestureRecognizer) {
        if recognizer.state == .recognized {
            self.tabBarController?.selectedIndex = 0
        }
    }
추가 확인 사항 
  • 화면전환이 애니메이션이 없이 이루어짐. 터치 종료시점(손가락을 뗀 시점)에서 애니메이션과 함께 탭이 전환되려면 EdgePanGesture가 아닌 PanGesture가 필요할 것 같음 

웹뷰에서 스냅샷 찍기 (Take a SnapShot in WKWebView)

상황 
  • 웹뷰를 로드한 직후, 웹뷰를 스냅샷을 찍어 이미지로 저장하고자 함 

방법 
  • WKNavigationDelegate 를 채택한뒤 webView(_:didFinish:) 메서드에 스냅샷 함수를 호출 
과정 
  • WKNavigationDelegate 채택 및 위임 설정 
  • webView(_:didFinish:) 메서드가 웹뷰가 로드되면 작동함 
  • snapshot 함수 호출 
  • 이미지 뷰 및 레이블에 해당 이미지와 타이틀 설정 
내용
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        let config = WKSnapshotConfiguration()
//        config.rect = CGRect(x: 0, y: 0, width: 150, height: 150)
        config.snapshotWidth = 150
        webView.takeSnapshot(with: config) { (snapImage, error) in
            if error == nil {
                guard let myImage = snapImage else { return }
                self.imageView.image = myImage
                
                guard let guardTitle = self.webView.title else { return }
                self.webViewLabel.text = guardTitle
            }
        }
    }

이슈
  • 만약 웹뷰가 숨김 상태라면 (webView.isHidden = true) 시뮬레이터에서는 스냅샷이 작동하지만 디바이스, 기기에서는 작동하지 않았다. (Xcode 10.2, iOS 12.4) 웹뷰를 화면 밖으로 꺼내놓아 작동시킴 (윈도우 밖에 위치시킴) 
더 확인해 볼 내용 
  • WKUIDelegate 와 WKNavigationDelegate의 작동 내용 
  • webView(_:createWebViewWith:for:windowFeatures:) 로 새 웹뷰를 만드는 과정
API Reference: 

참고: 1, 2

웹뷰에서 앞, 뒤 페이지로 이동하기(goForward & goBack in WKWebView)

설명 및 의도 
  • 웹뷰 네비게이션에서 앞, 뒤로 이동할 때 쓸어넘김으로 기능 구현하고자 함 
방법 
  • goBack(), goForward() 함수로 구현 (버튼액션이나 혹은 핸들러 이용시)
  • 또는 웹뷰의 프로퍼티 설정 값 변경으로 구현 
  • 또는 스와이프 제스쳐로 구현 
내용
self.webView.allowsBackForwardNavigationGestures = true

또는 스와이프 제스쳐 (UIGestureRecognizerDelegate 프로토콜 채택) 

이슈 
  • 뒤로가는 스와이프 동작은 방향을 .left 가 아닌 .right 로 지정( 터치를 오른쪽으로 이동하므로)
  • 제스쳐가 중복이 될경우 동작하지 않는 상황 발생하여 딜리게이트 메서드 추가해야 함 (중복된 제스쳐 허용)
더 확인해볼 내용 
  • func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool

Asks the delegate if a gestrue recognizer should require another gesture recognizer to fail. 
  • func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool

Asks the delegate if a gesture recognizer should be required to fail by another gesture recognizer. 
  • func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool

Asks the delegate if two gesture recognizers should be allowed to recognize gestures simultaneously. (제스쳐 두개가 동시에 인식되는지 여부) 

API Reference 

스테이터스 바에 블러 뷰 얹기 (Status Bar added Blur View)


상황 
  • 웹뷰의 top과 bottom을 Safe Area.top,  Safe Area.Bottom 이 아니라 SuperView의 top과 bottom으로 맞춤 
  • 네비게이션바가 숨김처리 되었을 경우 스테이터스 바 뒤로 컨텐츠가 겹쳐 보임
  • 스테이터스 바에 블러뷰를 얹고자 함  
방법 
  • 블러효과를 가진 비쥬얼이펙트뷰를 생성 (블러 효과 prominent로) 
  • 코드상에서 오토레이아웃 지정, Programmatic AutoLayout (top, left, right는 view에 맞추고, 높이를 스테이터스바에 맞춤)
  • 웹뷰와의 경계를 표시하기 위해 레이어로 라인을 그림 (Draw Bottom Line on View) 
내용 
        let blurEffect = UIBlurEffect(style: .prominent)
        let statusBarBlurView = UIVisualEffectView(effect: blurEffect)
        self.view.addSubview(statusBarBlurView)
        
        statusBarBlurView.translatesAutoresizingMaskIntoConstraints = false
        statusBarBlurView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        statusBarBlurView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        statusBarBlurView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        statusBarBlurView.heightAnchor.constraint(equalToConstant: UIApplication.shared.statusBarFrame.height).isActive = true
        
        statusBarBlurView.layer.borderWidth = 0.25

화면