이 글은 공부한 내용을 정리하는 목적으로 적는 글이오니 건전한 비판은 언제든 환영합니다.
XML 파싱이란
대략적으로 xml 파싱이란 이런 모양으로 생겼다.
<weatherinfo>
<local>
<country>한국</country>
<weather>비</weather>
<temperature>20</temperature>
</local>
<local>
<country>일본</country>
<weather>맑음</weather>
<temperature>19</temperature>
</local>
<local>
<country>중국</country>
<weather>눈</weather>
<temperature>14</temperature>
</local>
<local>
<country>스페인</country>
<weather>우박</weather>
<temperature>13</temperature>
</local>
<local>
<country>미국</country>
<weather>흐림</weather>
<temperature>2</temperature>
</local>
<local>
<country>영국</country>
<weather>비</weather>
<temperature>10</temperature>
</local>
<local>
<country>프랑스</country>
<weather>흐림</weather>
<temperature>15</temperature>
</local>
<local>
<country>브라질</country>
<weather>흐림</weather>
<temperature>35</temperature>
</local>
<local>
<country>스위스</country>
<weather>맑음</weather>
<temperature>13</temperature>
</local>
<local>
<country>덴마크</country>
<weather>비</weather>
<temperature>2</temperature>
</local>
<local>
<country>스웨덴</country>
<weather>눈</weather>
<temperature>0</temperature>
</local>
<local>
<country>네덜란드</country>
<weather>비</weather>
<temperature>12</temperature>
</local>
<local>
<country>크로아티아</country>
<weather>맑음</weather>
<temperature>30</temperature>
</local>
<local>
<country>필리핀</country>
<weather>맑음</weather>
<temperature>28</temperature>
</local>
<local>
<country>독일</country>
<weather>눈</weather>
<temperature>3</temperature>
</local>
<local>
<country>헝가리</country>
<weather>비</weather>
<temperature>13</temperature>
</local>
<local>
<country>벨기에</country>
<weather>흐림</weather>
<temperature>8</temperature>
</local>
<local>
<country>핀란드</country>
<weather>우박</weather>
<temperature>15</temperature>
</local>
<local>
<country>이탈리아</country>
<weather>맑음</weather>
<temperature>23</temperature>
</local>
</weatherinfo>
위의 글들을 보면 weatherinfo 안에 local이 들어가 있고 local로 감싸는 부분에
country, weather, temperature가 들어가 있으며, 역서 파싱할 것은 local 안에 있는 부분을 꺼내줘야 한다.
파싱할 대상들을 꺼내보기
tableview를 만들고 그 안에 라벨과 이미지 뷰를 넣어놓았다.
그래서 cell파일을 따로 만들어 놓았다.
#import <UIKit/UIKit.h>
@interface WeatherCell : UITableViewCell
@property (strong, nonatomic) IBOutlet UIImageView *imgView;
@property (strong, nonatomic) IBOutlet UILabel *countryLabel;
@property (strong, nonatomic) IBOutlet UILabel *weatherLabel;
@property (strong, nonatomic) IBOutlet UILabel *temperatureLabel;
@end
그리고 ViewController.h 파일에서
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController<NSXMLParserDelegate, UITableViewDataSource,UITableViewDelegate>{
NSXMLParser *parser;
NSMutableArray *datalist;
NSMutableDictionary *detailData;
NSString *elementTemp;
BOOL blank;
}
@end
XMLParserDelegate와 tableDataSource, tableDelegate를 받아주어서 처리하게 만들었다.
이제 ViewController.m 파일에서
#import "ViewController.h"
#import "WeatherCell.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
datalist = [[NSMutableArray alloc]init];
parser = [[NSXMLParser alloc]initWithContentsOfURL:[NSURL URLWithString:@"https://raw.githubusercontent.com/ChoiJinYoung/iphonewithswift2/master/weather.xml"]];
parser.delegate = self;
[parser parse];
NSLog(@"%@",datalist);
}
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict{
NSLog(@"didStartElement : %@", elementName);
if ([elementName isEqualToString:@"local"]) {
detailData = [[NSMutableDictionary alloc]init];
}
elementTemp = elementName;
blank = YES;
}
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if (blank == YES && ![elementTemp isEqualToString:@"local"]) {
NSLog(@"foundCharacters : %@",string);
[detailData setObject:string forKey:elementTemp];
}
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if ([elementName isEqualToString:@"local"]) {
[datalist addObject:detailData];
}
NSLog(@"didEndElement : %@",elementName);
blank = NO;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return datalist.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
WeatherCell *cell = [tableView dequeueReusableCellWithIdentifier:@"weather" forIndexPath:indexPath];
NSDictionary *dicTemp = [datalist objectAtIndex:indexPath.row];
cell.countryLabel.text = [dicTemp objectForKey:@"country"];
NSString *weatherStr = [dicTemp objectForKey:@"weather"];
cell.weatherLabel.text = weatherStr;
cell.temperatureLabel.text = [dicTemp objectForKey:@"temperature"];
if ([weatherStr isEqualToString:@"맑음"]) {
cell.imgView.image = [UIImage imageNamed:@"sunny.png"];
}else if ([weatherStr isEqualToString:@"비"]) {
cell.imgView.image = [UIImage imageNamed:@"rainy.png"];
}else if ([weatherStr isEqualToString:@"흐림"]) {
cell.imgView.image = [UIImage imageNamed:@"cloudy.png"];
}else if ([weatherStr isEqualToString:@"눈"]) {
cell.imgView.image = [UIImage imageNamed:@"snow.png"];
}else{
cell.imgView.image = [UIImage imageNamed:@"blizzard.png"];
}
return cell;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
위와 같이 만들어 주었는데 하나씩 분해하면 먼저 viewDidLoad에서는
- (void)viewDidLoad {
[super viewDidLoad];
datalist = [[NSMutableArray alloc]init];
parser = [[NSXMLParser alloc]initWithContentsOfURL:[NSURL URLWithString:@"https://raw.githubusercontent.com/ChoiJinYoung/iphonewithswift2/master/weather.xml"]];
parser.delegate = self;
[parser parse];
NSLog(@"%@",datalist);
}
먼저 datalist 객체를 생성하여 주고
parser를 xml데이터가 있는 http를 불러와서 delegate를 생성하여 준다.
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict{
NSLog(@"didStartElement : %@", elementName);
if ([elementName isEqualToString:@"local"]) {
detailData = [[NSMutableDictionary alloc]init];
}
elementTemp = elementName;
blank = YES;
}
이 메소드에서는 먼저 <local>이라는 부분에서 안에 있는 것을 파싱해야 하기 때문에 먼저 local이라는 부분을 찾아주고 bool했던 부분을 YES로 바꿔준다.
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if (blank == YES && ![elementTemp isEqualToString:@"local"]) {
NSLog(@"foundCharacters : %@",string);
[detailData setObject:string forKey:elementTemp];
}
}
그리고 local 안에 있는 것을 받아주고 넣어준다.
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if ([elementName isEqualToString:@"local"]) {
[datalist addObject:detailData];
}
NSLog(@"didEndElement : %@",elementName);
blank = NO;
}
마지막에 local이라고 하는 부분을 닫아준다.
이런식으로 parsing을 하면 된다
JSON 파싱
json도 xml파싱과 다르게 json으로 파싱할 수 있다.
{
"weatherinfo": {
"local": [
{
"country": "한국",
"weather": "비",
"temperature": "20"
},
{
"country": "일본",
"weather": "맑음",
"temperature": "19"
},
{
"country": "중국",
"weather": "눈",
"temperature": "14"
},
{
"country": "스페인",
"weather": "우박",
"temperature": "13"
},
{
"country": "미국",
"weather": "흐림",
"temperature": "2"
},
{
"country": "영국",
"weather": "비",
"temperature": "10"
},
{
"country": "프랑스",
"weather": "흐림",
"temperature": "15"
},
{
"country": "브라질",
"weather": "흐림",
"temperature": "35"
},
{
"country": "스위스",
"weather": "맑음",
"temperature": "13"
},
{
"country": "덴마크",
"weather": "비",
"temperature": "2"
},
{
"country": "스웨덴",
"weather": "눈",
"temperature": "0"
},
{
"country": "네덜란드",
"weather": "비",
"temperature": "12"
},
{
"country": "크로아티아",
"weather": "맑음",
"temperature": "30"
},
{
"country": "필리핀",
"weather": "맑음",
"temperature": "28"
},
{
"country": "독일",
"weather": "눈",
"temperature": "3"
},
{
"country": "헝가리",
"weather": "비",
"temperature": "13"
},
{
"country": "벨기에",
"weather": "흐림",
"temperature": "8"
},
{
"country": "핀란드",
"weather": "우박",
"temperature": "15"
},
{
"country": "이탈리아",
"weather": "맑음",
"temperature": "23"
}
]
}
}
오히려 json 파싱이 간편하게 작성할 수 있다.
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>{
NSDictionary *datalist;
NSArray *local;
}
@end
viewController.h 파일에서 이렇게 만들어 주면서
viewController.m 파일에서는
#import "ViewController.h"
#import "WeatherCell.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSError *err;
datalist = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"https://raw.githubusercontent.com/ChoiJinYoung/iphonewithswift2/master/weather.json"]] options:NSJSONReadingAllowFragments error:&err];
local = [[datalist objectForKey:@"weatherinfo"]objectForKey:@"local"];
//NSLog(@"%@",local);
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return local.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
WeatherCell *cell = [tableView dequeueReusableCellWithIdentifier:@"weather" forIndexPath:indexPath];
NSDictionary *dicTemp = [local objectAtIndex:indexPath.row];
cell.countryLabel.text = [dicTemp objectForKey:@"country"];
NSString *weatherStr = [dicTemp objectForKey:@"weather"];
cell.weatherLabel.text = weatherStr;
cell.temperatureLabel.text = [dicTemp objectForKey:@"temperature"];
if ([weatherStr isEqualToString:@"맑음"]) {
cell.imgView.image = [UIImage imageNamed:@"sunny.png"];
}else if ([weatherStr isEqualToString:@"비"]) {
cell.imgView.image = [UIImage imageNamed:@"rainy.png"];
}else if ([weatherStr isEqualToString:@"흐림"]) {
cell.imgView.image = [UIImage imageNamed:@"cloudy.png"];
}else if ([weatherStr isEqualToString:@"눈"]) {
cell.imgView.image = [UIImage imageNamed:@"snow.png"];
}else{
cell.imgView.image = [UIImage imageNamed:@"blizzard.png"];
}
return cell;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
먼저 viewDidLoad에서
- (void)viewDidLoad {
[super viewDidLoad];
NSError *err;
datalist = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"https://raw.githubusercontent.com/ChoiJinYoung/iphonewithswift2/master/weather.json"]] options:NSJSONReadingAllowFragments error:&err];
local = [[datalist objectForKey:@"weatherinfo"]objectForKey:@"local"];
//NSLog(@"%@",local);
}
json 데이터를 불러오고, weatherinfo에서 부분에서 local부분을 알려준다.
그리고 cell 부분에서
WeatherCell *cell = [tableView dequeueReusableCellWithIdentifier:@"weather" forIndexPath:indexPath];
NSDictionary *dicTemp = [local objectAtIndex:indexPath.row];
cell.countryLabel.text = [dicTemp objectForKey:@"country"];
NSString *weatherStr = [dicTemp objectForKey:@"weather"];
cell.weatherLabel.text = weatherStr;
cell.temperatureLabel.text = [dicTemp objectForKey:@"temperature"];
하나씩 key에 대해서 넣어준다.
'Mobile > IOS' 카테고리의 다른 글
iOS 커스텀 프레임워크 만들기 (0) | 2023.09.18 |
---|---|
ViewModel을 이용한 버튼 활성화 방법 (0) | 2022.10.18 |
DispatchQueue (0) | 2022.07.01 |
CocoaPods 에러 Cannot find 'Auth' in scope (0) | 2022.05.04 |
UINavigationController (0) | 2022.04.26 |