본문 바로가기
프로그래밍/iOS

썸네일 처리하기

by 백룡화검 2011. 5. 4.

 일단 시작하기 전에 RSS2.0 표준프로토콜에 썸네일 이미지 태그는 제공되지 않는다.(이유는 RSS의 역할에 대하여 이해하길 권장한다)

태그를 골라내어 model객체에 값을 입력하는 RSSParser로써는 이미지 태그가 제공되지 않는 이상 썸네일 이미지가 지원될 수 없다.

RSSParser는 이런 부분을 로직으로써 어느정도 커버하고 있는데 RSS의 본문에 해당하는 description에서 <IMG> 태그를 찾아 썸네일로써 스스로 제작하여 저장시킨다. 어떻게 구현해야 할까 고민하지 않아도 된다.

105행부터 116행까지의 코드만 추가해준다면 RSSParser ImageDownloader를 활용하여 스스로 이미지를 다운받는다.

RSS의 데이터가 30개라고 생각했을때 우리가 한 화면에 볼 수 있는 데이터의 갯수는 대략 7-8개정도 되겠다. 그럼 하위로 스크롤링이 가능하다는 이야기인데, 유저가 빠르게 스크롤링을 하면서 보고 싶은 화면에서 스크롤을 멈출 것이고, 우리는 이미지가 화면에 보일때 바로 다운로드 받아서 출력하는 것 보다 유저가 보고 싶어 하는 화면의 이미지들을 우선으로 로딩해 보여준다면 조금 더 친절한 UX가 될 것이다.

이러한 부분을 감안해 107행에서는 2가지 조건이 만족했을때 이미지 다운로드를 요청하고 있다.

첫번째는 유저가 손으로 스크롤링을 하고 있을 않을때다.

보통 여기까지만 생각하고 이미지를 로딩하면 되지 않을까 생각하기 쉽지만 아이폰에서 제공되는 UITableView는 스크롤시 관성이 적용되게끔 되어 있다. 이런 부분까지 생각하여 유저가 스크롤링을 끝냈고, 관성으로 속도가 줄다가 완전히 멈추었을때의 이미지만 로딩하게끔 고려했던 것이다.

이미지 로딩을 요청하는 방법은 간단하다.

parser startIconDownload 의 인자로 사용중인 model객체와 forIndexPath의 인자로 몇번째 RSS데이터인지를 식별할 수 있는 indexPath만 넘겨주면 끝이다.

ImageDownloader의 로직을 간단히 설명하자면

download요청을 받을 때(startIconDownload) 해당 요청을 자신의 큐 스택에 쌓는다. cpu의 자원점유율을 제한하여 버벅거림 현상을 방지하기 위하여 큐 스택에 쌓여있는 요청을 순차적으로 하나씩 처리한다.

(이러한 처리를 하지 않는다면 한 화면에 8개의 셀이 보일 경우 8개의 이미지를 거의 동시적으로 웹에서 다운로드 받게 된다. cpu ram이 넉넉치 못한 아이폰에서 위와 같은 로직으로 처리된다면 렉현상이 발생할 수 도 있다)

궁금증 하나.

위 샘플을 실행해보면 알겠지만 description본문중에 <IMG> 태그를 찾지 못하는 경우 현재 wikitree의 로고 이미지를 가져오게 설정되어 있다. 이 부분을 자신이 원하는 이미지로 대처하고 싶다면?

RSSParser.m 232행을 수정하면 된다. 본문에서 찾지 못하면 wikitree.co.kr logo_wikitree.gif로 설정되게 되어 있다.

궁금증 둘.

이미지를 못 찾으면 아예 로딩이 안되게끔 하고 싶다면?

RSSParser model imgURL의 속성에 다운받아야 할 이미지 주소를 찾아 입력한다.

위의 모습처럼 model ImgURL 속성에 값이 있을때만 download를 요청하면 된다.

잘 생각해보면 model imgURL값은 널이 될 수가 없다. RSSParser.m 232행에서 이미지 주소가 없으면 위키트리 로고를 다운받게 설정했기 때문이다.

해결 방법은? 그냥 주석처리 하면 끝~

[그림 3-52]같은 본문보기 페이지만 남았다.

해당 셀을 클릭했을때 UINavigationController에 새로운 ViewController를 표시하도록 해줘야 한다.

UITableView에 셀을 클릭했을때 호출되는 delegate 메소드는 아래와 같다.

(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

구현해야 하는 로직을 잠시 말로써 풀어보자면, 우린 특정 로우()이 터치

됐을때  UINavigationController 에 새로운 ViewController를 만들어서 넘겨주어 보여줄것을 요청한다.

요청받은 UINavigationController는 현재 보여주고 있는 ViewController(현재 상태엔 UITableViewController를 상속받은 RSSViewController가 되겠다) 위로 새로 넘겨받은 ViewController를 화면에 표시하게 된다.

화면에 슬라이드되어 오버랩되는 애니메이션과 상단에 뒤로가기 버튼등은 자동 생성이거나 옵션 인자만 추가해주면 되므로 사용법만 익히면 편하게 사용할 수 있겠다.

RSS description의 본문은 대부분 <html>로 구성되어 있다.

html을 화면에 표시 할거라면 safari가 최선책이 될 수 있다. 물런 다른 UIView로도 가능하겠지만, 원문의 이미지 구성을 유지하고 이미지 태그, 그리고 링크까지 그대로 전해야 한다면 웹 브라우져를 뷰어로 활용해야 한다.

(참고)대량의 텍스트 이미지 등을 보여준다면 내장 UIView중 브라우져인 UIWebView가 최고의 퍼포먼스를 보여준다. – 애플이 그렇다고 그랬다.

UIWebView 를 만들어 UINavigationController에 새로운 View꺼리로 제공해주면 우리가 해야 할 일은 끝이다. 당연한 이야기지만 UIWebView model description 속성에 저장되어 있는 본문 태그가 로딩되어야 하겠다.

일단 셀 터치시 넘겨줄 UIWebView를 뷰로 삼을 ViewController를 만들어 보자.

New File 에서 UIViewController를 상속받는 새로운 클래스를 생성하자.

interface builder의 힘을 빌리기 위해 xib 함께 만들기를 체크해도 되지만, 여기까지 잘 따라온 사람이라면 소스코드상에서 UIWebView를 직접 생성해 만들고 있는 UIViewController view로 설정해도 충분하리라 생각된다.

이름은 DetailViewController.

관리하기 쉽게 폴더를 구성하고 그 안에 넣었다.

UIViewController를 상속받은 DetailViewController.

ViewController라는 건 스스로 보여줄 내용이 없는 녀석으로, 뭐가 됐던 UIView를 상속받은 무엇인가를 제공해줘야 한다.

여기서 우린 사파리를 통해 description을 보여줄 생각이므로 UIWebView 를 사용하면 되겠다.

DetailViewController.h 파일의 내용이다.

DetailViewController UIView로 사용할 UIWebView와 본문 내용을 보여줄 NSString을 하나 준비하였다.

DetailViewController가 생성될때 UIWebView를 생성해서 DetailViewController view로써 사용하면 되겠다.

초기화 할때 적당한 메소드는 -(void)viewDidLoad 라고 처음에 이야기 한적 있었다.

클래스의 초기화 작업이므로 DetailViewController가 초기화 될때 UIWebView 를 생성해서 붙이자.

DetailViewController.m 의 일부다.

46 : DetailViewController viewDidLoad delegate가 호출될때 UIWebView를 생성해서

(참고 – initWithFrame size x, y 위치를 기초해 생성하는 생성자이다)

47 : DetailViewController view로 사용되고 있다.

초기화 시켰다면 model description은 어떻게 보여줘야 할 것인가?

셀을 클릭할때 준비해둔 html 속성에 description을 전달해주고

화면에 보이는 순간에 해당 description UIWebView를 통해 로딩하면 되겠다.

UIViewController는 화면에 보이는 순간에 viewDidApper deleage 메소드를 호출한다.

호출되는 순간 html에 내용이 있다면 view로 사용되는 UIWebView를 통해 description의 내용이 담겨있는 html을 로딩한다.

여기서 궁금증.

html에는 <html> 로 구성된 본문이 들어 있다고 했다. 그렇다면 본문을 직접 뿌려준다는 이야긴데 본문 뿌리는 것 대신 특정 url을 로드하려면 어떻게 해야 할까?

간단하다. url을 스트링으로 선언하고 UIWebView loadHTMLString 대신 loadRequest 메소드를 사용하면 된다.

url를 유동적으로 처리하려면 어떻게 해야 하나 물어보는 이는 없을거라 생각한다.

그래도 궁금하다면, html description을 받았던 것 처럼 url도 전달받아 사용하면 되지 않을까?

이제 실행해서 테스트 해보자.

브라보~!  아직 완성도는 떨어지지만 필수 기능은 모두 다 구현이 된 상태고

좀 더 있어보이는 (?!) 앱을 만들기 위해 제목도 설정해보고 메일로 전송하기 버튼도 달아보고

이것 저것 악세사리를 달아보도록 하자.

출처 : http://rulubla.com/bootcamp/2011/05/02/2-%EC%8D%B8%EB%84%A4%EC%9D%BC-%EC%B2%98%EB%A6%AC%ED%95%98%EA%B8%B0/