2013 이전/기타

[UNIX] cat 리다이렉션 주의 사항

hagulu 하구루2017.02.25 16:43

간단한 파일 입출력을 위해서 cat을 이용하는 경우가 종종 있을 것이다. 간단한 명령어기 때문에 별 생각 없이 써왔던 명령어였는데, 실수를 통해서 좀 깊이 알게되어 정리 해보려 한다.


 내가 했던 실수는 다음과 같다.
 
 test1.txt 와 test2.txt의 내용을  test3.txt에 저장하려고 하였다.
그런데 실수로 아래와 같이 해버렸다.

$cat test* > test3.txt

위 문장은 풀어서 쓰면 다음과 같다

$cat test1.txt test2.txt test3.txt > test3.txt

 위처럼 자기 자신 까지 포함해서 test3.txt에 저장이 되게 한 것이다. 그래도 test3.txt가 내용이 존재 하지 않기때문에 별 문제없을 것이라고 생각했다. 그런데, 신기하게도 무한 루프가 걸리면서 test1과 test2의 내용이 반복해서 test3.txt에 저장되고 있었다. 무슨일이 일어난 것일까?
 대충 생각하면, 자기자신에게 저장이 되다보니 그럴수도 있을것 같은데, 명확한 이유를 알고 싶었다. 직접 cat명령어의 소스도 찾아서 분석하고, Linux를 잘다루는 친구에게 물어봐가며 어럽게 답을 찾아 내었다.

 cat의 input output 방식의 문제이다. cat에서는 파일을 읽을때, 일정한 byte를 메모리에 읽어와서 파일에 쓰고, 그 나머지를 다시 읽어와서 파일에 쓰는 방식이다. 요쯤 되면 조금 감이 잡히는 분도 있을 것이다. 위의 예로 적용하면 test1.txt test2.txt test3.txt의 내용을 일정 byte를 메모리로 가져와서 test3.txt에 저장을 하게 된다. 그리고 다시 cat은 가져온 일정 byte이후의 내용을 확인하고 가져오려고 할것이다. test1.txt와 text2.txt의 내용은 더 이상 가져올 것이 없으므로 이대로 끝이다. 하지만 test3.txt는 다르다. 방금 test1.txt와 test2.txt의 내용이 써졌기 때문에 처음에 가져왔던 byte(파일이 새로 만들어지기 때문에 0byte) 이후의 내용이 존재한다. 그래서 이를 가져와서 다시 test3.txt에 쓰게 된다. 그러면 또 다시 test3.txt의 내용이 늘어나고 이전에 썻던 byte이후의 내용이 존재하여 이를 계속 반복하게 된다.
 cat이 한꺼번에 모든 파일의 내용을 읽어 올 수 없기 때문에, 일정 byte씩 읽어 와서 일어나는 현상이다.

 그리고 참고로, 위에서도 잠깐 언급했지만 일반적인 '>' 의 리다이렉션은 항상 결과 파일을 새로 생성한다. 그리고 그 생성하는 타이밍은 파일을 읽어서 메모리에 올리기전 가장 먼저 수행된다.
 이를 확인 할수 있는 예로
 test1.txt에 "test1.txt 파일입니다" 라는 내용이 있다고 해도,
 
$cat test1.txt > test1.txt

위와 같이 수행하면 test1.txt의 내용이 사라진다. test1.txt의 내용이 메모리에 올라가기 전에 test1.txt의 파일이 새로 생성되기 때문에 파일은 비어져 버리고 이를 test1.txt에 쓰게 되기 때문에 비어지게 된다.

위 두가지의 cat의 특성만 알더라도 사용하는데 좀더 도움이 되지 않을까 싶다.


신고

댓글

댓글쓰기 폼

2013 이전/일단까고보자

[일단까고보자] 네이트 모바일앱

hagulu 하구루2017.02.25 16:42

평소 뉴스 기사를 볼때 네이트 앱을 많이 사용한다. 시사, 스포츠, 연예 세개의 카테고리로 각각의 뉴스에 순위를 매겨서 보여준다. 일단 이슈가 되는 뉴스를 쉽게 한 눈에 볼 수 있기 때문에 많이 사용하게 된다. 그리고 베스트 리플이 잘 정리 되있어서 재치있는 리플을 쉽게 불 수 있다. 가끔 기사내용은 읽지 않고 베플만 보는 경우도 많다. 그리고 여자친구의 영향으로 가끔 톡이라는 것을 심심할때 보게 되는데 이것을 볼 때도 사용하게 된다. 출 퇴근 시간에 항상 보는 사용 빈도가 높은 앱 중의 하나이다.

 로딩도 길지 않고 사용성도 좋아서 앱 기능 자체를 깔 생각은 크게 없다. 너무 웹 뷰에 의존적이긴 하지만 사용하는데는 크게 문제될것은 없다.
 
 문제는 이들의 광고 행태이다. 다른 포털 사이트 앱과 달리 광고가 있는것 자체도 마음에 들지 않지만, 요즘 네이트(sk컴즈)의 상황을 보면 어느 정도 이해는 해줄 수 있다. 본인도 개발자로써, 뭐 돈은 벌어야 할테니. 하지만 광고를 올리는 방법이 너무 양아치같다.
 

 .       





 위 캡쳐 화면에서 보는 것처럼 메뉴 버튼을 가리도록 광고가 나온다. 앱을 구동했을때, 광고가 잠시 올로왔다가 사라지는 방식이다. 광고가 가리고 있는 시간이 꽤 될 뿐더러, 앱을 구동하고 바로 자리를 잡고 있는 것이 아니라, 화면이 다 나온 뒤 잠시 후에 올라 온다. 사용자는 앱을 구통하고, 무심결에 다른 버튼을 누르려고 하다보면, 광고가 올라와서 의도치 않게 광고를 누르는 경우가 많다. 광고주, 사용자는 원치 않는 광고 관리자만 배부른 전형적인 무효 클릭이다. 게다가 이들이 올리는 광고는 sk에서 운영하는 T-ad라는 광고 회사에서 진행하는 것이다.  결국 지내들 배불리기 위해서, 광고 주와 사용자를 우롱하는 것이다.
 더 웃긴건 T-ad가 이를 올린 다른 클라이언트 들에게 하는 처사이다.
 T-ad가 갓 서비스를 시작한 베타 시절 회자의 앱을 만드는데 적용을 해본 적이 있다. 우리는 광고를 앱 가장 상당에 올려 놓았다. 그리고 가끔 버튼이 광고 바로 밑에 보여지는 경우가 있다. 흔히 있는 일이기 때문에 별 신경을 쓰지 않았다 그런데, 광고 클릭이 좀 늘어나자, T-ad측에서 클릭을 유도하는 UI이므로 UI를 변경해 달라고 요청이 왔다. 버튼이 광고 주변에 있다는 이유였다. 광고가 버튼을 가렸다 사라지는 것이 아니라 그저 광고 밑에 버튼이 있다는 이유에서이다. 이렇게 다른 클라이언트 들에게는 까탈스럽게 굴더니, 자기네 앱에는 유도가 아니라 거의 낚시질을 하도록 광고를 올려 놓았다.

 현재 국내 포털은 네이버가 잠식하다 싶이하고, 다음이 그 다음으로 어느정도 포지션을 잡고있다. 네이트는 사활의 기로에 놓여 있는 것으로 알고 있다. 또한 최근 paran과 야후 코리아가 운영에 한계를 느끼고 웹 포털 서비스를 모두 접어 버렸다. 네이트도 이를 남일 같이 않게 지켜 봤을 것이다.
 이러한 시점에서 이렇게 광고 수익 좀 벌자고 사용자와 광고주를 기만하는 기획은 누구 머리에서 나온 것일까?

포털은 사용자의 이용도에 따라서 가치가 평가 된다. 이런식으로 사용자를 기만 한다면, 이러한 포털에 이용도가 높아질 수 있을까? 작은 것 부터 하나하나 고쳐 나가서 다시 예전의 명성을 얻었으면 하는 바램에서 몇자 끄적여 보았다.

이건 정말 아닌것 같다.


신고

댓글

댓글쓰기 폼

2013 이전/기타

옛날 웹페이지를 찾아 보자!

hagulu 하구루2017.02.25 16:40

인터넷을 예전 모뎀시절 부터 사용해 왔다면, 예전 hanmail, empas 등의 예전 웹페이지들이 그리울때가 있을 것이다. 또는 자료 수집이나 참고용으로 예전 90년대 후반 2000년대 초반의 웹페이지가 필요할 때가 있을 수 있다.

 혹은. 백업 해놓지 않았었던, 웹 페이지 관련 리소스를 날려 버렸을때, 기존 웹 페이지가 어딘가 보관되어 있다면, 필요한 리소스들을 얻어 낼 수 있을것이다.(본인 체험)
 
 놀랍게도 이를 저장해 놓고 기록하는 곳이 있다. 도메인을 연결만 해놓은 것이 아니라, 리소스를 저장하고 이를 기록해 놓고 있다. 무려 1996년 이후부터 기록이 되어 보관중이다. 웹 페이지 설명에서는 무려 240 billion(2400억)의 페이지가 보관되어 있다고 한다.

이곳이다. 유명한 몇몇 사이트 뿐만 보관하는 것이 아니다. 본인이 2000년도 초반 학창시절에 재미로 만들었던, 추억의 hihome 홈페이지도 보관이 되어 있다. 예전에 만들었다가 보관해놓지 못했던 페이지가 있다면, 한번 재미삼아 찾아보는것도 좋을 것 같다. 찾는다면, 그때의 추억이 새록새록 떠오를 것이다.

사용법은 간단하다.



페이지에 접속하여 위 사진에 표시된 부분에 주소를 입력하면 다음 화면 처럼 수집된 기록과 함께  표시되고 수집된 날짜를 선택하면 그때의 페이지를 볼수가 있다.







국내 인터넷 초창기에 가장 많이 사용되었던 야후 코리아 페이지 이다.



무려 구글의 베타 시절 모습도 볼수 있다.




다음의 모태가 되었던 한메일의 모습이다.



네이버의 초창기 모습도 볼수있다.

일부 소실되거나 제대로 나오지 않는 리소스들도 있지만, 그때 페이지를 기억하는데는 크게 문제가 없는 수준이다.  지금 보기에는 촌스럽고 텍스트 위주였지만, 그때 당시에는 너무나도 신기하고 놀라운 세상이었다. 여러분들이 기억하는 페이지를 통해서 시간여행을 해보는 것도 재미있을것 같다.


신고

댓글

댓글쓰기 폼

2013 이전/node.js

[node.js] Socket.io 맛보기 (웹 채팅 만들기)

hagulu 하구루2017.02.25 16:34

node.js 가 나타나면서 가장 주목 받았던 모듈중에 하나였던 Socket.io를 소개 해보려고 한다.

 
 웹을 통한 애플리케이션을 개발할때 가장 힘든점이, 바로 실시간 데이터 적용이다. 서버에서 넘어온 정보를 실시간 으로 화면에 보여 주어야 하는데 refresh를 이용하면 화면이 깜박이는 문제가 있다. 이를 위한 대안으로 Ajax를 많이 사용하게 된다. 하지만 이것은 Client위주의 개발에 적합하다. 서버에 변화 된 내용을 항상 유지하려면 poliing을 직접 구현해야 하는데 여간 번거로운 일이 아닐수 없다.
 이를 보완하기 위해 등장한것이 바로 WebSocket이다. 일반 애플리케이션에서 사용하면 Socket을 브라우져에서 사용가능하게 한 것으로, 어렵지 않게 웹상에서 Socket과 같은 방식의 애플리케이션 구현이 가능하다. 하지만 아직 표준이 정해지지 않았고, 이를 호환하는 브라우져가 제한적이다. 그리고 보안에 대한 논란도 아직 진행중이다.




  WebSocket 지원 여부(이미지 출처: http://caniuse.com)

 표에 보는 것처럼 전체의 55%정도만 완벽하게 지원이되고 부분적인 지원이 5%정도이다. 그리고 국내에서 가장 많이 사용하는 IE에서는 10.0에서나 지원이 가능하다. 
 
 이에 대한 대안이 바로 Socket.io이다. 서버는 node.js의 모듈로 간단히 이용이 가능하고 client도 모듈에 포함된 javascript 파일 하나만 있으면 지원이 된다. 일반 javascript를 사용하기 때문에 호환 문제도 걱정이 없다.
 
 더 길게 끌지 않고 예제를 통해서 살펴 보도록 하겠다.
 소켓 통신을 이용할때 가장 만만한 예제가 채팅이므로 이를 만드는 예제를 보도록 하겠다.
node.js와 socket.io 모듈의 설치에 관해서는 아래 두 포스팅을 참고하기 바란다.
[node.js] npm을 이용한 module 설치

Socket.io는 기본적인 웹서버 모듈과 연동하게 된다.
여기에서는 단순하게 http 모듈을 이용해서 소개해 보겠다.
var app = require('http').createServer(handler)
	, io = require('socket.io').listen(app)
	, fs = require('fs')
  
    app.listen(8005);
  
function handler (req, res) {
    fs.readFile(__dirname + '/index.html',
    function (err, data) {
        if (err) {
        	res.writeHead(500);
        	return res.end('Error loading index.html');
       	}
  
       	res.writeHead(200);
       	res.end(data);
    });
}
  
io.sockets.on('connection', function (socket) {
      socket.on('my other event', function (data) {
         	console.log(data);
        	socket.emit("my_message", data);
        	socket.broadcast.emit("message", data);
       });
 });
 handler 부분은 http를 위한 부분이니 다음에 다루어 보도록 하겠다.
 중요한 부분은 아래 소켓 관련된 부분이다.
 일반 프로그래밍에서 소켓을 통한 개발을 해보았다면 어렵지 않게 이해가 가능 할것으로 보인다.
 2번째 라인에 require 부분에서 app 즉, http서버를 통해서 socket을 listen을 하게 된다.
 그리고 20번째 라인에서 Client가 연결이 되었을떄의 작업을 function을 통해 정의 해주게 된다. 보는 것처럼 연결이 되었을때 생성된 해당 socket은 파라미터로 가져다 쓸 수가 있다. 이 소켓을 통해 연결된 Client와 통신하게 된다.
 여기에서 다시 해당 소켓에 새로운 이벤트를 추가해주게 된다. 해당 소켓에 on 함수를 통해 새로운 이벤트를 추가를 해주면 된다. 위 소스에서는 "my other event" 라는 이벤트를 추가하고 해당 이벤트가 발생했을때, 이루어질 작업을 function을 통해서 등록 해주게 된다. 이벤트와 함께 들어온 data는 파라미터를 통해 이용할 수 있다.
 23번째 라인은 들어 온 데이터를 다시 Client로  "my_message" 라는 이벤트로 전송하는 것이다. 이쯤 되면 감이 올것이다. 이벤트를 생성하여 발생시키는 것은 emit라는 메소드를 이용하면 된다. 잠시후 client에서도 보겠지만 같은 함수를 사용한다. 일반적으로 socket에 내장되어 있는 함수로 해당 소켓으로만 이벤트를 발생 시키는 것이다. 하지만 여기서 해보려는것은 채팅이다. 채팅의 경우 자기 자신만이 아니라 모두에게 전송이 이루어 져야 한다.
 이를 구현한것이 바로 24번째 라인이다. socket에 broadcast의 emit를 통해서 이벤트를 발생시키면, 해당 소켓이 연결된 Client를 제외한 다른 소켓으로 다른 모든 Client들에게 이벤트를 발생시키게 된다.
 이러면 자연스럽게 채팅과 같은 기능을 하는 서버가 완성이 된 것이다.
 정말 간단하기 그지 없다.
 이어서 바로 Client부분을 보겠다.
 먼저 아래 파일은 위 소스에서 구현한 javascript 파일과 같은 디렉토리에 index.html에 작성하면된다. 그 이유는 위 소스의 handler의 설정에 따른것 이다. 필요하다면 이를 수정해서 다른 디렉토리나 파일로 이용하는 것도 가능하다.
 

Client에서는 조심해야할 부분이 많다.
 먼저 조심해야할 부분이 1라인의 src부분이다. 내 디렉토리에는 눈씻고 찾아 봐도 /socket.io/socket.io.js 파일이 없는데, 왜 그래도 해야 할까 싶지만, 이것은 서버에 있는 socket.io 모듈이 알아서 연결해 주는 부분이다. 그러므로 의심 하지 말고 이용하기 바란다. 혹시 다른 곳에서 구하거나, 다른 곳의 링크를 이용할 경우 socket.io와 socket.io.js의 버젼이 맞지 않아서 문제가 발생할 수도 있으니 꼭 위와 같은 방식으로 이용하기 바란다.
 5번째 라인에서 소켓을 연결하게 된다. 간단하게 소켓을 생성하고 바로 연결이 된다. 예전 버젼에서는 번거롭게 진행해야 하니 최신버젼을 꼭사용하기 바란다. 본인은 원격지 서버로 이용하고, 포트 설정떄문에 포트를 다르게 했지만, local에서 테스트 할경우 "http://localhost" 형식으로 해주기만 하면된다.
 이제 서버에서 올라오게될 이벤트를 등록해주는 부분이 6~13라인이다. 보는 것처럼 서버와 문법이 똑같다. node.js의 장점이 바로 이런것이다. 서버에서 작성한 문법 그대로 웹 클라이언트에서 구현해주면 된다. 위에서는 24라인에 있는 div에 새로온 메시지와 현제 메시지를 합쳐 주는 일을 한다. "message"는 다른 곳에서 온 메시지를 처리하는 것이고, "my_message"는 내 메시지가 서버를 거쳐서 다시 오게되는 메시지를 처리하는 것이다. "my_message"는 굳이 서버를 거칠 필요는 없지만, 소켓의 동작을 보여주기 위해서 적용해 보았다.
 15~18라인은 메시지를 서버로 보내는 부분이다. 이 function은 아래 22 ~ 23라인에서 return키 혹은 버튼 클릭을 통해서 불려지게 된다. 이벤트 발생은 서버와 마찬가지로  emit 메소드를 통해서 사용하면 된다. 서버에 등록 해 두었던 "my other event" 로 이벤트를 발생시키도록 하였다. 메시지 내용은 아래 22번째 라인에 있는 input의 벨류로 하면된다. 17라인은 보낸 다음에 input을 비워주는 부분이다.
 
 여기까지 진행이되면 기본적인 채팅 프로그램이 간단하게 완성이 된다.
 로컬로 진행되었을경우 브라우져로 http://localhost로 접속을 하게 되고, 저 처럼 원격지로 진행된경우는 원격지 도메인을 입력하여 실행하여 보면된다.
간단하게 실행한 예이다





신고

댓글

댓글쓰기 폼

2013 이전/iOS개발

[iOS 개발] UIButton title, image 위치 정리

hagulu 하구루2017.02.25 16:32

UIButton을 사용하다 보면 title, image등을 버튼위에 올려서 사용하게 된다. 

그런데 이들이 깔끔하게 배치되지 않을때가 많다.

UIButton의 titleLabel의 frame을 직접 적용해도 변화가 없을 것이다.
그래서 대부분 포기하고 버튼 위에 따로 View를 올리는 경우가 있는데,
이럴 경우 버튼 state 마다 위에 올린 뷰를 수동으로 바꿔 주어야 한다.
특히, UIControlStateHighlighted 를 처리하려면 소스가 지저분해지고 번거러워 질 수 밖에 없다.  
다행히도 이들을 배치할 수 있는 방법은 존재한다.
일단 image, title의 Alignment를 정해줄수 있는데 아래와 같이 가능하다.
  [btn setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
    [btn setContentVerticalAlignment:UIControlContentVerticalAlignmentBottom];
각각 가로 세로의 정렬을 관리할수 있다.
해당 메소드는 UIControl에 포함된 메소드로 이를 상속 받은 UI들은 모두 사용할 수 있다.
위와 같이 배치를 하면 어느정도 원하는 모양을 가질 수 있지만, 아직 부족하다고 느낄수 있다.
좀더 세밀한 보정이 필요할때 아래와 같이 가능하다.
    [btn setContentEdgeInsets:UIEdgeInsetsMake(0, 10, 0, 0)];
    [btn setImageEdgeInsets:UIEdgeInsetsMake(0, 10, 0, 0)];
    [btn setTitleEdgeInsets:UIEdgeInsetsMake(0, 10, 0, 0)];
각각 Image와 Title의 EdgInsets을 지정해 줄 수 있는데, EdgeInsets은 각각 top, left, bottm, right 를 나타내고,
이를 통해서 위치 조정이 가능하다.
EdgeInsets의 자세한 내용은 해당 링크를 참조하기 바란다.

그리고 두개를 모두 같이 보정하고 싶을때는, contentEdgeInsets를 조정해 주면 된다.

이를 이용하면 버튼을 휠씬 간편하고 깔끔하게 관리 할 수 있게 된다.
간단하지만, 모르고 넘어가서 고생을 할 수있는 부분이다.
이것 때문에 지저분해진 소스가 있다면 지금 바로 수정해 보기 바란다.


신고

댓글

댓글쓰기 폼

2013 이전/iOS개발

[iPad 개발] PopoverController contentSize 문제

hagulu 하구루2017.02.25 16:32

PopoverController 를 사용하다보면 사이즈 때문에 골머리를 썩을 경우가 많을 것이다.

일단 가장 평범한 방법은 해당 PopoverController에 들어갈 해당 UIViewController에
- (CGSize)contentSizeForViewInPopover {
    return CGSizeMake(320, 480);
}
위 처럼 해당 하는 함수를 override 해주면 리턴하는 사이즈로 PopoverController 사이즈를 조절 해준다.
하지만 여기도 문제점이 하나 있다.
navigationController를 사용할때 push나 pop을 하게 되면 늘어나기는 하지만 줄어 들지는 않는다.
구글링을 통해서 얻게된 방법인데, 일종의 꼼수라고 볼수 있겠다.
- (void) forcePopoverSize 
{
    CGSize currentSetSizeForPopover = self.contentSizeForViewInPopover;
    CGSize fakeMomentarySize = CGSizeMake(currentSetSizeForPopover.width - 1.0f, 
                                          currentSetSizeForPopover.height - 1.0f);
    self.contentSizeForViewInPopover = fakeMomentarySize;
}


- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    [self forcePopoverSize];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    CGSize currentSetSizeForPopover = self.contentSizeForViewInPopover;
    self.contentSizeForViewInPopover = currentSetSizeForPopover;
}

위 처럼 ViewController에 해당하는 함수에 위 내용을 추가만 해주면 된다.
모두 ViewController 멤버를 사용하는 것이니, 바로 가져다 붙여 써도 잘 적용될것이다.
해당 메소드 이름을 정확히 확인하고 적용 바란다.
처음에 잘못 보고 적용을 해서 삽질을 했엇다. ㅠㅠ

각 viewController에 위사항을 적용하면, 언제 그랫냐는 듯이 pop, push 간에 PopoverController크기가 늘었다 줄었다 한다.

하지만 여기도 문제는 있다.
ViewController 사이의 사이즈 크기가 차이가 많이 나면 정신없이 움직여서 산만한 느낌이 든다.
이 기능이 꼼수를 통해서만 이루어 지는걸 봐서는 정신 없게 움직이는것을 방지하기 위해 그렇지 않을까 싶다.

때문에, 이 소스의 적용은 상황에 따라 잘 적용해야 할 것이다.


신고

댓글

댓글쓰기 폼

2013 이전/iOS개발

[iOS 개발] 안정적이고 flexible 한 UITableViewCell UI 구현하기

hagulu 하구루2017.02.25 16:31

UITableView 를 이용할때 Cell을 Customize 하여 사용하는 경우가 많을 것이다.

 이렇게 사용할때  Cell의 크기에 따라 Cell의 구성요소의 위치와 크기가 다르게 구성하는 경우가 많을 것이다.
 하지만 각각의 Cell을 UI사이즈나 위치가 변경할때 마다 각각의 Cell의 위치나 크기를 매번 새로 적용해주게 되면 여러 문제가 발생할 수가 있다.
 이때, 해당 Cell의 frame만 가지고 구성요소의 위치를 지정해 주게 되면 여러 문제에 봉착하게 된다.

 그래서 Cell을 구성할떄 위치와 크기에 변화가 필요한 것들은 모두  각 UIView에 AutoresizingMask를 적용하여 사용해야 한다. 전체 View가 유기적으로 AutoresizingMask를 적용하지 않아서 전체 적으로 static하게 구성하더라도, Cell은 적어도 AutoresizingMask를 통해서 구성해야 한다.
 Cell의 frame을 이용해서 계산하여 UIView의 위치를 배치하면, 최초 구동시나, 회전하여 구동할때 등 문제가 발생하게 된다.

 그리고 한가지 더 중요한 점이 Cell에서 구성되는 UIView를 Cell의 self에 바로 addSubview하는 경우가 많은데, 꼭! self.contentView에 addSubview 를 해주는 것이 좋다. Grouped UITableView에서 는 cell안에 표시되려면 꼭 필요한 부분이고, Plain이라고 하더라도 적용해 주어야한다. 그렇지 않으면 AutoresizingMask하는 부분이 의도한 대로 진행되지 않을 것이다. 따라서 특정한 경우가 아니라면 꼭 contentView에 addSubview를 해주어야 한다.
 어찌보면 당연한 것이지만, 쉽게 생각하고 무시하고 진행하는 경우가 있기때문에, 이 두 부분은 꼭 기억하고 UIView를 관리 하기 바란다.


신고

댓글

댓글쓰기 폼

2013 이전/iOS개발

[iOS 개발] UIPopoverController 의 EKEventEditViewController 키보드 문제

hagulu 하구루2017.02.25 16:31

iOS5에서 PopoverController위에 EKEventEditViewController를 올려서 사용하다 보면 cancel 버튼이나 done 버튼을 통해서 나왔을때는 문제가 없지만,


UIPopoverController의 바깥 공간을 선택했을때는 UIPopoverController가 사라져도 키보드가 내려가지 않는 문제가 발생한다.

해당 viewController의 view에 endEditing: 을 이용해 보아도 변화가 없다.

구글링을 통해서 일본사이트에서 해결 방법을 찾았다.

일본어는 번역기로도 꽤 읽을 만한 내용이 나온다.

해당 내용은 참고한 사이트에서 문제점을 수정하고 정리한 소스이다.
- (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController {

    EKEventEditViewController *ev = (EKEventEditViewController *)self.popoverController.contentViewController;
    for (UIView* view in [[ev navigationBar] subviews])
    {
        if ([NSStringFromClass([view class]) isEqualToString: @"UINavigationButton"])
        {
            UIButton* btn = (UIButton*)view;
            
            for (UIBarButtonItem* buttonItem in [btn allTargets])
            {
                id target = [buttonItem target];
                SEL sel = @selector(cancel:);
                
                if ([target respondsToSelector: sel])
                {
                    [target performSelector:sel];
                    
                    NSLog(@"target = %@", NSStringFromClass([target class]));
                    NSLog(@"action = %@", NSStringFromSelector(sel));
                    
                }
            }
        }
    }
    
    return YES;   
}

위 소스 처럼 UIPopoverController의 delegate인 "popoverControllerShouldDismissPopover:" 에 추가해주면 된다.

위 소스 내용은 UIPopoverController가 바깥쪽을 선택하여 사라지기 직전에 EKEventEditViewController의 navigation item중에서 selector가 cancel:인 item을 찾아서 cancel: 를 실행해주는 방식이다.

어찌보면 꼼수라고 할 수 있어서 정답이라고는 말할 수 없을것 같다.

혹시 좀더 깔끔한 답을 알게 된다면 다시 포스팅 해보도록 하겠다.


신고

댓글

댓글쓰기 폼

2013 이전/iOS개발

[iOS 개발] 현재 view의 모든 text editing 중단하기

hagulu 하구루2017.02.25 16:30

textfeild 나 textView 등 text를 editing 하는 view를 만들다 보면

키보드등 여러 문제로 골머리를 썩은 경험이 있을것이다.

특히, resignFirstResponder를 통해서 해당 editing을 그만 두려고 해야할때,

cell위에 사용하거나 여러 view가 중첩되어 해당 view의 객체를 컨트롤 하기 힘든경우가 발생할 수 있다.

이때 해당하는 뷰의 모든 subview들의 editing을 그만 두도록 한번에 처리 할수 있는 메소드가 있다.

[targetView endEditing:YES];

위 처럼 해당 뷰의 메소드를 호출하게되면 모든 subview들에 있는 editing이 멈추게 된다.

editing 때문에 올라와 있던 키보드들도 내려가게 된다.


신고

댓글

댓글쓰기 폼

2013 이전/node.js

[node.js] npm을 이용한 module 설치

hagulu 하구루2017.02.25 16:30

node.js 가 최근 많은 각광을 받는 이유 중 가장 큰 이유가 바로 강력한 추가 module들 때문이다.

 

 위 주소 공식사이트를 가보면 알겟지만 현재 18,333개의 모듈들이 들록되어 있다. 게다가 빠른속도록 추가되고 있고, 업데이트도 활발이 이루어 지고 있다. 모듈을 설치하고 사용하는 법은 매우 간단하다.
 node.js 를 설치할때 같이 설치된 npm을 이용하면 간단히 사용 할 수 있다. npm 은 간단한 명령으로 등록된 module을 쉽게 install 하고 update 할 수 있다.
 Mac 의 Mac port 나 Linux 의 apt-get 등의 package 관리 툴들을 이용해 보았다면 낯설지 않게 이용할수 있을것이다.

$npm install socket.io

 위와 같은 명령으로 간단하게 socket.io 를 설치 할 수 있다.
 기본 설치 위치가 /usr/local 으로 되어 permission 문제 때문에 설치가 제대로 이루어 지지 않을 수도 있으니 sudo 를 통해서 하기를 권장한다.

이외에 해당 module을 최신화를 위해 아래와 같이 update 명령을 이용하면 된다.

$npm update socket.io

이외에도 여러 명렁을 통해서 npm을 컨트롤 할 수있다  이들에 대해서는

$npm

위 처럼 command 없이 입력하면 이용가능한 명령어들을 볼 수 있다.
//socket_io.js
var socket = require("socket.io");

socket.listen(8005);

socket.sockets.on('connections', function(socket) {

        socket.emit('news', {hello:'world'});

});

socket.sockets.on('my event', function(data) {
        console.log(data);
});
설치한 module 은 위처럼 require 를 통해서 사용할 수 있다.
위 예제에서는 나중에 socket.io에 대해서 다룰때 다시한번 언급 해보도록 하겠다.

하지만 이대로 소스를 실행하명 다음과 같은 에러를 보게 될것이다.

module.js:337
    throw new Error("Cannot find module '" + request + "'");
          ^
Error: Cannot find module 'socket.io'
    at Function._resolveFilename (module.js:337:11)
    at Function._load (module.js:279:25)
    at Module.require (module.js:359:17)
    at require (module.js:375:17)
    at Object.<anonymous> (/Users/gwanlija/socket_io/socket_io.js:1:76)
    at Module._compile (module.js:446:26)
    at Object..js (module.js:464:10)
    at Module.load (module.js:353:31)
    at Function._load (module.js:311:12)
    at Array.0 (module.js:484:10)

 해당 module 이 없다는 것인데, 방금 설치 했는데 없다니.. 무슨일일까? 바로 디렉토리 문제이다.
 해당 module이 설치된 디렉토리에서 소스를 저장하고 실행해야 해당 module 못찾는다는 위와 같은 에러가 나타나지 않는다. 일반적인 경우라면 /usr/local/lib 의 하위 디렉토리에서 가능하다.
 그런데.. 이렇게만 가능하다면 찝찝할 수 밖에 없다. 내가 원하는 디렉토리에서 실행이 불가능 한걸까?
 방법은 있다 해당하는 module 들을 소스가 들어 있는 디렉토리에 포함시켜야 한다. 이를 간단하게 해주는 것이 바로 package.json 파일이다. 해당 파일은 module 패키지에 대한 여러 정보를 정리 한 파일이다.

자세한 사항은 아래 링크를 확인 하기 바란다.


일단 여기서는 위에서 발생하는 문제의 해결에 필요한 것만 초점을 맞추도록 하겠다.
//package.json
{
  "name": "application-name",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node app"
  },
  "dependencies": {
    "socket.io": "0.9.11"
  }
}
위와 같은  구조로 되어 있다. 윗부분은 보는것처럼 간단한 application 에 대한 정보를 기록한다.

그리고 주목하야 할것이 "dependencies" 항목이다.

socket.io 에 의존하고 있다고 명시하고 있다.
json 문법대로 키 벨류 쌍으로 이용하는 module을 필요하다면 추가로 명시해주면 된다.
이 파일을 소스가 들어 있는 디렉토리에 저장하면 된다.

그리고 해당 디렉토리에서

$npm install

위 처럼 입력하고 수행하면 package.json 의 "dependencies" 에 명시되어 있는 module을 해당 디렉토리에 설치가 되어 진다.
설치가 끝나고 다시한번 소스를 수행해 보면 문제 없이 수행되는것을 확인 할 수 있을 것이다.


신고

댓글

댓글쓰기 폼

hagulu.com

.....

VISITED

Today : 103

Total : 119,814

Lately Comment