[오픈 API] 앱 다운로드 순위를 가져오자 3부 (모바일앱 구현)

  1. [오픈 API] 앱 다운로드 순위를 가져오자 1부 (AppApnnie Api)
  2. [오픈 API] 앱 다운로드 순위를 가져오자 2부 (모바일 앱 설계)
  3. [오픈 API] 앱 다운로드 순위를 가져오자 3부 (모바일 앱 구현)

마지막 시간으로 지난시간에 설계한 부분을 구현하도록 하겠습니다.

  1. BaseViewController 생성
  2. AuthViewController 클래스
  3. ProductViewController 클래스
  4. SalesViewController 클래스

==============================================================================1. BaseViewController는 ViewController에서 자주 사용할 함수들을 정의할 부모 컨트롤러 입니다.
API를 http로 호출하고 받는 함수들을 정의하면, 각각의 ViewController에서 구현하지 않아도 됩니다.

  • requestUrlGet() : AFNetworking를 이용하여, get방식으로 호출하는 함수입니다.
  • receiveAPI() : AFNetworking를 이용하여, get방식으로 호출한 후 받는 함수 입니다.
  • requestUrlGet 함수에서 파라미터와 주소를 호출하면, 받은 결과를 노티피케이션 객체를 생성, 등록하고, receiveAPI에 노티피케이션 객체를 해지해줍니다.
=============================================================================

- (void)requestUrlGet:(NSString*)urlString parameters:(NSDictionary*)parameters className:(NSString*)className apiName:(NSString*)apiName
{
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveAPI:) name:apiName object:nil];
    
    AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc]initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
    manager.requestSerializer = [AFJSONRequestSerializer serializer];
    [manager.requestSerializer setTimeoutInterval:10];
    [manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    [manager.requestSerializer setValue:APPANNIE_API_KEY forHTTPHeaderField:@"Authorization"];
    
    
    NSLog(@"urlString = %@",urlString);

    
    [manager GET:urlString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        NSLog(@"responseObject = %@",responseObject);
         [[NSNotificationCenter defaultCenter] postNotificationName:apiName object:nil userInfo:responseObject];
        
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"error: %@", error.description);
        [[NSNotificationCenter defaultCenter] removeObserver:self name:apiName object:nil];
        

        
        
    }];
    
}

#pragma mark - receiveAPI
- (void)receiveAPI:(NSNotification*)notification
{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:notification.name object:nil];
}
=============================================================================

2. AuthViewController 에서는 account_id를 얻기 위해, APPANNIE_API_KEY을 이용하여, API를 호출하고, 받은 결과를 authModel 모델에 넣습니다. UI는 UITableView를 이용하여, 받은 결과를 보여주며, 테이블에서 선택한 account_id를 ProductViewController로 넘겨줍니다.


  • reqData() : 검색버튼을 누르면 호출되는 함수로, URL를 요청합니다.
  • receiveAPI() : URL로 요청해서 받은 결과를 받는 함수로, authModel를 넣어주고, 테이블을 새로고침 합니다.
  • nextAtcion() : 테이블에서 선택했을때 선택된 index정보로, 배열의 authModel객체의 account_id를  ProductViewController로 넘겨줍니다.


=============================================================================
- (void)reqData
{
    [self requestUrlGet:AUTH_API(@"0") parameters:nil className:NSStringFromClass(self.class) apiName:@"AUTH_API"];
}
- (void)receiveAPI:(NSNotification *)notification
{
    [super receiveAPI:notification];
    
    self.m_authArray=[AuthModel mj_objectArrayWithKeyValuesArray:notification.userInfo[@"accounts"]];
    
    [m_authTableView reloadData];
    
}

#pragma mark - UITableViewDataSource

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [self.m_authArray count];
    
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier =@"AuthCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    
    AuthModel * authModel =[self.m_authArray objectAtIndex:indexPath.row];
    
    
    [cell.textLabel setText:[NSString stringWithFormat:@"%@ (%@)", authModel.account_name, authModel.market]];
    
    
    return cell;
    
}

-(void)nextAtcion:(NSInteger)index
{
    ProductViewController *productViewController =[self.storyboard instantiateViewControllerWithIdentifier:@"ProductViewController"];
    
    AuthModel * authModel =[self.m_authArray objectAtIndex:indexPath.row];
    productViewController.m_AuthModel =authModel;
    
    [self.navigationController pushViewController:productViewController animated:YES];
}
=============================================================================

3. ProductViewController 에서는 product_id를 얻기 위해, account_id을 이용하여, API를 호출하고, 받은 결과를 Product 모델에 넣습니다. UI는 UITableView를 이용하여, 받은 결과를 보여주며, 테이블에서 선택한 product_id와 account_id그전에 얻은 SalesViewController로 넘겨줍니다.

  • reqData() : 검색버튼을 누르면 호출되는 함수로, URL를 요청합니다.
  • receiveAPI() :  URL로 요청해서 받은 결과를 받는 함수로, ProductModel를 넣어주고, 테이블을 새로고침 합니다.
  • nextAtcion() :  테이블에서 선택했을때 선택된 index정보로, 배열의 ProductModel 객체의 product_id와 account_id를  SalesViewController로 넘겨줍니다.


=============================================================================

- (void)reqData
{
    [self requestUrlGet:PRODUCTS_API(self.m_AuthModel.account_id, @"0") parameters:nil className:NSStringFromClass(self.class) apiName:@"PRODUCTS_API"];
}

- (void)receiveAPI:(NSNotification *)notification
{
    [super receiveAPI:notification];
    
    self.m_productArray=[ProductsModel mj_objectArrayWithKeyValuesArray:notification.userInfo[@"products"]];
    
    [m_producTabelView reloadData];
    
}

#pragma mark - UITableViewDataSource

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [self.m_productArray count];
    
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier =@"ProductCell";
    ProductCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    cell.delegate =self;
    cell.tag =indexPath.row;
    ProductsModel * productModel =[self.m_productArray objectAtIndex:indexPath.row];
    
    [cell.m_iconImageView sd_setImageWithURL:[NSURL URLWithString:productModel.icon]];
    [cell.m_productIdLabel setText:productModel.product_id];
    [cell.m_productNameLabel setText:productModel.product_name];
    
    
    return cell;
    
}


#pragma mark - ProductCellCellDelegate
-(void)btnAction:(NSInteger)index
{
    SalesViewController *salesViewController =[self.storyboard instantiateViewControllerWithIdentifier:@"SalesViewController"];
    
    ProductsModel * productModel =[self.m_productArray objectAtIndex:index];
    salesViewController.m_ProductModel =productModel;
    salesViewController.m_AuthModel =self.m_AuthModel;
    
    [self.navigationController pushViewController:salesViewController animated:YES];
}
=============================================================================

4.SalesViewController 에선 넘겨받은 product_id와 account_id 이용하여, Sales API 호출하고 결과를 테이블에 노출합니다. 기간을 선택할 수있는 컴포넌트를 추가하여, 파라미터로 같이 넘겨줍니다.

initView() : 시작, 종료를 선택할 수 있는 UITextfiled를 초기화 해줍니다.
seachAction() : 시작, 종료일을 받아 Sales API를 호출합니다.
receiveAPI() : Sales API 받은 결과를 SalesModel에 넣고, 테이블을 새로고침합니다.
dateAction() : 시작, 종료일이 선택했을때 호출되는 함수로 피커뷰를 띄우고 정보를 저장합니다.


=============================================================================
-(void)initView{
    
    [m_tabelView reloadData];
    
    DatePickerCell *endDateCell = [self getDatePickerCell:1];
    
    NSDate *date =[NSDate date];
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"yyyy-MM-dd"];
    [endDateCell.m_dateBtn setTitle:[formatter stringFromDate:date] forState:UIControlStateNormal];
    
    TextFieldCell *textField = [self getTextFieldCell];
    [textField.m_textField setText:@"kr"];
}

-(void)backAction
{
    [self.navigationController popViewControllerAnimated:YES];
}


-(void)seachAction
{
//    #define SALES_API (accountId,productId,start_date,end_date,page_index) [NSString stringWithFormat:@"%@/accounts/%@/products/%@/sales?
    
    DatePickerCell *startDateCell = [self getDatePickerCell:0];
    DatePickerCell *endDateCell = [self getDatePickerCell:1];
    
    NSString *startDate =startDateCell.m_dateBtn.titleLabel.text;
    NSString *endDate =endDateCell.m_dateBtn.titleLabel.text;
    
    if ([self isNull:startDate])
    {
        startDate = @"2017-04-14";
    }
    else if([startDate isEqualToString:@"시작날짜를 선택하세요"])
    {
        
        [SGAlertView alertViewWithTitle:@"알림"
                               delegate:self
                           contentTitle:@"시작날짜를 선택하세요"
                alertViewBottomViewType:SGAlertViewBottomViewTypeOne];
        
        
        
        return;
    }

    if ([self isNull:endDate])
    {
        endDate = @"";
    }
    
    TextFieldCell *textField = [self getTextFieldCell];
///    NSArray = [textField.textLabel.text componentsSeparatedByString:@","];
    NSString *countries = textField.m_textField.text;
    if (countries.length < 1)
    {
        countries =@"kr";
    }

    [self requestUrlGet:SALES_API(self.m_AuthModel.account_id,
                                  self.m_ProductModel.product_id,
                                  startDate,
                                  endDate,
                                  countries,
                                  @"0") parameters:nil className:NSStringFromClass(self.class) apiName:@"SALES_API"];
}

- (void)receiveAPI:(NSNotification *)notification
{
    [super receiveAPI:notification];
    
     self.m_saleArray=[SalesModel mj_objectArrayWithKeyValuesArray:notification.userInfo[@"sales_list"]];
    
    SalesModel *salesModel =  [self.m_saleArray objectAtIndex:0];
    
    [m_downLabel setText:[NSString stringWithFormat:@"다운로드 : %@", salesModel.units.product.downloads]];
    [m_updateLabel setText:[NSString stringWithFormat:@"업데이트 : %@",salesModel.units.product.updates]];
    
    
}

#pragma mark - UITableViewDataSource

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 3;
    
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    

    if (indexPath.row ==0)
    {
        // 시작 날짜
        static NSString *CellIdentifier =@"DatePickerCell";
        DatePickerCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
        [cell.m_dateBtn setTitle:@"시작날짜를 선택하세요" forState:UIControlStateNormal];
        cell.m_dateBtn.tag =0;
        cell.delegate = self;
        
        return cell;
    }
    else if (indexPath.row ==1)
    {
        static NSString *CellIdentifier =@"DatePickerCell";
        DatePickerCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
        
        [cell.m_dateBtn setTitle:@"종료날짜를 선택하세요" forState:UIControlStateNormal];
        cell.m_dateBtn.tag =1;
        cell.delegate = self;
        // 종료 날짜
        return cell;
        
    }
    else
    {
        // countries
        static NSString *TextFieldCellIdentifier =@"TextFieldCell";
        TextFieldCell *cell = [tableView dequeueReusableCellWithIdentifier:TextFieldCellIdentifier forIndexPath:indexPath];
        [cell.m_textField setPlaceholder:@"국가를 입력해주세요(선택사항)"];
        
        return cell;
    }
    
  
    
}

-(void)dateAction:(NSInteger)index
{
    if(index == 0)
    {
        // 시작
        m_startPicker = [[SGDatePicker alloc] init];
        m_startPicker.isBeforeTime = YES;
        m_startPicker.datePickerMode = UIDatePickerModeDate;
        

//        __weak typeof(self) weakSelf = self;
        
        [m_startPicker didFinishSelectedDate:^(NSDate *selectedDate) {
            NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
            [formatter setDateFormat:@"yyyy-MM-dd"];
            DatePickerCell *datePickerCell =[self getDatePickerCell:0] ;
            [datePickerCell.m_dateBtn setTitle:[formatter stringFromDate:selectedDate] forState:UIControlStateNormal];

            
        }];
        
        [m_startPicker show];
    }
    else{
        // 종료
        m_endPicker = [[SGDatePicker alloc] init];
        m_endPicker.isBeforeTime = YES;
        m_endPicker.datePickerMode = UIDatePickerModeDate;
        
        
//        __weak typeof(self) weakSelf = self;
        
        [m_endPicker didFinishSelectedDate:^(NSDate *selectedDate) {
            NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
            [formatter setDateFormat:@"yyyy-MM-dd"];
            
            DatePickerCell *datePickerCell =[self getDatePickerCell:1] ;
            [datePickerCell.m_dateBtn setTitle:[formatter stringFromDate:selectedDate] forState:UIControlStateNormal];
            
            
        }];
        
        [m_endPicker show];
    }
        
}


-(DatePickerCell*)getDatePickerCell:(NSInteger)index
{
    
    DatePickerCell *datePickerCell;
    
    for (DatePickerCell *cell in m_tabelView.visibleCells)
    {
        if ([cell isKindOfClass:[DatePickerCell class]])
        {

            if (cell.m_dateBtn.tag == index)
            {
                datePickerCell =(DatePickerCell*)cell;
                 break;
            }
        }
    }
    
    return datePickerCell;
}

-(TextFieldCell*)getTextFieldCell
{
    
    TextFieldCell *textFieldCell;
    
    for (TextFieldCell *cell in m_tabelView.visibleCells)
    {
        if ([cell isKindOfClass:[TextFieldCell class]])
        {
            
            textFieldCell =(TextFieldCell*)cell;
            break;
        }
    }
    
    return textFieldCell;
}
=============================================================================

결과 화면 

결과 화면

댓글

주간 인기글

[정보] 인스타그램은 당신의 소리를 '듣고' 있을 수도 있습니다

남산 케이블카 이야기

[Angular] 모델, 값이 바뀌었는데 화면 template 이 업데이트 되지 않을 때 조치 팁

안드로이드에서 당겨서 새로고침(SwipeRefreshLayout) 쉽게 구현하기

Java8 Stream 가이드