반응형

반응형

MPVolumeView *volumeView = [[MPVolumeView alloc] initWithFrame:CGRectMake(0, 0, 320, 20)];


[self.view addSubview:volumeView];


디바이스에서 실행해야 나타남. 시뮬레이터에서는 안 나타남.

반응형
Posted by 컴스터
,
반응형


// 초기화 하는 곳에 다음 코드를 넣어 준다. (시뮬레이터에서는 동작하지 않고 디바이스에서 테스트 해야함.)

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];

반응형
Posted by 컴스터
,
반응형


1. 자신이 읽은 책, 읽는 책, 읽고 싶은 책을 간단히 정리 할 수 있는 앱입니다.


2. 주요기능.

- 읽은 책 관리.
- 읽는 책 관리.

- 읽을 책 관리.

- 책내용 간단히 입력하기(텍스트, 이미지)

- 책표지 및 내용 공유하기.

- 배경화면 취향에 맞게 설정하기.

- 읽은책, 읽는책, 읽을 책 검색기능.

- 네이버, 구글 책 검색 및 추가 기능.

- 네이버 베스트셀러 보기 및 추가 기능.


독서노트 바로가기


https://itunes.apple.com/kr/app/dogseonoteu/id870304942?mt=8


반응형
Posted by 컴스터
,
반응형

성공하는 사람과 성공하지 못하는 사람의 차이점 16가지가 적힌 인포그래픽. ⓒlinked in


성공하는 사람과 그렇지 못하는 사람의 차이점 16가지가 존재한다.

 

라이커블 로컬의 최고경영자 데이브 카펜(Dave Kerpen)은 세계 최대 비즈니스 전문 소셜네트워크 서비스 링크드 인에 자신의 선물 받은 엽서 한 장을 소개했다. 엽서의 내용에는 성공한 사람과 성공하지 못한 사람의 차이점 16가지가 나열돼 있다.

 

당신은 어떤 쪽에 속하는가? 성공하지 못한 사람은 실패한 사람이 아니다. 만약 성공하지 못한 쪽에 속하더라도, 데이브의 조언을 듣고 습관을 서서히 변화시켜보자.

 

1. 변화를 수용 하는가 vs 변화를 두려워하는가

 

변화를 수용하는 것은 사람이 힘들어 하는 일 중 하나이다. 그러나 세상은 매우 빠르고 지속적으로 변화하고 있다. 과학기술 또한 빠른 속도로 변해간다. 변화를 두려워하고 뒤로 숨는 것이 아닌 적극적으로 포용하는 자세가 필요하다.

 

2. 다른 사람의 성공을 원하는가 vs 은밀히 실패하길 바라는가

 

당신이 한 그룹의 일원이 됐을 때 성공하기 위해선 모두가 성공하길 원해야 한다. 동료들의 성장과 성공을 원해야한다. 만약 주위사람의 실패를 원한다면, 그런 실패한 사람과 일하고 싶은가?

  

당신은 웃음이 넘치는가 분노가 넘치는가? 성공한 사람들은 웃음을 잃지 않고 기쁨에 넘친다. ⓒwordpress.com

 

3. 즐거움이 넘치는가 vs 분노가 넘치는가

 

일 을 함에 있어서, 기쁨과 행복이 넘치는 것은 항상 옳다. 이러한 행복은 전염성을 갖고 있어 다른 사람들 또한 기분을 좋게 만든다. 사람들이 행복할수록 일에 집중할 수 있고 성공할 확률이 높아진다. 만약 화를 몸에 지니고 있다면 사람들 주위에 ‘악의 기운’을 퍼뜨리게 되며 성공은 멀어질 것이다.

 

4. 실패에 대한 책임을 지는가 vs 실패의 책임을 남에게 돌리는가

 

삶 에는 오르락내리락 굴곡이 존재한다. 성공적인 리더가 된다는 말은 과거의 실패가 있었다는 것을 존재하고, 만약 실패를 맛보지 않은 사람이라면 후에 언젠간 ‘실패’가 온다는 것을 의미한다. 실패한 경험에 대해 남의 탓으로 돌리는 것이 아닌 자신의 것으로 인정하고 받아들여야 다음에 같은 실패를 경험하지 않을 것이다.

 

5. 아이디어에 대해 말하는가 vs 사람에 대해 말하는가

 

가십은 언제 어디서나 존재한다. 그러나 대부분의 내용은 사실무근이며 부정적이고 시간낭비다. 주변사람을 흉보기보단, 사람들과 일에 대한 아이디어를 공유해라.

  

당신은 좋은 정보가 있을 때 공유하는가? 혼자만 몰래 축적하는가? 성공하는 사람들은 좋은 것이 있으면 공유한다.ⓒinserco.org

 

6. 정보와 자료를 공유하는가 vs 정보와 자료를 축적하는가

우 리는 유치원에서부터 배운다. 장난감을 같이 쓰고 공유하면 착한어린이라고. 사회에서도 마찬가지다. 자신이 갖고 있는 것에 대해 공유하는 것은 성공하는 데 있어 매우 중요한 일이다. 타인과 정보와 자료를 공유한다면 당신은 타인의 정보 또한 얻을 수 있을 것이다. 자신만 보기 위해 좋은 정보를 간직하고 있다면 이기적이며 삶을 짧게 보고 있는 것이다.

 

7. 성공의 공을 사람에게 돌리는가 vs 다른사람의 공을 빼앗는가

 

팀워크는 성공에 있어 매우 중요한 요소이다. 팀을 꾸려 일을 할 때 그들의 공헌에 대해 무시하지 마라. 각 구성원에 대한 공헌을 인정하고 성공의 순간을 함께 누려야 한다.

 

8. 삶의 목표와 계획을 세우는가 vs 목표를 세우지 않는가

 

당 신의 삶에 어디에 있는지 위치를 정확히 파악하지 못한다면 성공에서 멀어질 것이다. 길게는 10년, 짧게는 3년의 예측을 하고 각 연간 계획이 필요하다. 또한 하루단위의 계획 또한 성공을 하는 데 유용한 행동이 될 것이다. 당신의 비전을 확인하고 목표를 종이에 옮겨 적길 당부한다.

 

9. 일기를 쓰는가 vs 일기를 쓰자고 말만 하는가

 

매 일 일기를 쓰면 머리에 문득 떠오르는 아이디어를 적을 수 있고 잊기 쉬운 일들을 기록해 나중에 아이디어로 승화시킬 수 있다. 휴대폰을 이용해 적을 수도 있고, 노트에 직접 적어도 무방하다. 그러나 말로 글을 쓰는 것이 아닌 직접 손을 이용해 남겨라.

  

당신은 매일 책을 읽는가? TV를 보는가? 당신이 읽는 활자는 모두 좋은 학습거리가 된다.ⓒwordpress.com

 

10. 매일 독서를 하는가 vs 매일 TV를 보는가

 

매 일 독서를 하면 하루에 하나 이상 새로운 주제에 대해 깨달음을 얻게 된다. 꼭 책을 읽을 필요는 없다. 블로그의 글, 당신이 가장 좋아하는 잡지, 혹은 책. 당신이 읽는 활자는 모두 좋은 학습거리가 될 것이다. 반면 TV를 보는 것은 좋은 여가거리가 될 순 있지만 성공을 하기엔 큰 도움이 되지 않을 것이다.

 

11. 유연한 관점으로 일을 처리하는가 vs 틀에 박힌 관점으로 일을 처리하는가

 

유연한 사고를 가진 리더는 끊임없이 새로운 경지를 향해 도달해 간다. 그들은 팀 구성과 함께 동기부여, 조직을 어떻게 운영하면 조화로울지에 대해 고민한다. 

 

12. 끊임없이 배우는가 vs 눈앞의 일만 처리하는가

 

쉴 새 없이 배우고 향상시키는 것은 성장하는 유일한 방법이다. 또한 당신의 경쟁자를 앞설 수 있으며 아는 것이 많아지면 유연한 사고를 가질 수 있다.

  

당신은 남을 칭찬하는가? 남을 비판하는가?  칭찬은 상대방에게 기쁨을 준다. ⓒkrcnr.cn

 

13. 남을 칭찬하는가 vs 남을 비판하는가

 

남을 칭찬하는 것은 당신이 그를 아낀다는 것을 보여주는 가장 훌륭한 방법이다. 칭찬은 사람에게 힘을 불어넣어 주며, 기분을 좋게 한다. 비난하는 것은 그 어떤 좋은 결과를 가져오지 못한다.

 

14. 남을 용서하는가 vs 원한을 품는가

 

사람은 누구나 실수를 한다. 실수를 인정하고 용서해야 앞으로 나아갈 수 있다. 분노를 계속 품고 있는 것은 당신에게 이득이 될 것이 하나도 없다.

 

15. To-Be 리스트를 지키는가 vs 무엇을 할지 모르는가

 

To-Be 리스트란 어떤 일을 하기의 To-Do 리스트와는 다른 어떠한 사람이 되고자 하는지에 관한 목록이다. To-Be 리스트는 미래를 계획하는데 필요한 목록이다. “나는 TED의 강연자가 되겠다” “나는 CEO가 될 것이다” 혹은 “나는 좋은 아빠, 좋은 남편이 될 것이다”와 같은 목록을 만들어라.

 

16. 감사하는 마음을 갖고 있는가 vs 세상이나 주위 사람에게 감사할 줄 모르는가

 

매일 매사에 감사하는 마음을 갖고 있다면 틀림없이 당신은 더욱 행복해지고 성공할 것이다. 당신과 매일 마주하는 사람들, 함께 일하는 사람들에게 감사의 마음을 표현해라. 감사는 성공하는 사람들이 가진 가장 큰 공통점이다.


반응형
Posted by 컴스터
,
반응형

건물 주인이 깨진 유리창을 그대로 방치하면
이 건물이 무법천지로 변한다.
곧 깨진 유리창처럼 사소한 것들은
사실은 치명적인 위험을 초래한다.


- 마이클 레진, ‘깨진 유리창의 법칙’에서

반응형
Posted by 컴스터
,
반응형

선진 기업들은 위기관리 능력을 개발하기 위해
‘부정적 상상의 기술’을 사용한다.
위기 사건을 예방하는 데 긍정적 사고는 ‘독약’이다.
즉 ‘괜찮겠지’ ‘설마 일이 그렇게 까지 악화되겠어?’라는
생각은 금물이다.


- 김호, 더랩에이치 대표

반응형
Posted by 컴스터
,
반응형

돌다리든 나무다리든 뭐든지 건너라.
그래서 실패하면 상을 줘라. 실패는 많이 할수록 좋다.
아무 일도 하지 않는 사람 보다
무언가 해보려다 실패한 사람이 훨씬 유능하다.
나는 평소 임직원들에게 실패를 두려워하지 말고
일을 저질러보라고 적극 권장하고 있다.
기업경영에서 실패 경험만큼 귀중한 자산이 없다고
생각하기 때문이다.
실패는 우리에게 주어진 특권이다.


- 이건희 삼성 회장

반응형
Posted by 컴스터
,
반응형

성공한 제자들은 항상 걸음이 빠르다. 즉, 부지런하다.
그들은 언제나 앞자리에 앉는다. 그만큼 적극적이고 진취적이다.
또 그들은 늘 시선을 집중시킨다.
그들은 항상 웃는 얼굴이고, 모든 일에 긍정적이다.


- 미국 남가주대 심리학과 골드 교수

반응형
Posted by 컴스터
,

How to Parse HTML on iOS

IPHONE 2014. 4. 16. 15:58
반응형

This is a blog post by iOS Tutorial Team member Matt Galloway, founder of SwipeStack, a mobile development team based in London, UK. You can also find me on .

Let’s say you want to find some information inside a web page and display it in a custom way in your app.

This technique is called “scraping.” Let’s also assume you’ve thought through alternatives to scraping web pages from inside your app, and are pretty sure that’s what you want to do.

Well then you get to the question – how can you programmatically dig through the HTML and find the part you’re looking for, in the most robust way possible? Believe it or not, regular expressions won’t cut it!

Well, in this tutorial you’ll find out how! You’ll get hands-on experience with parsing HTML into an Objective-C data model that your apps can use.

In fact, you’ll work with some HTML from this very site, downloading a list of tutorials and also a list of the members of the iOS Tutorial Team (who are quite awesome, if I do say so myself).

Even if you are pretty sure you never want to parse HTML in your apps, you might enjoy this tutorial anyway, because it covers some cool things you can do with XML and querying its elements with XPath.

This tutorial assumes some familiarity with Objective-C and iOS programming. If you are a complete beginner, you may wish to check out some of the other tutorials on this site.

Let’s start scraping!

But Wait!

Are you sure that's what you want to be doing?

Are you sure that's what you want to be doing?

Before you begin parsing/scraping web pages in your app, you should first make sure that this is really the best choice for you.

Scraping web pages from your app is not always the best choices because:

  • Do you own the content? If you own the content you’re scraping, no problem. But if you don’t, it’s kinda dodgy legally. You can probably get away with it but there are serious questions here. And remember, IANAL – so for more reading, check out this, this, or even better – check with your lawyer.
  • What if the content changes? Since web pages are dynamic things, remember at the format of the page could change at any time. If you’ve hard-baked assumptions on the format of the web page within your app, it might break your app, and you’d have to wait through the long App Store review cycle to get it fixed.
  • Should you be using a web service instead? If you really want to be getting data from the web, you should consider using a web service instead that can return you nice, beautiful XML or JSON. You could even put the scraping code on the server side instead of in your app. This has a number of advantages, including offloading the heavy lifting to the server side, and only having to perform it 1 time, instead of 1 time per running app instance.
  • So – assuming you’ve thought this all through, and you’re *really sure* this is what you want to do, here’s how! But don’t say we didn’t warn you ;]

    Getting Started: How to Climb Trees

    As you’re probably aware, HTML (HyperText Markup Language) is a markup language (it’s in the name!) that tells browsers how to layout a web page. By its very nature, this content is in a hierarchy that defines where within the page a piece of information is to be displayed.

    You may also be aware of XML (eXtensible Markup Language). This also defines a hierarchy of information, and you may at this point be thinking that perhaps HTML is related to XML. You’d be right to think that, and also wrong!

    There are two flavors of HTML: the one that is pure XML, and the original, where-it-all-started HTML. You can read about the difference over at Wikipedia, but it’s sufficient for the purposes of this tutorial to know that HTML is “sort of” an XML document, but with more relaxed rules.

    Since an XML document has a natural hierarchy in a tree structure, it makes sense to have some kind of language to describe retrieving portions of that tree. This is where XPath comes in. XPath is a language for selecting portions of an XML document. Fortunately for you, it works just as well with an HTML document.

    For example, consider this portion of HTML:

    <html>
      <head>
        <title>Some webpage</title>
      </head>
      <body>
        <p class=”normal”>This is the first paragraph</p>
        <p class=”special”>This is the second paragraph. <b>This is in bold.</b></p>
      </body>
    </html>

    This clearly is in a tree structure that looks like this:

    Based on the above diagram, if you wanted to access the title of the HTML document, then you could use the following XPath expression to walk the tree and return the corresponding node:

    /html/head/title

    This would yield a node with just one child: the text “Some webpage.”

    Similarly, if you wanted to access the second paragraph, you could use the following XPath expression:

    /html/body/p[@class=‘special’]

    This would give you access to the node that represents the portion of the tree underneath <p class=’special’>. Note that you have used the syntax [@class=‘special’] to say that you want the nodes which are at html -> body -> p, where the <p> tag has the “class” attribute set to “special.” If there were more than one <p> tag with that class, then this expression would have returned an array of the nodes. But in this case, there’s only one.

    With that knowledge in hand, you can now write XPath queries to access anything within the tree!

    Getting Started for Real: Libxml2 and Hpple

    Parsing an XML document into a manageable format is a pretty complex process. But never fear, there is a handy little library that’s included in the iOS SDK called libxml2.

    This may sound scary at first. A C library without a pretty Objective-C wrapping?

    Fortunately, thanks to some excellent development, there is an open source library called hpple that wraps libxml2 nicely using Objective-C objects. Hpple wraps the creation of the XML document structure, as well as the XPath querying.

    While you may feel like you have the hiccups every time you see the word, in this tutorial you will be using hpple to parse HTML.

    Start Xcode and go to File\New\Project, select iOS\Application\Master Detail Application and click Next. Set up the project like so:

    • Project name: HTMLParsing
    • Company Identifier: Your usual reverse DNS identifier
    • Class Prefix: Leave blank
    • Device Family: iPhone
    • Use Storyboards: No
    • Use Automatic Reference Counting: Yes
    • Include Unit Tests: No (you’re living life on the edge)

    Click Next and finally, choose a location to save your project.

    Creating the Data Model

    You’re going to be downloading tutorials and contributor names from raywenderlich.com, so it would be nice to have these objects modeled in an Objective-C class for easy access. I know you like to keep your project organized, so create a group in the project called Model under the root HTMLParsing group like so (right-click on the HTMLParsing folder to get the context menu):

    Next create a new file under the Model group by selecting Model, then clicking File\New\File (or right-clicking on the folder and selecting New File…). Select Cocoa Touch\Objective-C class and click Next. Enter “Tutorial” as the class, and make it a subclass of NSObject. Finally, click Next and save it along with the rest of the project.

    Now select Tutorial.h and make the interface look like this:

    @interface Tutorial : NSObject
     
    @property (nonatomic, copy) NSString *title;
    @property (nonatomic, copy) NSString *url;
     
    @end

    Then select Tutorial.m and make the implementation look like this:

    @implementation Tutorial
     
    @synthesize title = _title;
    @synthesize url = _url;
     
    @end

    Now create another class, again under the Model group, and call it “Contributor.” Like before, make it a subclass of NSObject. Then make the interface and implementation look like the following:

    // Interface
    @interface Contributor : NSObject
     
    @property (nonatomic, copy) NSString *name;
    @property (nonatomic, copy) NSString *imageUrl;
     
    @end
     
    // Implementation
    @implementation Contributor
     
    @synthesize name = _name;
    @synthesize imageUrl = _imageUrl;
     
    @end

    Adding the Hpple Code

    Note: If you are comfortable with git, then you might want to consider doing the following by cloning the git repository locally, rather than downloading the ZIP file.

    The hpple project is hosted on GitHub, so open a browser and point it to https://github.com/topfunky/hpple. Click the “ZIP” button to download a ZIP file containing the project. Unzip it and open the resulting folder in Finder. You should see something like this:

    Now create another group under the HTMLParsing group called “hpple,” and drag the TFHpple.h/.m, TFHppleElement.h/.m and XPathQuery.h/.m files to the newly created group. When you do this, make sure that you opt to copy the files to the destination group’s folder and add them to the HTMLParsing target:

    Since hpple makes use of libxml2, you need to tell your project where to find the libxml2 headers, and also to link against it when building.

    To do this, select the project root at the top of the project navigator, go to Build Settings and search for “header search paths.” Enter the value for the Header Search Paths row as $(SDKROOT)/usr/include/libxml2 and press Enter. It should end up looking like this:

    Next select Build Phases and open the “Link Binary With Libraries” section. Click the (+) button and search for libxml2. Select libxml2.dylib and press Add. The project navigator should now look like this:

    If you build and run the project now, everything should compile and link, and you’ll be presented with the standard app that’s created with the Master-Detail Application template you opted to use:

    Sit on Your Arse and Parse

    Now that everything is set up, go ahead and parse some HTML! Your first trick will be to parse http://www.raywenderlich.com/tutorials for a list of tutorials. If you open the site’s homepage in your favorite browser and view the source of the page, you should find something in there like this:

    <div class="content-wrapper">
    <h3>Beginning iPhone Programming</h3>
        <ul>
            <li><a href="/?p=1797">How To Create a Simple iPhone App on iOS 5 Tutorial: 1/3</a></li>
            <li><a href="/?p=1845">How To Create a Simple iPhone App on iOS 5 Tutorial: 2/3</a></li>
            <li><a href="/?p=1888">How To Create a Simple iPhone App on iOS 5 Tutorial: 3/3</a></li>
            <li><a href="/?p=10209">My App Crashed &#8211; Now What? 1/2</a></li>
            <li><a href="/?p=10505">My App Crashed &#8211; Now What? 2/2</a></li>
            <li><a href="/?p=8003">How to Submit Your App to Apple: From No Account to App Store, Part 1</a></li>
            <li><a href="/?p=8045">How to Submit Your App to Apple: From No Account to App Store, Part 2</a></li>
        </ul>
    </div>

    Note: A lot of irrelevant code has been trimmed out for clarity.

    If you draw that in tree format, you come up with something like this:

    Tutorials tree

    It should be clear that you can obtain all the tutorials by finding all the <a> tags within the <li> tags, which are under <ul> tags, which are in the <div> tag with “class=’content-wrapper’.” An XPath expression that obtains these is:

    //div[@class='content-wrapper']/ul/li/a

    Note: The double slash (//) at the front means “search anywhere in the document for the following tag.” This stops you having to go right from the top of the tree down through html, then body, etc.

    Having located all of the <a> tags, you will then be interested in the “href” attributes of the <a> tags, and also the text contents within.

    Open MasterViewController.m and add the following imports at the top, since you will need to use these classes later on:

    #import "TFHpple.h"
    #import "Tutorial.h"
    #import "Contributor.h"

    Next, add the following method above initWithNibName:bundle:, which will load the list of tutorials from raywenderlich.com:

    -(void)loadTutorials {
        // 1
        NSURL *tutorialsUrl = [NSURL URLWithString:@"http://www.raywenderlich.com/tutorials"];
        NSData *tutorialsHtmlData = [NSData dataWithContentsOfURL:tutorialsUrl];
     
        // 2
        TFHpple *tutorialsParser = [TFHpple hppleWithHTMLData:tutorialsHtmlData];
     
        // 3
        NSString *tutorialsXpathQueryString = @"//div[@class='content-wrapper']/ul/li/a";
        NSArray *tutorialsNodes = [tutorialsParser searchWithXPathQuery:tutorialsXpathQueryString];
     
        // 4
        NSMutableArray *newTutorials = [[NSMutableArray alloc] initWithCapacity:0];
        for (TFHppleElement *element in tutorialsNodes) {
            // 5
            Tutorial *tutorial = [[Tutorial alloc] init];
            [newTutorials addObject:tutorial];
     
            // 6
            tutorial.title = [[element firstChild] content];
     
            // 7
            tutorial.url = [element objectForKey:@"href"];
        }
     
        // 8
        _objects = newTutorials;
        [self.tableView reloadData];
    }

    This might look scary, but let’s break it down and see what’s going on:

    1. First you need to download the web page, so you create an NSURL with the appropriate URL string. Then you create an NSData object with the contents of that URL. This means “tutorialsHtmlData” will contain the entire HTML document in raw data form.

      If you wanted, you could create an NSString from this using NSString’s alloc/initWithData:usingEncoding: to see the data. It would be the same as if you were to “view source” in your browser.

      Note:
      dataWithContentsOfURL:
      will block until the data has been returned. This means that the UI will become unresponsive until the data is fetched from the server. A better approach is to use NSURLConnection to asynchronously grab the data, but that’s beyond the scope of this tutorial.

    2. Next you create a TFHpple parser with the data that you downloaded.
    3. Then you set up the appropriate XPath query and ask the parser to search using the query. This will return an array of nodes (in hpple land, these are TFHppleElement objects).
    4. Then you create an array to hold your new tutorial objects and loop over the obtained nodes.
    5. Inside the loop, you first create a new Tutorial object and add it to the array.
    6. Then you get the tutorial’s title from the node’s first child’s contents. If you look back at the tree, you should be able to see that this is the case.
    7. Then you get the tutorial’s URL from the “href” attribute of the node. It’s an <a> tag, so it gives you the linking URL. In our case, this is the tutorial’s URL.
    8. Finally you set _objects on the view controller to the new tutorials array you created, and ask the table view to reload its data.

    Before you build and run, do some spring cleaning on this class to remove some of the default behavior of the template project. Remove the insertNewObject: method, and change viewDidLoad to look like:

    -(void)viewDidLoad {
        [super viewDidLoad];
     
        [self loadTutorials];
    }

    Make the tableView:cellForRowAtIndexPath: look like this:

    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        static NSString *CellIdentifier = @"Cell";
     
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
            cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
        }
     
        Tutorial *thisTutorial = [_objects objectAtIndex:indexPath.row];
        cell.textLabel.text = thisTutorial.title;
        cell.detailTextLabel.text = thisTutorial.url;
     
        return cell;
    }

    Here we simply set the main label and the detail label to the tutorial title and URL.

    Build and run, and you should be greeted with a list of tutorials!

    The Fellowship of the Tutorial

    Next up, you’ll be downloading the list of Ray’s contributors, i.e. the fellowship of the iOS Tutorial Team. If you open http://www.raywenderlich.com/about in your favorite browser and “View Source” again, somewhere in the file you should see something like this:

    <ul class="team-members">
        <li id='mgalloway'>
            <h3>Matt Galloway (Editor, Tutorial Team Member)</h3>
            <img src='/wp-content/images/authors/mgalloway.jpg' alt='Matt Galloway' width='100' height='100'>
        </li>
    </ul>

    In a tree structure, it looks like this:

    Contributors tree

    This time, your corresponding XPath expression looks like this:

    //ul[@class='team-members']/li

    This translates to: get me all the <li> tags which are children of a <ul> tag that has “class=’team-members’”.

    Back in MasterViewController.m, add an instance variable to the class continuation category as follows (the class continuation category is the section beginning with @interface MasterViewController () at the top of the file, right below the imports section):

    @interface MasterViewController () {
        NSMutableArray *_objects;
        NSMutableArray *_contributors;
    }

    You will be adding the contributors to the new _contributors array.

    Next add the following method below loadTutorials in MasterViewController.m:

    -(void)loadContributors {
        // 1
        NSURL *contributorsUrl = [NSURL URLWithString:@"http://www.raywenderlich.com/about"];
        NSData *contributorsHtmlData = [NSData dataWithContentsOfURL:contributorsUrl];
     
        // 2
        TFHpple *contributorsParser = [TFHpple hppleWithHTMLData:contributorsHtmlData];
     
        // 3
        NSString *contributorsXpathQueryString = @"//ul[@class='team-members']/li";
        NSArray *contributorsNodes = [contributorsParser searchWithXPathQuery:contributorsXpathQueryString];
     
        // 4
        NSMutableArray *newContributors = [[NSMutableArray alloc] initWithCapacity:0];
        for (TFHppleElement *element in contributorsNodes) {
            // 5
            Contributor *contributor = [[Contributor alloc] init];
            [newContributors addObject:contributor];
     
            // 6
            for (TFHppleElement *child in element.children) {
                if ([child.tagName isEqualToString:@"img"]) {
                    // 7
                    @try {
                        contributor.imageUrl = [@"http://www.raywenderlich.com" stringByAppendingString:[child objectForKey:@"src"]];
                    }
                    @catch (NSException *e) {}
                } else if ([child.tagName isEqualToString:@"h3"]) {
                    // 8
                    contributor.name = [[child firstChild] content];
                }
            }
        }
     
        // 9
        _contributors = newContributors;
        [self.tableView reloadData];
    }

    This should look familiar. That’s because it’s very similar to the loadTutorials method you wrote! This time, though, there’s a slightly more work that needs to be done to extract the relevant information about the contributors. Here’s what it all means:

    1. Same as before, except this time grabbing a different URL. This time we’re using the main page, so we can get the list of the cool guys and gals on the sidebar.
    2. Again, creating a TFHpple parser.
    3. Execute your desired XPath query.
    4. Create a new array and loop over the found nodes.
    5. Create a new Contributor object and add it to your array.
    6. You need to get at the name and image URL elements from the <h3> and <img> tags, which are children of the <li> tag. So you loop over the children and pull out the relevant details as you find them.
    7. If this child is an <img> tag, then the “src” attribute tells you the image URL. Note that this is wrapped in a @try{}@catch{} because sometimes internally within hpple, an exception is thrown. I hope that will be fixed upstream at some point.
    8. If this child is a <h3> tag, then the first child (the text node) will tell you the name of the contributor.
    9. As before, set the view controller’s _contributors array to the new one you created, and reload the table data.

    All that’s left is to make the table view display the new contributor data. Change the following table view data source methods to look like this:

    -(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
        switch (section) {
            case 0:
                return @"Tutorials";
                break;
            case 1:
                return @"Contributors";
                break;
        }
        return nil;
    }
     
    -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
        return 2;
    }
     
    -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
        switch (section) {
            case 0:
                return _objects.count;
                break;
            case 1:
                return _contributors.count;
                break;
        }
        return 0;
    }
     
    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        static NSString *CellIdentifier = @"Cell";
     
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
            cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
        }
     
        if (indexPath.section == 0) {
            Tutorial *thisTutorial = [_objects objectAtIndex:indexPath.row];
            cell.textLabel.text = thisTutorial.title;
            cell.detailTextLabel.text = thisTutorial.url;
        } else if (indexPath.section == 1) {
            Contributor *thisContributor = [_contributors objectAtIndex:indexPath.row];
            cell.textLabel.text = thisContributor.name;
        }
     
        return cell;
    }

    Finally, add the following at the bottom of your viewDidLoad:

    [self loadContributors];

    Then build and run. You should see a list of not only the tutorials but also the contributors! Great work!

    Where to Go From Here?

    Here is a sample project with all of the code from this tutorial.

    I’ve shown you how to parse some simple HTML into a data model. I showed how to grab various bits of information out of the HTML, but you might want to consider some additions. Can you:

    • Parse each tutorial’s HTML data (i.e. the web page at each Tutorial object’s ‘url’) and extract the contributor who wrote that article?
    • Download the image of each contributor and show it in the table view next to the contributor’s name?
    • Make the phone open Safari to that tutorial’s or contributor’s URL when you tap on each row?
    • Perform the fetching of HTML data and parsing on a background thread so that it doesn’t lock the UI?

    I hope you have enjoyed learning about HTML parsing on iOS. If you have any further questions then I’d love to hear about them in the forums!


    This is a blog post by iOS Tutorial Team member Matt Galloway, founder of SwipeStack, a mobile development team based in London, UK.


    반응형
    Posted by 컴스터
    ,
    반응형

    신은 ‘아무 것도 아닌 사람’을 만들 만큼 한가롭지 않습니다.
    누구나 소중합니다.
    신은 우리 모두 열매 맺기를 바라는 마음으로
    누구에게나 무한한 재능을 주셨습니다.


    - 메리 캐이 애쉬 회장

    반응형
    Posted by 컴스터
    ,


    반응형