UITableView의로드 끝을 감지하는 방법


141

로드가 완료되면 테이블의 오프셋을 변경하고 해당 오프셋은 테이블에로드 된 셀 수에 따라 다릅니다.

uitableview 로딩이 완료된 시점을 아는 것이 SDK에 있습니까? 대리인이나 데이터 소스 프로토콜에는 아무것도 보이지 않습니다.

보이는 셀만로드하기 때문에 데이터 소스 수를 사용할 수 없습니다.


데이터 소스 계수의 조합 'indexPathsForVisibleRows'시도
Swapnil Luktuke

1
"복제되지 않습니다. 데이터 요청 완료가 아니라 보이는 셀의로드에 대해 묻습니다. 허용 된 답변으로 업데이트 참조"
Kev

이 솔루션은 저에게 잘 작동합니다. 당신은 확인 stackoverflow.com/questions/1483581/...
칼레드 Annajar

답변:


224

@RichX 답변으로 향상 : 또는 lastRow모두 가능합니다 . 따라서 코드는 다음과 같습니다.[tableView numberOfRowsInSection: 0] - 1((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).row

-(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if([indexPath row] == ((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).row){
        //end of loading
        //for example [activityIndicator stopAnimating];
    }
}

업데이트 : 글쎄, @htafoya의 의견이 맞습니다. 이 코드가 소스에서 모든 데이터로드의 끝을 감지하도록하려면 그렇지 않지만 원래 질문은 아닙니다. 이 코드는 보이는 모든 셀이 표시되는시기를 감지하기위한 것입니다. willDisplayCell:보다 부드러운 UI를 위해 여기에 사용됩니다 (단일 셀은 일반적으로 willDisplay:통화 후 빠르게 표시됨 ). 로 시도해 볼 수도 있습니다 tableView:didEndDisplayingCell:.


보이는 모든 셀이 언제로드되는지 알기에 훨씬 낫습니다.
Eric

14
그러나 사용자가 스크롤하여 더 많은 셀을 볼 때마다 호출됩니다.
htafoya

이것의 문제는 바닥 글보기를 설명하지 않는다는 것입니다. 대부분의 경우 문제가되지는 않지만 같은 경우 viewForFooterInSection방법 에 동일하게 적용 할 수 있습니다 .
Kyle Clegg

1
@KyleClegg patric.schenke는 귀하의 답변에 대한 의견 중 하나를 언급했습니다. 또한 셀 로딩이 끝날 때 바닥 글이 보이지 않으면 어떻게해야합니까?
folex

27
tableView : didEndDisplayingCell :은 실제로 뷰에서 렌더링이 완료되지 않아 뷰에서 셀을 제거 할 때 호출되지 않습니다. 좋은 분석법 이름이 아닙니다. 문서를 읽어야합니다.
Andrew Raphael

34

스위프트 3 & 4 & 5 버전 :

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if let lastVisibleIndexPath = tableView.indexPathsForVisibleRows?.last {
        if indexPath == lastVisibleIndexPath {
            // do here...
        }
    }
}

1
이 메소드는 데이터를 처음로드 할 때 호출됩니다. 내 경우에는 4 개의 보이는 셀 만 있습니다. 8 행을로드했지만 여전히이 함수가 호출되었습니다. 내가 원하는 때 마지막 행에 대한 사용자 스크롤 아래로 더 많은 데이터를로드하는 것입니다
무하마드 Nayab

안녕하세요 무하마드 Nayab는, 어쩌면 당신은 대체 할 수있는 "경우 indexPath == lastVisibleIndexPath"와 "indexPath.row == yourDataSource.count 경우"
다니엘 Ceglia

1
@DanieleCeglia이 점을 지적 해 주셔서 감사합니다. indexPath == lastVisibleIndexPath && indexPath.row == yourDataSource.count-1이면 이것이 효과가 있습니다. 건배!!!
Yogesh Patel

28

나는 항상이 매우 간단한 솔루션을 사용합니다 :

-(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if([indexPath row] == lastRow){
        //end of loading
        //for example [activityIndicator stopAnimating];
    }
}

마지막 행을 감지하는 방법? 그게 저에게 문제입니다. 어떻게 당신이 그 마지막 행을 if 조건으로 가져 오는지 설명 할 수 있습니까?
Sameera Chathuranga

6
마지막 행은 [tableView numberOfRowsInSection: 0] - 1입니다. 0필요한 값으로 교체해야합니다 . 그러나 그것은 문제가 아닙니다. 문제는 UITableView가 표시되는 것만로드한다는 것입니다. 그러나 ((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).row문제를 해결합니다.
folex

1
절대 완성을 찾고 있다면 사용하지 않는 것이 가장 좋습니다-(void) tableView : (UITableView *) tableView didEndDisplayingCell : (UITableViewCell *) forRowAtIndexPath : (NSIndexPath *) indexPath?
morcutt

10

나를 위해 일하는 것처럼 보이는 또 다른 옵션이 있습니다. viewForFooter 델리게이트 메소드에서 마지막 섹션인지 확인하고 코드를 추가하십시오. 이 방법은 willDisplayCell이 바닥 글이있는 경우 바닥 글을 고려하지 않는다는 것을 인식 한 후에 생각되었습니다.

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section 
{
  // Perform some final layout updates
  if (section == ([tableView numberOfSections] - 1)) {
    [self tableViewWillFinishLoading:tableView];
  }

  // Return nil, or whatever view you were going to return for the footer
  return nil;
}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
  // Return 0, or the height for your footer view
  return 0.0;
}

- (void)tableViewWillFinishLoading:(UITableView *)tableView
{
  NSLog(@"finished loading");
}

이 방법은 UITableView단순히 보이는 셀이 아니라 전체에 대한 최종로드를 찾고자 할 때 가장 효과적 입니다. 필요에 따라 보이는 셀만 원할 수 있으며,이 경우 folex의 대답 은 좋은 경로입니다.


반환 nil에서 tableView:viewForFooterInSection:자동 레이아웃을 사용하여 아이폰 OS 7 내 레이아웃을 엉망.
ma11hew28

흥미 롭군 높이와 너비가 0 인 프레임으로 설정하면 어떻게 되나요? return CGRectMake(0,0,0,0);
Kyle Clegg

나는 그것을 시도하고 심지어 설정했습니다 self.tableView.sectionFooterHeight = 0. 어느 쪽이든, 높이가 약 10 인 섹션 바닥 글 뷰를 삽입하는 것 같습니다. 반환하는 뷰에 0 높이 제약 조건을 추가 하여이 문제를 해결할 수 있습니다. 어쨌든, 실제로 마지막 셀에서 UITableView를 시작하는 방법을 알고 싶었지만 이것을 처음 보았 기 때문에 좋습니다.
ma11hew28

1
@MattDiPasquale viewForFooterInSection을 구현하는 경우 heightForFooterInSection도 구현해야합니다. 바닥 글이 0 인 섹션의 경우 0을 반환해야합니다. 이것은 현재 공식 문서에도 있습니다.
patric.schenke

0으로 heightForFooterInSection를 설정하면 viewForFooterInSection가 호출되지 않습니다
오디드 Harth

10

스위프트 2 솔루션 :

// willDisplay function
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    let lastRowIndex = tableView.numberOfRowsInSection(0)
    if indexPath.row == lastRowIndex - 1 {
        fetchNewDataFromServer()
    }
}

// data fetcher function
func fetchNewDataFromServer() {
    if(!loading && !allDataFetched) {
        // call beginUpdates before multiple rows insert operation
        tableView.beginUpdates()
        // for loop
        // insertRowsAtIndexPaths
        tableView.endUpdates()
    }
}

9

개인 API 사용 :

@objc func tableViewDidFinishReload(_ tableView: UITableView) {
    print(#function)
    cellsAreLoaded = true
}

퍼블릭 API 사용 :

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // cancel the perform request if there is another section
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(tableViewDidLoadRows:) object:tableView];

    // create a perform request to call the didLoadRows method on the next event loop.
    [self performSelector:@selector(tableViewDidLoadRows:) withObject:tableView afterDelay:0];

    return [self.myDataSource numberOfRowsInSection:section];
}

// called after the rows in the last section is loaded
-(void)tableViewDidLoadRows:(UITableView*)tableView{
    self.cellsAreLoaded = YES;
}

더 나은 디자인은 보이는 셀을 세트에 추가하는 것입니다. 테이블이로드되었는지 확인해야하는 경우 대신이 세트 주위에 for 루프를 수행 할 수 있습니다.

var visibleCells = Set<UITableViewCell>()

override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    visibleCells.insert(cell)
}

override func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    visibleCells.remove(cell)
}

// example property you want to show on a cell that you only want to update the cell after the table is loaded. cellForRow also calls configure too for the initial state.
var count = 5 {
    didSet {
        for cell in visibleCells {
            configureCell(cell)
        }
    }
}

다른 것보다 훨씬 나은 솔루션입니다. tableView 재로드가 필요하지 않습니다. 매우 간단하며 마지막 셀이로드 될 때마다 viewDidLoadRows :가 호출되지 않습니다.
매트 허드슨

다른 솔루션은 여러 섹션을 고려하지 않기 때문에 이것은 지금까지 가장 좋은 솔루션입니다
justicepenny

으스스한 의견에 대해 유감이지만이 '마법'은 정확히 무엇입니까? 델리게이트에서 다른 메소드를 호출합니다. 나는 그것을 얻지 못한다.
Lukas Petr

@LukasPetr은 cancel 및 afterDelay를 살펴 봅니다. 이렇게하면 테이블을 완전히로드 한 마지막 섹션을 제외한 모든 섹션에 대해 메소드 호출을 취소 할 수 있습니다.
말할

@malhal 아, 알았어. 언뜻보기에 생각했던 것보다 조금 더 영리합니다.
Lukas Petr

8

Swift 3에서 선택한 답변 버전 :

var isLoadingTableView = true

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if tableData.count > 0 && isLoadingTableView {
        if let indexPathsForVisibleRows = tableView.indexPathsForVisibleRows, let lastIndexPath = indexPathsForVisibleRows.last, lastIndexPath.row == indexPath.row {
            isLoadingTableView = false
            //do something after table is done loading
        }
    }
}

기본 셀을 선택하기 전에 테이블로드가 완료되도록하기 위해 isLoadingTableView 변수가 필요했습니다. 이것을 포함하지 않으면 테이블을 스크롤 할 때마다 코드가 다시 호출됩니다.



3

테이블 뷰가 내용로드를 완료 한 시점을 알기 위해서는 먼저 뷰가 화면에 표시되는 방식에 대한 기본적인 이해가 필요합니다.

앱의 수명주기에는 4 가지 주요 순간이 있습니다.

  1. 앱이 이벤트를 수신함 (터치, 타이머, 차단 발송 등)
  2. 앱이 이벤트를 처리합니다 (제약 조건 수정, 애니메이션 시작, 배경 변경 등).
  3. 앱이 새로운 뷰 계층을 계산합니다
  4. 앱이 뷰 계층을 렌더링하고 표시

2 번과 3 번은 완전히 분리되어 있습니다. 왜 ?성능상의 이유로 수정이 완료 될 때마다 순간 3의 모든 계산을 수행하고 싶지 않습니다.

그래서 나는 당신이 다음과 같은 경우에 직면하고 있다고 생각합니다.

tableView.reloadData()
tableView.visibleCells.count // wrong count oO

무슨 일이야?

다른 뷰와 마찬가지로 테이블 뷰는 내용을 느리게 다시로드합니다. 실제로 reloadData여러 번 호출 하면 성능 문제가 발생하지 않습니다. 테이블 뷰는 델리게이트 구현을 기반으로 컨텐츠 크기 만 다시 계산하고 순간 3이 셀을로드 할 때까지 기다립니다. 이번을 레이아웃 패스라고합니다.

좋아, 레이아웃 패스에 들어가는 방법?

레이아웃 단계에서 앱은 뷰 계층의 모든 프레임을 계산합니다. 참여하려면 전용 방법을 재정의 할 수 있습니다 layoutSubviews, updateLayoutConstraintsA의 등 UIView보기 컨트롤러 서브 클래스와 동등한 방법.

이것이 바로 테이블 뷰가하는 일입니다. layoutSubviews대리자 구현에 따라 재정의 하고 셀을 추가하거나 제거합니다. cellForRow바로 새로운 셀을 추가하고 배치하기 직전에 호출합니다 willDisplay. reloadData테이블 뷰를 호출 하거나 계층 구조에 방금 추가 한 경우 테이블 뷰는이 주요 순간에 프레임을 채우는 데 필요한만큼의 셀을 추가합니다.

자, 이제 테이블 뷰가 내용을 다시로드하는 시점을 아는 방법은 무엇입니까?

이제 테이블 뷰가 서브 뷰 레이아웃을 완료 한 시점을 아는 방법은 무엇입니까?

가장 쉬운 방법은 테이블 뷰의 레이아웃에 들어가는 것입니다.

class MyTableView: UITableView {
    func layoutSubviews() {
        super.layoutSubviews()
        // the displayed cells are loaded
    }
}

이 방법은 테이블 뷰의 수명주기에서 여러 번 호출됩니다. 테이블보기의 스크롤 및 큐 제거 동작으로 인해 셀이 자주 수정, 제거 및 추가됩니다. 그러나 super.layoutSubviews()셀이로드 된 직후에 작동합니다 . 이 솔루션은 willDisplay마지막 인덱스 경로 의 이벤트 를 기다리는 것과 같습니다 . 이 이벤트는 layoutSubviews추가 된 각 셀에 대해 테이블보기를 실행하는 동안 호출 됩니다.

또 다른 방법은 앱이 레이아웃 패스를 마치면 호출되는 것입니다.

설명서에 설명 된대로 다음 옵션을 사용할 수 있습니다 UIView.animate(withDuration:completion).

tableView.reloadData()
UIView.animate(withDuration: 0) {
    // layout done
}

이 솔루션은 작동하지만 레이아웃이 완료된 시간과 블록이 호출 된 시간 사이에 화면이 한 번 새로 고쳐집니다. 이것은 DispatchMain.async솔루션 과 동일 하지만 지정되었습니다.

또는 테이블 뷰의 레이아웃을 강제로 설정하고 싶습니다

모든 뷰가 서브 뷰 프레임을 즉시 계산하도록하는 전용 방법이 있습니다 layoutIfNeeded.

tableView.reloadData()
table.layoutIfNeeded()
// layout done

그러나 이렇게하면 시스템에서 사용하는 지연 로딩이 제거됩니다. 이러한 메소드를 반복해서 호출하면 성능 문제가 발생할 수 있습니다. 테이블 뷰의 프레임이 계산되기 전에 호출되지 않도록하십시오. 그렇지 않으면 테이블 뷰가 다시로드되고 알림이 표시되지 않습니다.


나는 완벽한 해결책이 없다고 생각합니다. 서브 클래 싱 클래스는 문제를 일으킬 수 있습니다. 레이아웃 패스는 위에서부터 시작하여 맨 아래로 이동하므로 모든 레이아웃이 완료되면 알림을 받기가 쉽지 않습니다. 그리고 layoutIfNeeded()성능 문제 등을 만들 수있다하지만 그 옵션을 알고, 당신은 당신의 필요에 맞게됩니다 하나 개의 대안으로 생각 할 수 있어야한다.


1

Swift 3에서 수행하는 방법은 다음과 같습니다.

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    if indexPath.row == 0 {
        // perform your logic here, for the first row in the table
    }

    // ....
}

1

여기 내가 스위프트 3에서 어떻게하는지

let threshold: CGFloat = 76.0 // threshold from bottom of tableView

internal func scrollViewDidScroll(_ scrollView: UIScrollView) {

    let contentOffset = scrollView.contentOffset.y
    let maximumOffset = scrollView.contentSize.height - scrollView.frame.size.height;

    if  (!isLoadingMore) &&  (maximumOffset - contentOffset <= threshold) {
        self.loadVideosList()
    }
}

1

여기 내가 할 일이 있습니다.

  1. 기본 클래스 (rootVC BaseVc 등일 수 있음)에서

    A. "DidFinishReloading"콜백을 보낼 프로토콜을 작성하십시오.

    @protocol ReloadComplition <NSObject>
    @required
    - (void)didEndReloading:(UITableView *)tableView;
    @end

    B. 테이블 뷰를 다시로드하는 일반적인 방법을 작성하십시오.

    -(void)reloadTableView:(UITableView *)tableView withOwner:(UIViewController *)aViewController;
  2. 기본 클래스 메소드 구현에서 reloadData를 호출 한 다음 지연과 함께 delegateMethod를 호출하십시오.

    -(void)reloadTableView:(UITableView *)tableView withOwner:(UIViewController *)aViewController{
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            [tableView reloadData];
            if(aViewController && [aViewController respondsToSelector:@selector(didEndReloading:)]){
                [aViewController performSelector:@selector(didEndReloading:) withObject:tableView afterDelay:0];
            }
        }];
    }
  3. 콜백이 필요한 모든 뷰 컨트롤러에서 재로드 완료 프로토콜을 확인하십시오.

    -(void)didEndReloading:(UITableView *)tableView{
        //do your stuff.
    }

참조 : https://discussions.apple.com/thread/2598339?start=0&tstart=0


0

@ 플렉스 대답이 맞습니다.

그러나 tableView에 한 번에 둘 이상의 섹션이 표시 되면 실패 합니다 .

-(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
   if([indexPath isEqual:((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject])]){
    //end of loading

 }
}

0

Swift에서는 이와 같은 작업을 수행 할 수 있습니다. tableView 끝에 도달 할 때마다 다음 조건이 적용됩니다.

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
        if indexPath.row+1 == postArray.count {
            println("came to last row")
        }
}


0

섹션이 여러 개인 경우 마지막 섹션 (Swift 3)에서 마지막 행을 얻는 방법은 다음과 같습니다.

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if let visibleRows = tableView.indexPathsForVisibleRows, let lastRow = visibleRows.last?.row, let lastSection = visibleRows.map({$0.section}).last {
        if indexPath.row == lastRow && indexPath.section == lastSection {
            // Finished loading visible rows

        }
    }
}

0

우연히 나는이 솔루션에 부딪쳤다.

tableView.tableFooterView = UIView()
tableViewHeight.constant = tableView.contentSize.height

viewDidLoad와 같이 contentSize를 가져 오기 전에 footerView를 설정해야합니다. Btw. footeView를 설정하면 "미사용"구분 기호를 삭제할 수 있습니다


-1

표에 표시 될 총 항목 수 또는 현재 표시되는 총 항목 수를 찾고 있습니까? 어느 쪽이든 .. 나는 모든 데이터 소스 메소드가 호출 된 후 'viewDidLoad'메소드가 실행된다고 믿는다. 그러나 이것은 데이터의 첫 번째로드에서만 작동합니다 (단일 alloc ViewController를 사용하는 경우).


-1

Andrew의 코드를 복사하여 확장하여 테이블에 1 행이있는 경우를 설명합니다. 그것은 지금까지 일하고 있습니다!

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
// detect when all visible cells have been loaded and displayed
// NOTE: iOS7 workaround used - see: http://stackoverflow.com/questions/4163579/how-to-detect-the-end-of-loading-of-uitableview?lq=1
NSArray *visibleRows = [tableView indexPathsForVisibleRows];
NSIndexPath *lastVisibleCellIndexPath = [visibleRows lastObject];
BOOL isPreviousCallForPreviousCell = self.previousDisplayedIndexPath.row + 1 == lastVisibleCellIndexPath.row;
BOOL isLastCell = [indexPath isEqual:lastVisibleCellIndexPath];
BOOL isFinishedLoadingTableView = isLastCell && ([tableView numberOfRowsInSection:0] == 1 || isPreviousCallForPreviousCell);

self.previousDisplayedIndexPath = indexPath;

if (isFinishedLoadingTableView) {
    [self hideSpinner];
}
}

참고 : Andrew의 코드에서 1 섹션 만 사용하므로 명심하십시오.


SO @ jpage4500에 오신 것을 환영합니다. 낮은 응답 포인트와 질문 범프에 대한 내용을 제거하기 위해 귀하의 답변을 편집했습니다. 다른 사용자의 답변을 확장하는 것은 그 자체로 완벽하게 유효한 답변이므로 해당 내용을 생략하여 혼란을 줄일 수 있습니다. 그래도 앤드류에게 신용을 줘서 ​​좋았습니다.
skrrgwasme

-3

iOS7.0x에서는 솔루션이 약간 다릅니다. 여기에 내가 생각해 낸 것이 있습니다.

    - (void)tableView:(UITableView *)tableView 
      willDisplayCell:(UITableViewCell *)cell 
    forRowAtIndexPath:(NSIndexPath *)indexPath
{
    BOOL isFinishedLoadingTableView = [self isFinishedLoadingTableView:tableView  
                                                             indexPath:indexPath];
    if (isFinishedLoadingTableView) {
        NSLog(@"end loading");
    }
}

- (BOOL)isFinishedLoadingTableView:(UITableView *)tableView 
                         indexPath:(NSIndexPath *)indexPath
{
    // The reason we cannot just look for the last row is because 
    // in iOS7.0x the last row is updated before
    // looping through all the visible rows in ascending order 
    // including the last row again. Strange but true.
    NSArray * visibleRows = [tableView indexPathsForVisibleRows];   // did verify sorted ascending via logging
    NSIndexPath *lastVisibleCellIndexPath = [visibleRows lastObject];
    // For tableviews with multiple sections this will be more complicated.
    BOOL isPreviousCallForPreviousCell = 
             self.previousDisplayedIndexPath.row + 1 == lastVisibleCellIndexPath.row;
    BOOL isLastCell = [indexPath isEqual:lastVisibleCellIndexPath];
    BOOL isFinishedLoadingTableView = isLastCell && isPreviousCallForPreviousCell;
    self.previousDisplayedIndexPath = indexPath;
    return isFinishedLoadingTableView;
}

-3

목표 C

[self.tableView reloadData];
[self.tableView performBatchUpdates:^{}
                              completion:^(BOOL finished) {
                                  /// table-view finished reload
                              }];

빠른

self.tableView?.reloadData()
self.tableView?.performBatchUpdates({ () -> Void in

                            }, completion: { (Bool finished) -> Void in
                                /// table-view finished reload
                            })

1
이 방법은 UICollectionView내가 이해하는 한만 사용할 수 있습니다 .
Awesome-o 5

네, 맞아요. UITableView의 beginUpdates는 UICollectionView의 performBatchUpdates : completion과 같습니다. stackoverflow.com/a/25128583/988169
pkc456 10

따라서 질문에 대한 적절하고 유효한 답변을 제공하십시오.
G.Abhisek
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.