이맥스 – 텍스트 정렬하기

날씨 탓일까요? 뭔가 막혀있는 느낌이 자꾸 드네요. 이럴 땐 역시나 무엇인가에 몰두하는게 가장 좋더라고요.

이맥스 – 텍스트 정렬하기

이건 왜 몰랐을까? 아래와 같이 정렬되지 않은 텍스트를 일정한 규칙에 의해서 정렬할때 align-regexp기능을 사용할 수 있습니다.

rooney = 21
haha = 20
ray = 17

만약 문자 “=” 을 기준으로 정렬을 하고 싶다면, align-regexp을 치고 문자로 “=”을 입력해주세요.

결과는 아래와 같이 정렬된 것을 볼 수 있습니다.

rooney = 21
haha   = 20
ray    = 17

약간 고급스럽게 아래와 같이 사용 할 수 있습니다.

California 423,970 km²
Taiwan 36,008 km²
Japan 377,944 km²
Germany 357,021 km²
Iraq 438,317 km²
Iran 1,648,195 km²
Korea (North+South) 219,140 km²
Mexico 1,964,375 km²

위에 것을 아래와 같이

Taiwan                 36,008 km²
Korea (North+South)   219,140 km²
Japan                 377,944 km²
Germany               357,021 km²
California            423,970 km²
Iraq                  438,317 km²
Iran                1,648,195 km²
Mexico              1,964,375 km²

먼저 전체 텍스트를 영역 지정하고, CTRL+u 그리고 나서 align-regex명령을 입력합니다. 정규식 입력 란에

.* \([0-9,]+\).*

을 입력하고, 그룹에 대해서는

-1

, 공백은

1

을 입력합니다. 반복 실행은

n

을 입력해줍니다.

위와 동일한 효과를 가질 수 있는 두가지 명렁어가 더 있습니다.

  • sort-regexp-fields
  • sort-columns

급하게 잡힌 약속에 나가봐야해서 이만 쓰겠습니다.

Tool – 맥용 최강 터미널 툴 iTerm2!!!

iTerm2는 많은 기능들을 제공합니다.
터미널 사용자들은 미리 볼수 있고 해결한 수 있는 많은것들을 상상할 수 잇습니다. 그리고 지금 보는 것들은 아주 매력적인 것들입니다.

분활 화면

여러개화면을 각각 탭으로 나누는것과, 다른 세션을 한 화면에서 보여주는 기능을 제공합니다. 또한 세로든 가로든 화면을 나눌수 있고 패널에 번호를 매길수 있습니다.

NewImage

사용하지 않는 화면들은 딤처리 되어 현재 활동하고 있는 구간을 쉽게 확인 할 수 있습니다.

윈도우 핫키

단축키를 등록함으로써 iTerm2를 다른 어플리케이션 사이에서 화면 맨앞쪽으로 쉽게 불러올 수 있습니다. 또한 핫키를 통해서 아주 자주 사용하던 창을 선택 할 수 있습니다. 이 기능은 마우스로 손이 안가게끔 시간을 단축하게 해주죠.

NewImage

검색

iTerm2은 한페이지에서 검색할 수 있는 강력한 기능을 제공합니다. 화면에서 보이지는 않는 것까지 동일한것들을 찾아주고 하이라이트로 표시해줍니다. 또한 Regular Expression도 제공하지요.

NewImage

자동완성

간단하게 입력하고 필요할때

Cmd-;

을 입력하시면 자동 완성 창이 활성화 됩니다. 그리고 친적이 있고 이미 분석되어 리스트에 있는 항목들을 보여주죠.

NewImage

마우스 없이 복사하기

검색 명령어로 원하는 키워드를 검색하고, 탭 또는 시프트 탭을 활용하여 왼쪽 오른쪽 영역을 선택하세요. 그리고 원하는 영역이 지정되고 그 영역을 복사하고 싶을때는

Opt-Enter

를 눌러주세요.

NewImage

붙여 넣기 히스토리

붙여 넣기 히스토리는 재방문, 그러니까 최근에 사용했던 내용을 다시 사용하고 싶을 때 사용합니다. 목록에서 또한 선택이 가능하고 절대 읽어버릴일이 없을 겁니다.

NewImage

Instant Replay? 번역을 어떻게?

Instant replay 기능은 시간을 되돌릴수 있는 기능입니다.

NewImage

… 더 많은 내용은 아래의 링크로

http://iterm2.com/features.html

iOS – 음성 바꾸기

원문

필독
… 생략

iOS 기능 중 텍스트를 음성으로 내주는 기능있습니다. 정말 강력한 기능이고, 또한 남자 또는 여자 목소리 또한 선택이 가능합니다.

아래에 보시면 언어에 따른 각 다른 목소리를 골라 사용할 수 있습니다.

[AVSpeechSynthesisVoice 0x17e30940] Language: ar-SA, Name: Maged, Quality: Default, 
[AVSpeechSynthesisVoice 0x17d3e150] Language: cs-CZ, Name: Zuzana, Quality: Default, 
[AVSpeechSynthesisVoice 0x17e79700] Language: da-DK, Name: Sara, Quality: Default, 
[AVSpeechSynthesisVoice 0x17e50c50] Language: de-DE, Name: Anna, Quality: Default, 
[AVSpeechSynthesisVoice 0x17ec30f0] Language: el-GR, Name: Melina, Quality: Default, 
[AVSpeechSynthesisVoice 0x17e687f0] Language: en-AU, Name: Karen, Quality: Default, 
[AVSpeechSynthesisVoice 0x17e23be0] Language: en-GB, Name: Daniel, Quality: Default, 
[AVSpeechSynthesisVoice 0x17e6ffc0] Language: en-IE, Name: Moira, Quality: Default, 
[AVSpeechSynthesisVoice 0x17ec79b0] Language: en-US, Name: Samantha (Enhanced), Quality: Enhanced, 
[AVSpeechSynthesisVoice 0x17e795a0] Language: en-US, Name: Samantha, Quality: Default, 
[AVSpeechSynthesisVoice 0x17e75900] Language: en-ZA, Name: Tessa, Quality: Default, 
[AVSpeechSynthesisVoice 0x17e27ec0] Language: es-ES, Name: Monica, Quality: Default, 
[AVSpeechSynthesisVoice 0x17ec5e10] Language: es-MX, Name: Paulina, Quality: Default, 
[AVSpeechSynthesisVoice 0x17e799c0] Language: fi-FI, Name: Satu, Quality: Default, 
[AVSpeechSynthesisVoice 0x17ec61c0] Language: fr-CA, Name: Amelie, Quality: Default, 
[AVSpeechSynthesisVoice 0x17e75b10] Language: fr-FR, Name: Thomas, Quality: Default, 
[AVSpeechSynthesisVoice 0x17ee2460] Language: he-IL, Name: Carmit, Quality: Default, 
[AVSpeechSynthesisVoice 0x17ef5140] Language: hi-IN, Name: Lekha, Quality: Default, 
[AVSpeechSynthesisVoice 0x17e6f840] Language: hu-HU, Name: Mariska, Quality: Default, 
[AVSpeechSynthesisVoice 0x17e59bd0] Language: id-ID, Name: Damayanti, Quality: Default, 
[AVSpeechSynthesisVoice 0x17d2c950] Language: it-IT, Name: Alice, Quality: Default, 
[AVSpeechSynthesisVoice 0x17ebaec0] Language: ja-JP, Name: Kyoko, Quality: Default, 
[AVSpeechSynthesisVoice 0x17d42100] Language: ko-KR, Name: Yuna, Quality: Default, 
[AVSpeechSynthesisVoice 0x17ee3130] Language: nl-BE, Name: Ellen, Quality: Default, 
[AVSpeechSynthesisVoice 0x17d637d0] Language: nl-NL, Name: Xander, Quality: Default, 
[AVSpeechSynthesisVoice 0x17e7c8b0] Language: no-NO, Name: Nora, Quality: Default, 
[AVSpeechSynthesisVoice 0x17d3e430] Language: pl-PL, Name: Zosia, Quality: Default, 
[AVSpeechSynthesisVoice 0x17e33190] Language: pt-BR, Name: Luciana, Quality: Default, 
[AVSpeechSynthesisVoice 0x17eabf00] Language: pt-PT, Name: Joana, Quality: Default, 
[AVSpeechSynthesisVoice 0x17e2a650] Language: ro-RO, Name: Ioana, Quality: Default, 
[AVSpeechSynthesisVoice 0x17e232b0] Language: ru-RU, Name: Milena, Quality: Default, 
[AVSpeechSynthesisVoice 0x17ee6830] Language: sk-SK, Name: Laura, Quality: Default, 
[AVSpeechSynthesisVoice 0x17e64a10] Language: sv-SE, Name: Alva, Quality: Default, 
[AVSpeechSynthesisVoice 0x17e62fc0] Language: th-TH, Name: Kanya, Quality: Default, 
[AVSpeechSynthesisVoice 0x17df4080] Language: tr-TR, Name: Yelda, Quality: Default, 
[AVSpeechSynthesisVoice 0x17e76a10] Language: zh-CN, Name: Ting-Ting (Enhanced), Quality: Enhanced, 
[AVSpeechSynthesisVoice 0x17db4850] Language: zh-CN, Name: Ting-Ting, Quality: Default, 
[AVSpeechSynthesisVoice 0x17e2ecf0] Language: zh-HK, Name: Sin-Ji, Quality: Default, 
[AVSpeechSynthesisVoice 0x17e224c0] Language: zh-TW, Name: Mei-Jia, Quality: Default]

위 코드에 맞는 언어/나라

Arabic (Saudi Arabia) - ar-SA
Chinese (China) - zh-CN
Chinese (Hong Kong SAR China) - zh-HK
Chinese (Taiwan) - zh-TW
Czech (Czech Republic) - cs-CZ
Danish (Denmark) - da-DK
Dutch (Belgium) - nl-BE
Dutch (Netherlands) - nl-NL
English (Australia) - en-AU
English (Ireland) - en-IE
English (South Africa) - en-ZA
English (United Kingdom) - en-GB
English (United States) - en-US
Finnish (Finland) - fi-FI
French (Canada) - fr-CA
French (France) - fr-FR
German (Germany) - de-DE
Greek (Greece) - el-GR
Hindi (India) - hi-IN
Hungarian (Hungary) - hu-HU
Indonesian (Indonesia) - id-ID
Italian (Italy) - it-IT
Japanese (Japan) - ja-JP
Korean (South Korea) - ko-KR
Norwegian (Norway) - no-NO
Polish (Poland) - pl-PL
Portuguese (Brazil) - pt-BR
Portuguese (Portugal) - pt-PT
Romanian (Romania) - ro-RO
Russian (Russia) - ru-RU
Slovak (Slovakia) - sk-SK
Spanish (Mexico) - es-MX
Spanish (Spain) - es-ES
Swedish (Sweden) - sv-SE
Thai (Thailand) - th-TH
Turkish (Turkey) - tr-TR

실제로 사용 하는 방법을 알아보겠습니다.

let voice = AVSpeechSynthesisVoice(identifier: AVSpeechSynthesisVoiceIdentifierAlex)

다른 목소리를 사용하기 위해서, 이름으로 매칭하여 사용 할 수 있습니다. [code]identifier[/code]으로는 매치가 안됩니다.

목록 불러오기

var voiceToUse: AVSpeechSynthesisVoice?
for voice in AVSpeechSynthesisVoice.speechVoices() {
    if #available(iOS 9.0, *) {
        if voice.name == "Karen" {
        voiceToUse = voice
        }
    } 
} 

텍스트를 주어 음성을 내는 방법은 아래와 같습니다.

let utterance = AVSpeechUtterance(string: "Hello from iOS.")
utterance.voice = voiceToUse
let synth = AVSpeechSynthesizer()
synth.speakUtterance(utterance)

iOS – 유닛 테스트 쉽게 하기! (Swift 2 + XCode 7)

원문

유닛 테스트를 하기 위해 아래의 항목을 확인해주어야 한다.

1. 내부 클래스 만들기

만약 새롭게 내부 클래스를 만들었다면, 클래스나 메서드를 찾지 못한다면, 아래와 같이 Public 처리를 해주어야 한다.

NewImage

2. Import with @testable

테스트 타겟에서, 아래와 같이 @testable keyword를 사용하여, 모듈을 import해줘야한다.

NewImage

3. Test하기

모든게 완료되었다. 외부 클래스나 메서드도 쉽게 테스트 할 수 있다.

NewImage

끝.

iOS 9 – 새로운 UIAlertController, Swift Closures and Enumeration

원본 자료

iOS 8 SDK가 나오면서, 그렇게 큰 관심을 두가지 변화 점에 대해서 설명하고자 한다.
이전에는 UIActionSheetUIAlertView가 사용되었다면, 이제는 UIAlertController라는 클래스를 대체 사용하여야 한다.

iOS 8에서, 앱 내 Alert 메시지를 표현하고 싶다면, 위에서 언급한 UIAlertSheetUIAlertView가 아닌 UIAlertController를 사용하여야 한다. UIAlertController내 Enum값으로 두가지 스타일을 제공한다. 스타일 설정으로 우리는 UIAlertSheetUIAlertView를 선택 할 수 있다. 그냥 둘중에 하나만 선택하며 되는것이다. 또한 우리가 액션을 등록할 때 ex)UIAlertViewDelegate를 사용하였다면, 이제는 closures나, Objective-C에서의 블럭 코드를 사용해야 한다.


이 소개 페이지에서는 UIAlertConroller 클래스 사용법과 alert message표현 방법과 action sheet에 대해서 설명할 것이다.

NewImage

자 시작해보자.

새로운 Xcode 프로젝트 생성

데모하기에는 새로운 프로젝트를 생성하는 방법이 가장 좋다. 자 Single View Application 템플릿을 선택하고, UIAlertDemo라는 이름으로 프로젝트를 생성해보자.

!! Swift Language 선택하는 것을 잊지 말도록!.

여기서는 Xcode 6 Beta를 사용했다는 것을 염두해 두길 바란다. (번역자 데모 실행 7버전도 정상적으로 동작함)

Xcode 6에서는 기본적으로 Size Classes가 활성화 된다.
!! Size Classes기능은 모든 화면을 자동으로 수용하는 기능이다.

여기서는 간단하게 Size Classes 기능을 비활성화 하는 것으로 한다. Main.storyboard에 File inspector옵션에서 “Use Size Classes”기능을 체크를 해지하자. 체크를 해지하게 되면 Device Type선택 창이 보여질 것이고. 우리는 iPhone을 선택 할 것이다.

화면은 아래와 같이 볼 수 있을 것이며, 간단한 버튼 컴퍼넌트를 드래그 하여 넣어주자. 제목은 간단하게 “Hello Alert”로 넣어주자.

NewImage

Action 메서드 추가하기

ViewController.swift에 아래와 같이 코드를 작성해주자.이는 나중에 “Hello World” 버튼을 클릭했을 때 취해지는 액션 메서드이다. 추후 스토리보드에서 버튼과 저 메서드를 따로 연결 시켜주어야 한다.

@IBAction func showAlert() {

}

알다시피, OutletAction은 스토리보드에서 소스코드와 UI Object를 연결하게 해준다.

Swift에서는 메서드 앞에 @IBAction 붙여주면 된다.

자 그러면 이제 실제로 메서드와 UI Object를 연결해보자.

Document Outline에서, CTRL을 누르고, View Controller에을 클릭 후 “Hello Alert”까지 드래그 해주자 그리고 “showAlert”를 선택해주자.

아래의 그림과 같이 될 것이다.

NewImage

실제 Alert를 표현하기 위해 UIAlertViewController를 사용하기

거의 모든 설정이 완료되었다. 이번에는 간단하게 alert message를 표현하는 가장 기본이 되는 것을 설명할 것이다. 간단하게 표현하기 위해 기초가 되는 것은 아래와 같다.

  • UIAlertController 객체 생성! (title, message, alert controller의 스타일 선택)

  • UIAlertAction 생성과 위에서 생성한 alert controller에 반인딩!

  • 마지막으로, presentViewController 메서드를 호출함으로써 alert controller 을 보여주기!

우리는 swift를 사용하고, 위 룰에 충족 시킨다면 코드는 아래와 같이 나올 것이다.


@IBAction func showAlert() {
        let alertController = UIAlertController(title: "Hey AppCoda", message: "What do you want to do?", preferredStyle: .Alert)
        
        let defaultAction = UIAlertAction(title: "OK", style: .Default, handler: nil)
        alertController.addAction(defaultAction)
        
        presentViewController(alertController, animated: true, completion: nil)
}

간단하죠? alert나 action sheet를 표현하는 방법은 위와 동일합니다. 단지 스타일만 선택해주면 된다. .Alert를 선택한다면, alert message를 보여주고, .ActionSheet 스타일을 지정한다면, action sheet가 표현될것이다.

기본적으로, alert controller는 아무 액션도 포함하고 있지 않다. 만약, 어떠한 액션을 추가하고 싶다면, 예로 alert의 버튼 액션이 취해졌을때 사라지게 하고 싶다면, 우리는 UIAlertAction 객체를 생성하고 addAction메서드를 활용하여, alert controller에 연결시켜주어야 한다.

UIAlertAction을 생성할때 두가지 파라미터를 받는다. 제목과 핸들러이다. 핸드로는 블럭 코드로, 버튼이 눌려졌을 때 실행되는 부분이며, handler에 nil을 포함하게 되면, controller는 사라지는 기능만 가지게 될것이다. 이부분에 대해서 나중에 더 이야기 하도록 하겠다.

마지막으로, presentViewController메서드를 호출함으로써 alert controller 를 표현할 것이다. 만약 앱을 실행하고, 버튼을 클릭하게 되면 아래와 같이 실행될 것이다.

NewImage

Swift에서 Enumeration에 대한 설명

Swift코드 작성이 처음이라면, .Alert와 .ActionSheet이 생소할 것이다. 그 부분같은 경우 아래와 같이 full syntax로 사용할 수 있다.

let alertController = UIAlertController(title: "Hey AppCoda", message: "What do you want to do?", preferredStyle: UIAlertControllerStyle.Alert)

위 코드는 우리가 사용했던 부분과 완전히 동일한 방법이고, 사실 UIAlertControllerStyle은 아래와 같이 enumration이다.

enum UIAlertControllerStyle : Int { 
     case ActionSheet 
     case Alert 
}

swift에서 enumeration은 값들을 다 그룹화 시킬때 사용된다. AlertSheet와 Alert는 enumeration 안에 멤버 값으로 정의된다. objective C와 같지 않게 만들때 상수는 아니다. AcitonShee와 Alert는 0 그리고 1로 정의되지는 않는다. 각 각 멤버들은 enumberation에서의 full-fledged 값을 가진다.

쉽게 말하면, 딱 정해진 값은 아니지만, 그 안에서는 독립된 값을 가지게 된다.

UIAlertControllerStyle.Alert로 사용할 수 도 있지만 .Alert를 사용하도록 하자.

당신의 짧은 코드는 당신이 더 쉽게 읽을 수 있도록 한다.

Action Handler와 Closures

UIAlertController로 돌아가보자. 우리가 이야기 아직 이야기 하지 않은 것중 하나, UIAlertAciton의 handler이다. 우리가 UIAlertAction 객체를 생성할때 우리는 handler에 블럭 코드를 작성하기 되는데, 이 블럭 코드는 사용자로부터 이벤트를 받았을 때 실행되는 코드이다.

showAlert 메서드 안에 아래와 같이 코드를 작성하고 다른 액션을 취하도록 해보자.

let callActionHandler = { (action:UIAlertAction!) -> Void in
            let alertMessage = UIAlertController(title: "Service Unavailable", message: "Sorry, the call feature is not available yet. Please retry later.", preferredStyle: .Alert)
            alertMessage.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
            self.presentViewController(alertMessage, animated: true, completion: nil)
        }
        let callAction = UIAlertAction(title: "Call", style: .Default, handler: callActionHandler)
        alertController.addAction(callAction)

우리는 새로운 handler를 정의하고 이를 추가하였다. 위 코드는 간단하게 alert 버튼이 눌려졌을 때 취하는 액션을 정의하고 추가만 해줬을 뿐이다. 블럭코드는 Closure로 알려져 있다.

Closures는 코드 자체를 기능으로 할 수 있는 블럭을 자체적으로 포함하고 있다. 이것은 위와 같이 Objective-C에 블럭과 굉장히 흡사하다.

action closure에 값 같은 것을 제공하기 위한 한가지 방법은 코드 블럭과 같은 상수 또는 변수이다.

코드 블럭의 첫 번째 부분은 UIAlert Action의 handler 파라미터들과 리턴 타입를 정의하는 것이고, in 키워드는 이후로는 closure의 몸체 부분이 시작되는 부분이다.

NewImage

위 처럼 closure를 각 변수나 상수로 정의하는 것은 필수가 아니다. 아래와 같이 간단하게 closure을 파라미터처럼 활용 할 수도 있다. 아래와 같이 간단하게 사용 할 수 있다.

let callAction = UIAlertAction(title: "Call", style: .Default, handler: {
            action in
                let alertMessage = UIAlertController(title: "Service Unavailable", message: "Sorry, the call feature is not available yet. Please retry later.", preferredStyle: .Alert)
                alertMessage.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
                self.presentViewController(alertMessage, animated: true, completion: nil)
                }
        )
alertController.addAction(callAction)

결론

UIAlertController는 clsures의 사용 (또는 Objective-C의 블럭)을 포용하고 있으며, 이로써 우리는 UIAlertController을 잘 활용 할 수 있을 것이라고 예상한다.

Clojure – Clojure Cider REPL에서 쓰래드를 사용하였을 때 print 되지 않는 이유와 해결 방법

참고 링크

Q> Emacs Cider REPL에서 백그라운드 쓰레드에서 println을 돌렸을 때 왜 출력이 되지 않는가?

A> 원인은 출력되는 버퍼가 다르기 때문이다.

println의 행동은 동적으로 *out* 라는 output stream에 바인딩 되어 출력되는데, 만약 thread를 사용한다면, 그 thread는 루트 *out* 에 바인딩 될것이고, 그렇게 되면 사용하고 있는 REPL에서는 확인을 할 수 없다.

그러면 어디서 확인할 수 있는가?

buffer list에서 *nrepl-server*라는 이름을 가진 버퍼에서 확인 할 수 있다.

또는

(alter-var-root #'*out* (constantly *out*))

와 같이 바꾸어 기존 buffer에서 확인 할 수 있다.

참고 링크

만약 Cider REPL을 사용하지 않는다면, nrepl을 시작한 터미널에서 확인 할 수 있다.

Emacs – 폴더에서 상호작용하며, 텍스트 찾아 바꾸기

텍스트 파일 버퍼 안에서가 아닌, 다수의 파일 여러개의 파일안에 특정 문자열을 변경하고 싶을 때 사용합니다.

원문

사용법

  1. dired을 실행, 디렉토리 목록에서 변경하고 싶은 파일을 선택 %m합니다.
  2. Q를 누르면 dired-do-query-replace-regexp.
  3. 정규식 또는 특정 문자열을 입력합니다. (elisp 정규식 패턴)
  4. 변경 될 문자열로 focus가 이동하게 되는데, 변경하고자 한다면 y, 아니면 n을 눌러 변경해줍니다. 만약 변경 중 취소하고 싶다면 Ctrl+g를 눌러주세요.
    • 파일안에 모든 문자열을 한번에 변경하고자 한다면, ! 또는 변경을 원하지 않는다면 N을 눌러주세요. (23버전 이후만 가능)
    • 모든 파일을 한번에 적용하고 싶다면, Y를 눌러주세요.
  5. 변경 된 (열려진 파일)을 저장하기 위해서, ibuffer를 이용, 모든 파일을 열어 저장하기 위해서 *****을 이용하여 마크 후 S를 눌러 저장해주세요. 파일을 닫기 위해서는 D를 사용합니다.

끄읕

Android – getFragment NullPointerException 문제 해결하기

MaterialNavigationDrawer와 ViewPager (v4 22.2.0)를 사용 할때 (즉 다중 Fragment를 사용했을 때) getFragment 시 NullPointException 문제가 발생합니다.

정확한 이유는 아직 찾지 못했으나, stackoverflow에서 동일한 문제를 겪고 있는 분들이 있더라고요. 일단 증상부터 해결책을 살펴보도록 하겠습니다.

일단 에러 코드는 아래와 같습니다.

java.lang.NullPointerException
at android.support.v4.app.FragmentManagerImpl.getFragment(FragmentManager.java:569)
at android.support.v4.app.FragmentStatePagerAdapter.restoreState(FragmentStatePagerAdapter.java:211)
at android.support.v4.view.ViewPager.onRestoreInstanceState(ViewPager.java:1281)
at android.view.View.dispatchRestoreInstanceState(View.java:12043)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2688)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2694)
...

일단 문제의 원인은 childFragment 이슈 때문에 발생하는데, 아래의 방법은 그렇게 확실하지 않은 방법이라고 하네요. 원인은 states 복구 쪽에서 일어나는 거 같습니다.

그래서 아래의 해결책은 상태값을 저장하지 못하게 되는데요, 이부분을 사용하지 않을거라면 아래의 방법으로 해결하여도 무방할거 같습니다.

아래의 부분을 FragmentStatePagerAdapter 상속한 클래스에 넣어주시면 됩니다.
아래의 코드는 상태 복구부분에서 아무것도 안하는 것을 확인 할 수 있습니다.

    @Override
public void restoreState(Parcelable arg0, ClassLoader arg1) {
    //do nothing here! no call to super.restoreState(arg0, arg1);
}

끄읕.

JAVA – 자주하는 실수 10가지

원문

이 글은 자바 개발자들이 자주하는 실수 10가지에 대한 글입니다.

1. Array 객체를 ArrayList로 변환하기

아래와 같이 자주들 이렇게 사용하고는 합니다:

List<String> list = Arrays.asList(arr);

하지만! Arrays.asList()메서드는 Arrays클래스 내부에 있는 private static class 객체를 리턴합니다. java.util.ArrayList class가 아니라는 말이죠.
java.util.Arrays.ArrayList 클래스는 set(), get(), contains() 메서드를 가지며 대신 그외 element를 추가하기 위한 아무 메서드도 지원하지 않습니다. 그래서 리스트의 사이즈는 항상 일정합니다.

그럼 어떻게 사용해야 할까요?

ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(arr));

ArrayList 생성자는 Collection type의 객체를 받을 수 있고, 이는 java.util.Arrays.ArrayList가 됩니다.

2. 만약 Array 객체에서 특정 값을 찾는다면?

개발자들은 아래와 같이 자주 사용하고는 합니다.

Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);

위 코드는 정상적인 작동을 합니다. 하지만 구지 List를 Set으로 변환 할 필요는 없습니다. 이는 추가적인 시간 비용이 들기 때문에 아래와 같이 간단하게 해결 할 수 있습니다.

Arrays.asList(arr).contains(targetValue);

또는

for(String s: arr){
    if(s.equals(targetValue))
        return true;
}
return false;

첫 번째 방법이 두번째 방법보다 읽기가 편하겠죠?

3. 루프 상태에서 List의 특정 객체 지우기

아래의 코드를 돌리다면 어떠한 일들이 벌어질까요? 한번 생각해봅시다.

ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));
for (int i = 0; i < list.size(); i++) {
    list.remove(i);
}
System.out.println(list);

결과는 처참합니다.

[b, d]

위 코드는 심각한 문제를 가지고 있습니다. 특정 객체를 지우게 되면, 리스트의 사이즈는 줄어들게 되고, 삭제할 타겟의 인덱스 또한 변하게 됩니다. 그래서 만약 루프 안에서 인덱스를 사용하여 여러개의 Element를 지우게 한다면 정상적으로 작동하지 않게 됩니다.

아마 알지도 모르겠지만 대안은 iterator를 사용하면 됩니다. 그리고 foreach문이 있겠죠. 자바에서 foreach문은 iterator처럼 작동하지만 사실 iterator가 아닙니다.

아래의 코드를 보도록 하죠.

ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));
 
for (String s : list) {
    if (s.equals("a"))
        list.remove(s);
}

위 코드는 ConcurrentModificationException를 발생시킵니다.

하지만 아래의 코드는 정상적으로 작동합니다.

ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));
Iterator<String> iter = list.iterator();
while (iter.hasNext()) {
    String s = iter.next();
 
    if (s.equals("a")) {
        iter.remove();
    }
}

.next() 메서드는 .remove() 메서드가 호출되기 전에 호출되어야 합니다. foreach문에서 ConcurrentModificationException 문제의 원인은 Compiler.remove() 호출 후에 .next()가 불리도록 만들기 때문입니다.

자세한 내용은 소스코드를 참조해주세요.

4. Hashtable vs HashMap

알고리즘 관례에서, Hashtable은 데이터 구조의 이름이라고 한다고 하네요. 하지만 자바에서는 데이터 구조 이름은 HashMap이라고 합니다.

여기서 중요한 차이점 하나는 Hashtable은 동시성을 가진다는 것과 HashMap는 그렇지 않다는 것입니다.

그래서 Hashtable보다 HashMap의 사용을 많이 합니다.

HashMap vs. TreeMap vs. Hashtable vs. LinkedHashMap
Top 10 questions about Map

5. Collection의 Row Type을 사용해라!?

자바에서, raw type과 unbounded wildcard type은 같이 사용하기 쉽습니다. Set이 raw type이고, Set이 unbounded wildcard type입니다.

파라미터로 raw type의 List객체를 사용하는 코드를 생각해봅시다.

public static void add(List list, Object o){
    list.add(o);
}
public static void main(String[] args){
    List<String> list = new ArrayList<String>();
    add(list, 10);
    String s = list.get(0);
}

이 코드는 아래와 같이 예외를 발생하게 하는데,

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
    at ...

여기서 **Set,Set,그리고 **Set는 몇가지 차이점이 있습니다.

자세한건 Raw type vs. Unbounded wildcardType Erasure를 참조해주세요.

6. 접근 제어

개발자들은 자주 public 클래스 필드를 사용합니다. 필드에 대한 접근이 다이렉트로 이루어지기 때문에 매우 쉽기는 하지만 클래스 디자인 측면에서는 좋지 않습니다. 접근 제어에 대해서는 적으면 적을 수록 좋은 디자인입니다.

자세한 내용은 아래의 링크를 참조해주세요.
public, default, protected, and private

7. ArrayList vs. LinkedList

ArrayListLinkedList의 차이점을 잘 모르는 개발자들은 주로 ArrayList를 사용하고는 합니다. 그 이유는 매우 친숙하기 때문이죠. 그렇지만, 여기에는 아주 큰 퍼포먼스 차이가 있습니다.

LinkedList의 경우 추가와 삭제가 빈번하게 사용될때 사용되어야 하며, 또한 random access 동작이 많지 않습니다.

좀더 상세한 정보를 얻기 위해서 ArrayList vs. LinkedList을 참조해주세요.

8. Mutable vs. Immutable

Immutable 객체는 단순함, 안전함, 기타 등등의 여러가지의 혜택을 받습니다. 하지만 제한된 값을 떼어낼때, 객체들에 많은 변화가 필요할때 가비지 컬렉션이 자주 일어나게 되는데요, 이럴대는 발란스를 맞춰 선택을 해야합니다. 내가 mutable을 사용할지 아니면 immutable을 사용할지에 대해서 말입니다.

일반적으로, mutable객체는 많은 객체의 생상을 피하기 위해 사용되는데요, 아주 오래된 예로 문자열의 결합을 말할 수 있을 있을거 같습니다. 만약 immutable string을 사용한다면, 아무래도 많은 객체 생성과 그에 합당한 가비지 컬렉션이 일어나겠죠. 이는 시간과 cpu 전력을 낭비하는 일입니다. 이럴때는 간단하면 mutable 객체(e.g. StringBuilder)를 사용하면 됩니다.

String result="";
for(String s: arr){
    result = result + s;
}

mutable객체가 매력적으로 보일때는 이런 상황입니다. 예로, 메서드 호출로 하나의 값이 아닌 여러개의 값을 얻고자 할때, 그리고 정렬이나, 필터링 등이 될수 있습니다. 물론 제대로 사용하지 않으면 많은 비용을 그만큼 지불하게 되겠죠.

자세한 내용은 아래의 링크를 참조해 주세요.
from dasblinkenlight’s answer on stack overflow

Why String is Immutable?

9. Super와 Sub의 생성자

Implicit-super-constructor-is-undefined-for-default-constructor

기본 슈퍼 생성자는 정의되어 있지 않아 에러가 발생한다. 자바에서 만약 생성자를 생성하지 않으면, 컴파일러는 인자를 받지 않는 기본생성자를 기본으로 생성한다.

만약 슈퍼 클래스에 생성자가 정의되어 있다면, 위와 같은 경우 Super(String s), 컴파일러는 파라미터가 없는 생성자를 만들지 않을 것이다.

그 파라미터가 있거나 또는 없는 서브 클래스의 생성자는 파라미터가 없는 슈퍼 생성자를 호출한다.
컴파일러는 서브 클래스에 super() 생성자를 추가할려고 할것이고, 그렇지만 그 슈퍼의 기본 생성자는 정의 되어 있지 않다. 그래서 컴파일러는 에러를 표시할 것이다.

이 문제를 해결하기 위해서는 간단하게 Super()생성자를 생성하는것이다.

public Super(){
    System.out.println("Super");
}

또는 슈퍼 생성자를 지우고 서브 생성자를 생성하는 것이다.

Constructor of Super and Sub

10. “”or 생성자?

문자열은 아래와 같이 두가지 방식으로 생성될 수 있다.

//1. use double quotes
String x = "abc";
//2. use constructor
String y = new String("abc");

어떤 차이점이 있을까?

아래의 코드로 빠르게 확인 할 수 있다.

String a = "abcd";
String b = "abcd";
System.out.println(a == b);  // True
System.out.println(a.equals(b)); // True
 
String c = new String("abcd");
String d = new String("abcd");
System.out.println(c == d);  // False
System.out.println(c.equals(d)); // True

좀 더 자세한 내용을 알기 위해서는 아래의 링크로 확인 할 수 있다.
Create Java String Using ” ” or Constructor?.

내일을 향해
위 목록들은 GitHub, Stack Overflow의 open source project의 분석으로 통한 질문으로, 구글 인기 검색이다. 탑 10에 대한 정확한 평가, 수치는 없지만 공통적으로 많이 언급이 되었던 부분이다.

이상