2019년 2월 9일 토요일

macOS 에서 eclipse jee 와 CDT 동시에 설치 및 아이콘 변경 하기

요즘 회사에서 web 이나 서버 API 를 간간히 배우면 개발을 해야하기 때문에 spring을 이용하기 위해 vscode 부터 eclipse 까지 이것 저것 만저 보았다.

스프링 개발을 위해 eclipse jee를 설치 하고 잘 사용 하고 있는 상황 그런데 raspberry pi에 C 로 개발해야 할 일이 생겨서 eclipse CDT도 설치 해봐야 하는 상황이 발생 했다.


기존 설치되어 있는 eclipse jee에  CDT 플러그인을 install software 메뉴로 추가로 설치를 하면 하나의 이클립스가 java / c++ 모두 되는 IDE가 되는 것으로 보인다.

하지만 자바 프로젝트 워크 스페이스가 열리면서 무언가 화면은 C++ IDE 였다가, java IDE 였다가 하는 것이 맘에 안든다.

해서 eclipse jee 가 설치된 mac 머신에 새로 eclipse cdt를 설치 하기로 했다.

eclipse/cpp-2018-12 ,  jee-2018-12 로 나뉘어 설치 되게 된다.

하지만 아이콘이 같은 모양이라서 어떤게 java IDE인지 어떤게 c++ IDE인지 구분이 가지 않는다.



https://github.com/eclipse-cdt/cdt/blob/master/debug/org.eclipse.cdt.debug.application/icons/cc.icns
여기에서 C++ eclipse icns를 다운 받는다.

cc.icns 를 Eclipse.icns로 이름을 변경 하고

eclipse CDT 설치 경로에서 패키지 보기로 하여  Resource 디렉토리에 있는
Eclipse.icns에 복사하여 아이콘을 바꾼다.

어떤이유에서인지는 모르지만 실행전에는 dock에 아이콘이 변경 되지 않지만 실행중에는
변경되어 어떤것이 java인지 C++인지 구분이 된다.

이정도면 만족 한다.







2019년 1월 15일 화요일

visual studio code 로 spring maven project를 할때 너무 package does not exist로 밑줄이 많을떄

https://github.com/redhat-developer/vscode-java/issues/161

java linter 플러그인을 제거 해야 한다.

springframework.beans.factory.anotation 등등
멀쩡한 코드들이 빨간줄이 가는 문제가 있었다.

https://github.com/redhat-developer/vscode-java/issues/161의 답변중에 하나인
java linter 플러그인이 문제 인 듯 하다.

2019년 1월 12일 토요일

visual studio code로 java spring maven project 하기

java spring 은 eclipse로 작업하는게 일반적이다.

spring을 시작하는 입장에서 eclipse의 불편함이 개발에 어려움에 한 몫 하고 있다.

현업에서 가장 많이 사용 하는게 eclipse이니 사실 장점이 더 많을 수 있지만
eclipse는 느리고 macOS에서 다크 테마도 부자연 스럽고 맘에 들지 않는다.

하여 code 편집기로 자주 사용하는 vscode를 spring 개발에 이용하려 함이다.

이미 eclipse로 만들어진 spring maven 프로젝트 폴더를 vscode로 열어서 빌드및 tomcat debug가 가능 하도록 하는것이 목표이다.

MacOS 기준에서 테스트 하였다.


1. tomcat 설치 mac os
eclipse 개발 환경으로도 tomcat 설치는 필요하다.


http://igeniusdo.tistory.com/12
톰캣 버젼을 다운로드 받아서 /usr/local 폴더에  복사한다.
/Library/Tomcat 으로 심볼릭 링크를 걸어준다.

2. maven 설치
아파치 maven을 다운 받아서 /usr/local 에 복사한다.
https://maven.apache.org/install.html

cat .bash_profile 
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-9.0.1.jdk/Contents/Home

export PATH=/usr/local/apache-maven-3.6.0/bin:$PATH

위와 같이 JAVA홈과 maven PATH를 설정 한다.


3.vscode에 java 관련 플러그인 설치
https://code.visualstudio.com/docs/languages/java

여기에 언급한 플러그인을 몽땅 설치 한다.

이상태에서 eclipse spring maven project 폴더를 폴더 열기를 하면 다음과 비슷한 화면으로 로딩 된다

.


4.톰캣 서버 추가

TOMCAT SEVERS에서 +를 누른다음 /Library/Tomcat 폴더를 선택하여 tomcat 을 추가한다.
tomcat의 마우스 오른쪽 버튼을 눌러 Open Server Configuration을 선택 하여 server.xml을 편집 할 수 있다.  port 설정등을 할 수 있다.

5. 프로젝트 maven 빌드
MAVEN PROJECTS 에서 마우스 오른쪽 버튼으로 package를 선택 한다.

정상적으로 빌드가 끝나면 target 디렉토리에 .war 파일이 생성 된다.

6. tomcat 디버깅


디버깅도 잘 된다.




2018년 12월 14일 금요일

XCTest 에서 비동기 통신 class를 테스트를 하려면?

https://developer.apple.com/documentation/xctest/asynchronous_tests_and_expectations/testing_asynchronous_operations_with_expectations


위 링크를 보면 좋은 예제가 있다.


만일 네트워크 RESTFul API를 요청 하는 함수들 과
응답에 결과를 delegate로 호출 해주는 방법으로 만든 클래스가 있다면

이 class의 unit 테스트를 만들려면 testcase 함수 에서는 응답이 오기전에 XCAssertEqual()등의 메서드를 호출 할 수 없다. 네트워크 응답을 delegate로 받고 테스트가 진행 되어야 한다.


XCTest case 함수에서
XCTestExpectation 변수를 전역 변수로 만들고

테스트 케이스 함수에서 네트워크 요청 후
wait(for: [expectation], timeout: 10.0)
위와 같은 코드로 대기를 하게 한다.

XCAssertEqual() 메서드든 wait 코드 아래에 위치 하게 한다.

네트워크 클래스의 delegate 응답 결과를 처리 하는 protocol 메서드에서
expectation.fulfill() 을 호출 하여 대기를 풀어 준다.

그럼 wait이 풀리고 XCAssertEqual에서 테스트 판단이 이루어진다.

말로 설명한 TestCase 코드는 다음과 같다.

let expectation = XCTestExpectation(description: "Network API TEST")
    func testLogin() {
        // 1. given

        // 2. when
        network.login = Network.Login(aId: "choijh", aPassword: "1234567a")
        network.request(API: Network.API.Login, delegate: self)

        wait(for: [expectation], timeout: 10.0)

        // 3. then
        XCTAssertEqual( self.success, true, "Login success")
    }
    
    func testLoginFail() {
        // 1. given
        
        // 2. when
        network.login = Network.Login(aId: "choijh", aPassword: "a")
        network.request(API: Network.API.Login, delegate: self)
        
        wait(for: [expectation], timeout: 10.0)
        
        // 3. then
        XCTAssertEqual( self.success, false, "Login fail wrong password")

    }
    
    func onReceiveSuccessFail(_ success: Bool, api: Network.API) {
        self.success = success
        expectation.fulfill()

    }

2018년 10월 7일 일요일

Xcode에서 이미지 없이 둥근 버튼, 원 버튼 디자인 적용 하기

1. 다음과 같은 라운드 버튼을 이미지 없이





zeplin 오른쪽 사이드에 사각형 이라 표시되고 전혀 image asset에 대한 정보가 없다.
디자이너는 그냥 파란색 도형을 디자인 한것이다.

로그인 버튼은 사각형이며 파란색 도형인데 이미지가 없다?

이러한 경우는

UIVew를 상속 받은 UIButton에서 conerRadius를 설정 하여 처리 하면 된다.
결국 코딩으로 해야 한다.


2. 이번에는 속이 투명한 완전 원형 버튼






width / height 값이 동일하게 그리고 conerRadius를 width/2 로 설정 하면 원이 된다.
결국 코딩이다.

viewDidLoad에 코딩으로 하지 않고 스토리보드 인터페이스 빌더에서 속성으로 처리 하고 싶다면?


import UIKit

extension UIView {
    
    @IBInspectable var cornerRadius: CGFloat {
        get {
            return layer.cornerRadius
        }
        set {
            layer.cornerRadius = newValue
            layer.masksToBounds = newValue > 0
        }
    }
    
    @IBInspectable var borderWidth: CGFloat {
        get {
            return layer.borderWidth
        }
        set {
            layer.borderWidth = newValue
        }
    }
    
    @IBInspectable var borderColor: UIColor? {
        get {
            return UIColor(cgColor: layer.borderColor!)
        }
        set {
            layer.borderColor = newValue?.cgColor
        }
    }

}


위와 같이 extension을 작성 하면

@IBInspectable 덕에 IB에 표시된다.



extension은 @IBDesignable이 적용이 되지 않아 storyboard 랜더링은 그대로 사각형이지만 런타임에서는 훌륭한 타원으로 표출 된다.


2번 원 버튼의 경우 배경색을 투명으로 하고 border with  와 border color 를 적용 하고 corner radius를 width에 1/2로 적용 하면 원 버튼이 표현 가능 하다.





















Xcode storyboard 리팩토링

Main.storyboard에 ViewController를 계속해서 디자인 하다 보면
성능이 별로 좋지 않은 mac에서는 랜더링 속도가 현저하게 떨어진다.

ViewController에 image등을 올리는 작업이 늘어 나면 늘어 날 수록 더이상 편집 자체가
너무 느려 하기 어려워 질 수도 있다.


이렇게 하나의 Main.storyboard에 모든 ViewController를 때려 박지 않고
여러개의 storyboard 파일로 나누어 segue를 연결 할 수 있다.


스토리보드 리팩토링 방법

1. 새로운 스토리 보드 파일을 추가 한다.
2. 기존 Main.storyboard 파일과 새로 만든 스토리 보드 파일을 보기 좋게 그룹으로 생성 하여 추가 한다.
3. Main.storyboard 파일에서 일부 연결된 ViewController들을 선택 하여 Cmd + X로 자른다.
4. 새로 추가된 스토리 보드 파일에 붙여 넣기를 한다.
5. 새로 추가된 스토리 보드에 첫번째 ViewController를 is Initial View Controller로 체크 한다.
6. Main.storyboard 파일에서 새로 추가된 스토리 보드와 segue를 연결 한다.





Main.storyboard를 간단하게 바꾸고 segue에 연결은 스토리 보드 레퍼런스로 한다.


Xcode 10에서는 라이브러리 화면이 팝업으로 나오게 되어 있다. Cmd + Shift + L




두번째 항목이 스토리 보드 레퍼런스 이다.

이런한 과정을 통해 프로젝트 성격에 맡도록 storyboard 파일을 나누면
각각의 스토리 보드에서 적은수의 View Controller를 처리 하도록 하여 Xcode에서 보다 쾌적 하게 작업 할 수 있다.

2018년 9월 20일 목요일

iOS ViewController 그라데이션 배경색 적용 하기


위와 같이 zeplin에서 색상 정보가 표시되고 ViewController의 배경색을 적용 해야 하는 경우

디자이너님에게 배경 PNG를 주세요! 라고 할 수도 있고
코드로 해결 할 수도 있다.

위 두점은 그라데이션의 시작점이다.
그리고 두개의 색상 정보가 있다.

extension CAGradientLayer {
    
    convenience init(frame: CGRect, colors: [UIColor]) {
        self.init()
        self.frame = frame
        self.colors = []
        for color in colors {
            self.colors?.append(color.cgColor)
        }
        startPoint = CGPoint(x: 0, y: 0)
        endPoint = CGPoint(x: 1, y: 1)
    }
    
    convenience init(frame: CGRect, colors: [UIColor], startPoint: CGPoint, endPoint: CGPoint) {
        self.init()
        self.frame = frame
        self.colors = []
        for color in colors {
            self.colors?.append(color.cgColor)
        }
        self.startPoint = startPoint
        self.endPoint = endPoint
    }
    
    func createGradientImage() -> UIImage? {
        
        var image: UIImage? = nil
        UIGraphicsBeginImageContext(bounds.size)
        if let context = UIGraphicsGetCurrentContext() {
            render(in: context)
            image = UIGraphicsGetImageFromCurrentImageContext()
        }
        UIGraphicsEndImageContext()
        return image
    }

}

위코드에서 첫번째 convenience 초기화는 대각선 즉 0,0 ~ 1,1 로 그라데이션 을 적용 하는 것이고
추가로 두번째 convenience초기화는 startPoint와 endPoint를 파라메터로 전달 할 수 있도록 만든 초기화 이다.


위와 같이 extension을 만들고

실제 ViewController에서 imageView를 전체 영역으로 올리고 다음과 같이 코딩을 한다.

    @IBOutlet weak var backgroundImage: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        
        var colors = [UIColor]()
        colors.append( colorLiteral(red: 0, green: 0.6941176471, blue: 1, alpha: 1))
        colors.append( colorLiteral(red: 0.05882352941, green: 0.8392156863, blue: 0.8078431373, alpha: 1))
        let gradientLayer = CAGradientLayer(frame: self.view.frame, colors: colors, startPoint: CGPoint(x: 0.5, y:0), endPoint: CGPoint(x:0.5, y:1))
        backgroundImage.image = gradientLayer.createGradientImage()


    }


colorLiteral을 사용해서 숫자로 표시되지만 실제로른 Xcode에서 색상 표를 이용해 hex로 입력 한것이다.


CGPoint(x: 0.5, y:0)  ~ CGPoint(x:0.5, y:1) 은 중앙 상단에서 중앙 하단을 의미 한다.