UITableViewController가없는 UIRefreshControl


308

즉시 궁금하지는 않지만 호기심이 많지만 하위 UIRefreshControl클래스를 사용하지 않고 새로운 iOS 6 클래스 를 활용하는 은밀한 방법이 UITableViewController있습니까?

나는 종종를 사용 UIViewController와 UITableView서브 뷰와 준수 UITableViewDataSource하고 UITableViewDelegate오히려를 사용하는 것보다 UITableViewController철처.


6
@DaveDeLong : 아니요, Dave, 어떻게해야합니까? 이 페이지 뒷부분에서 자신의 솔루션이 지원되지 않는다고 말하면 올바른 솔루션은 무엇입니까?
— matt

3
@ 매트 그는를 사용해야 UITableViewController하고를 사용하는 API를 요청하는 버그를 제출 UIRefreshControl와 UITableView직접.
— Dave DeLong

31
UITableViewController는 너무 많은 모호하고 틈새 버그와 사소한 뷰 계층 구조의 문제를 가지고 있습니다. TableView 하위 뷰와 함께 표준 VC를 사용하도록 전환하면 마술처럼 사라집니다. "UITVC 사용"은 모든 솔루션 IMHO의 시작이 좋지 않습니다.
— Adam

@Adam 'UITableViewController'를 자식 뷰 컨트롤러로 사용할 때 이러한 버그가 발생합니까? 이런 식으로 사용할 때 문제가 발생하지 않았습니다.
— memmons

답변:


388

직감하고 DrummerB의 영감에 따라 UIRefreshControl인스턴스를 하위 뷰로 간단히 추가하려고했습니다 UITableView. 그리고 그것은 마술처럼 작동합니다!

UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:@selector(handleRefresh:) forControlEvents:UIControlEventValueChanged];
[self.myTableView addSubview:refreshControl];

이것은 UIRefreshControl테이블 뷰 위에 위를 추가 하고 UITableViewController:) 을 사용할 필요없이 예상대로 작동합니다.


편집 : 위의 내용은 여전히 ​​작동하지만 몇 가지 지적했듯이 UIRefreshControl 을이 방법으로 추가 할 때 약간의 "말더듬"이 있습니다. 이에 대한 해결책은 UITableViewController를 인스턴스화 한 다음 UIRefreshControl 및 UITableView를 다음과 같이 설정하는 것입니다.

UITableViewController *tableViewController = [[UITableViewController alloc] init];
tableViewController.tableView = self.myTableView;

self.refreshControl = [[UIRefreshControl alloc] init];
[self.refreshControl addTarget:self action:@selector(getConnections) forControlEvents:UIControlEventValueChanged];
tableViewController.refreshControl = self.refreshControl;

48
참고로, 이는 지원되지 않는 동작이며 향후 변경 될 수 있습니다. Apple이 제공하는 유일한 보증은 제공된 api (이 경우 -[UITableViewController setRefreshControl:]) 에 따라 사용하는 것이 계속 작동한다는 것입니다.
— Dave DeLong

18
이 구현으로 트리거하기 직전 handleRefresh:에 스크롤 뷰의 값이 예기치 않게 변경되는 것처럼 보입니다 contentInsets. 다른 사람이 이것을 경험하거나 해결해야합니까? (그래, 나는 이것이 처음에는 지원되지 않는다는 것을 안다!)
— Tim

6
이것을 위해 단순히 컨테이너 뷰를 사용해야합니다. 뷰 컨트롤러의 클래스를 커스텀 서브 클래스로 설정 UITableViewController하면 "올바로 작동"하게됩니다.
— 유진

3
iOS7 (iOS6에 알려지지 않음)에서 앱을 닫았다가 다시 열 때를 ​​제외하고 편집 된 버전이 제대로 작동합니다. 두 번째로 새로 고침 할 때까지 애니메이션이 재생되지 않습니다. 앱을 다시 연 후 처음으로 새로 고침하는 방법은 앱을 얼마나 아래로 당기는가에 따라 증분 원 대신 전체 원입니다. 수정이 있습니까?
— david2391

30
UITableViewController를 여전히 우회하면서 위에서 언급 한대로 "버 거림"을 피하려면 다음과 같이 테이블보기 아래에 새로 고침 제어를 추가하십시오 [_tableView insertSubview:_refreshControl atIndex:0];. iOS 7과 8에서 테스트
— ;;

95

허용 대답에 의해 발생하는 더듬을 제거하기 위해, 당신은 당신을 할당 할 수 있습니다 UITableViewA를 UITableViewController.

_tableViewController = [[UITableViewController alloc]initWithStyle:UITableViewStylePlain];
[self addChildViewController:_tableViewController];

_tableViewController.refreshControl = [UIRefreshControl new];
[_tableViewController.refreshControl addTarget:self action:@selector(loadStream) forControlEvents:UIControlEventValueChanged];

_theTableView = _tableViewController.tableView;

편집하다:

더듬 지 않고을 추가 UIRefreshControl하지 UITableViewController않고 테이블 뷰에서 데이터를 새로 고친 후 멋진 애니메이션을 유지하는 방법입니다.

UIRefreshControl *refreshControl = [UIRefreshControl new];
[refreshControl addTarget:self action:@selector(handleRefresh:) forControlEvents:UIControlEventValueChanged];
[self.theTableView addSubview:refreshControl];
[self.theTableView sendSubviewToBack:refreshControl];

나중에 새로 고친 데이터를 처리 할 때 ...

- (void)handleRefresh:(UIRefreshControl *)refreshControl {
    [self.theTableView reloadData];
    [self.theTableView layoutIfNeeded];
    [refreshControl endRefreshing];
}

7
새로운 UITableView를 만들 필요조차 없습니다. initWithStyle : existingTableView.style이라고 말한 다음 newTableViewController.tableView = existingTableView를 수행하고 refreshControl을 할당하십시오. 이것을 세 줄로 끓입니다.
— Trenskow 2013

[_tablewViewController didMoveToParentViewController:self];서브 뷰를 추가 한 후 전화하는 것을 잊지 마십시오 .
— qix

4
self.tableView = _tableViewController.tableView;해야_tableViewController.tableView = self.tableView
— 알리

@Linus는 왜 필요한가? 내 커스텀 viewController의 viewDidLoad 메소드에서 _tableViewController.view를 subView로 추가했는데 트릭을 수행하는 것처럼 보였습니다. _tableViewController.tableView를 설정할 필요조차 없습니다
— taber

UITableViewController를 사용할 수 없으며 테이블보기가있는 UIViewController를 사용하는 이유입니다. stackoverflow.com/questions/18900428/…
— lostintranslation 14 년

21

시도하는 것은 사용중인 ViewController 내부의 컨테이너보기를 사용하는 것입니다. 전용 테이블 뷰로 깨끗한 UITableViewController 서브 클래스를 정의하고 ViewController에 배치 할 수 있습니다.


2
정확하게, 가장 깨끗한 방법은 UITableViewController 유형의 자식보기 컨트롤러를 추가하는 것 같습니다.
— Zdenek

그런 다음을 사용하여 UITableViewController를 가져올 수 있습니다 self.childViewControllers.firstObject.
— cbh2000

^ prepareForSegue스토리 보드에서 인스턴스화 할 때 segue 이벤트로 즉시 트리거되므로 컨테이너보기에서 UITableViewController 객체에 대한 참조를 얻는 데 사용할 수도 있습니다 .
— crarho

18

UIRefreshControl은 UIView 하위 클래스이므로 자체적으로 사용할 수 있습니다. 어떻게 렌더링되는지 잘 모르겠습니다. 렌더링은 단순히 프레임에 의존 할 수 있지만 UIScrollView 또는 UITableViewController에 의존 할 수도 있습니다.

어느 쪽이든, 그것은 우아한 솔루션보다 해킹이 될 것입니다. 사용 가능한 타사 복제본 중 하나를 보거나 직접 작성하는 것이 좋습니다.

ODRefreshControl

여기에 이미지 설명을 입력하십시오

슬라임

여기에 이미지 설명을 입력하십시오


1
답장을 보내 주셔서 감사합니다. 그러나 내가 찾던 것이 아닙니다. 그러나 귀하의 게시물의 첫 번째 문장은 해결책이었던 것을 시도하도록 영감을주었습니다!
— 켈러

7
ODRefreshControl은 대단합니다-팁 주셔서 감사합니다! 매우 간단하고 작업을 수행합니다. 물론 애플보다 훨씬 유연합니다. 나는 왜 아무도 APITableViewController, IMO를 전체 API에서 최악의 클래스로 사용하는지 이해하지 못했습니다. 아무것도하지 않지만 뷰를 유연하게 만듭니다.
— n13

그것은 실제로 프로젝트에서 당신이 무엇을 사용하는지에 달려 있습니다.. 하나의 거대한 파일 대신 디버그하는 데 사용됩니다 ..
— kush

@ n13 안녕하세요, UITableViewController를 사용해야하는 좋은 이유는 정적 셀로 디자인 할 수 있기 때문입니다. 불행히도 UIViewController에있는 tableView에서는 사용할 수 없습니다.
— Jean Le Moignan

@JeanLeMoignan iOS 도구 및 라이브러리가 빠르게 변경되어 3 년 전 내 의견이 더 이상 유효하지 않습니다. SnapKit을 사용하여 코드로 모든 사용자 인터페이스를 만드는 것으로 전환했으며 정직하게 인터페이스 빌더에서 10 만 번 클릭하는 것보다 훨씬 효율적입니다. 또한 UITableViewController를 UIViewController로 변경하는 것은 쉽고 1 초 밖에 걸리지 않지만 IB에서는 큰 고통입니다.
— n13

7

-endRefreshNSObject -performSelector:withObject:afterDelay:또는 GCD를 사용하여 tableView가 내용을 다시로드 한 후 새로 고침 컨트롤 메서드에 대한 호출을 1 초 정도 지연하십시오 dispatch_after.

이를 위해 UIRefreshControl에 카테고리를 작성했습니다.

@implementation UIRefreshControl (Delay)

- (void)endRefreshingAfterDelay:(NSTimeInterval)delay {
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        [self endRefreshing];
    });
}

@end

나는 그것을 테스트했고 이것은 Collection Views에서도 작동합니다. 0.01 초 정도의 지연이 충분하다는 것을 알았습니다.

// My data refresh process here while the refresh control 'isRefreshing'
[self.tableView reloadData];
[self.refreshControl endRefreshingAfterDelay:.01];

4
지연과 대기는 정말 나쁜 스타일입니다.
— orkoden

2
@orkoden 동의합니다. 이것은 이미 지원되지 않는에 대한 해결 방법입니다 UIRefreshControl.
— boliva

지연 시간이 훨씬 짧은 메소드를 훨씬 쉽게 호출 할 수 있습니다. [self performSelector:@selector(endRefreshing) withObject:nil afterDelay:0.01]
— orkoden

2
최종 효과는 정확히 동일하며 '해킹'을 더 우아하게 만들지 않습니다. -performSelector:withObject:afterDelay:이것을 사용할 것인지 GCD 를 사용할 것인지는 개인적인 취향에 달려 있습니다.
— boliva

7

iOS 10 스위프트 3.0

간단 해

import UIKit

class ViewControllerA: UIViewController, UITableViewDataSource, UITableViewDelegate {

    @IBOutlet weak var myTableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        myTableView.delegate = self
        myTableView.dataSource = self

        if #available(iOS 10.0, *) {
            let refreshControl = UIRefreshControl()
            let title = NSLocalizedString("PullToRefresh", comment: "Pull to refresh")
            refreshControl.attributedTitle = NSAttributedString(string: title)
            refreshControl.addTarget(self,
                                     action: #selector(refreshOptions(sender:)),
                                     for: .valueChanged)
            myTableView.refreshControl = refreshControl
        }
    }

    @objc private func refreshOptions(sender: UIRefreshControl) {
        // Perform actions to refresh the content
        // ...
        // and then dismiss the control
        sender.endRefreshing()
    }

    // MARK: - Table view data source

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 12
    }


    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)

        cell.textLabel?.text = "Cell \(String(indexPath.row))"
        return cell
    }

}

여기에 이미지 설명을 입력하십시오

iOS 10 UIRefreshControl에 대해 배우려면 여기를 참조하십시오 .


3

새로 고치기 제어를 서브 뷰로 추가하면 섹션 헤더 위에 빈 공간이 작성됩니다.

대신 UITableViewController를 UIViewController에 포함시킨 다음 tableView포함 된 속성과 비올라를 가리 키도록 속성을 변경했습니다 . 최소한의 코드 변경. :-)

단계 :

  1. 스토리 보드에서 새 UITableViewController를 만들고 원래 UIViewController에 포함하십시오.
  2. @IBOutlet weak var tableView: UITableView!아래와 같이 새로 내장 된 UITableViewController의 것으로 교체하십시오.

class MyViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    weak var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let tableViewController = self.childViewControllers.first as! UITableViewController
        tableView = tableViewController.tableView
        tableView.dataSource = self
        tableView.delegate = self

        // Now we can (properly) add the refresh control
        let refreshControl = UIRefreshControl()
        refreshControl.addTarget(self, action: "handleRefresh:", forControlEvents: .ValueChanged)
        tableViewController.refreshControl = refreshControl
    }

    ...
}

2

스위프트 2.2.

먼저 UIRefreshControl ()을 만드십시오.

var refreshControl : UIRefreshControl!

viewDidLoad () 메소드에서 다음을 추가하십시오.

refreshControl = UIRefreshControl()
    refreshControl.attributedTitle = NSAttributedString(string: "Refreshing..")
    refreshControl.addTarget(self, action: #selector(YourUIViewController.refresh(_:)), forControlEvents: UIControlEvents.ValueChanged)
    self.tableView.addSubview(refreshControl)

그리고 새로 고침 기능을

func refresh(refreshControl: UIRefreshControl) {

    // do something ...

    // reload tableView
    self.tableView.reloadData()

    // End refreshing
    refreshControl.endRefreshing()
}

0

조금 다른 또 다른 해결책이 있습니다.

나는 몇 가지보기 계층 문제로 인해 그것을 사용해야했다. 나는 UITableViewController의 tableview b / c를 사용할 때 깨지는보기 계층 구조의 다른 장소로 뷰를 전달 해야하는 기능을 만들고 있었다. self.view)는 일반보기뿐만 아니라 일관성없는 컨트롤러 /보기 계층을 생성하여 충돌을 일으켰습니다.

기본적으로 고유 한 UITableViewController 하위 클래스를 만들고 loadView를 재정 의하여 self.view에 다른 뷰를 할당하고 tableView 속성을 재정 의하여 별도의 tableview를 반환합니다.

예를 들면 다음과 같습니다.

@interface MyTableVC : UITableViewController
@end

@interface MyTableVC ()
@property (nonatomic, strong) UITableView *separateTableView;
@end

@implementation MyTableVC

- (void)loadView {
    self.view = [[UIView alloc] initWithFrame:CGRectZero];
}

- (UITableView *)tableView {
    return self.separateTableView;
}

- (void)setTableView:(UITableView *)tableView {
    self.separateTableView = tableView;
}

@end

Keller의 솔루션과 결합하면 tableView는 이제 VC의 루트 뷰가 아닌 일반 뷰이며 뷰 계층 구조 변경에 대해 더 강력하다는 의미에서 더욱 강력 해집니다. 이런 식으로 사용하는 예 :

MyTableVC *tableViewController = [[MyTableVC alloc] init];
tableViewController.tableView = self.myTableView;

self.refreshControl = [[UIRefreshControl alloc] init];
[self.refreshControl addTarget:self action:@selector(getConnections) forControlEvents:UIControlEventValueChanged];
tableViewController.refreshControl = self.refreshControl;

이것에 대한 또 다른 가능한 사용법이 있습니다.

이 방법으로 서브 클래 싱하면 self.view가 self.tableView와 분리되므로 이제이 UITableViewController를 일반 컨트롤러로 사용하고 UITableView에 서브 뷰를 추가 할 필요없이 self.view에 다른 서브 뷰를 추가 할 수 있습니다. UITableViewController 자식을 갖지 않고 직접 컨트롤러를 UITableViewController의 서브 클래스로 봅니다.

주의해야 할 사항 :

super를 호출하지 않고 tableView 속성을 재정의하므로 필요한 경우주의해야 할 사항이 있습니다. 예를 들어, 위의 예제에서 tableview를 설정하면 self.view에 tableview가 추가되지 않고 원하는 프레임이 설정되지 않습니다. 또한이 구현에는 클래스가 인스턴스화 될 때 제공되는 기본 tableView가 없으며 추가 할 수도 있습니다. 경우에 따라 여기에 포함되지 않으며이 솔루션은 실제로 Keller의 솔루션과 잘 맞습니다.


1
질문은 "UITableViewController 서브 클래스를 사용하지 않고"지정되었으며이 답변은 UITableViewController 서브 클래스에 대한 것입니다.
— Brian

0

이 시도,

위의 솔루션은 훌륭하지만 iOS 9.x까지 iOSTableViewController에서만 tableView.refreshControl을 사용할 수 있으며 iOS 10.x부터 UITableView로 제공됩니다.

스위프트 3으로 작성-

let refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: #selector(FeedViewController.loadNewData), for: UIControlEvents.valueChanged)
// Fix for the RefreshControl Not appearing in background
tableView?.addSubview(refreshControl)
tableView.sendSubview(toBack: refreshControl)

지금까지 최고의 솔루션
— Karthik KM

-1

Keller의 첫 번째 제안은 iOS 7에서 뷰 컨트롤러가 다시 나타난 후 테이블의 삽입이 증가하는 이상한 버그를 유발합니다. uitableviewcontroller를 사용하여 두 번째 답변으로 변경하면 문제가 해결되었습니다.


-6

UITableView 하위보기와 함께 UIViewController를 사용하고 UITableViewDataSource 및 UITableViewDelegate를 준수 할 때 다음을 사용할 수 있습니다.

self.refreshControl = [[UIRefreshControl alloc]init];
[self.refreshControl addTarget:self action:@selector(refresh:) forControlEvents:UIControlEventValueChanged];

9
동의하지 않는다. self.refreshControlA의 속성입니다 UITableViewControllerA, 없습니다 UIViewController.
— Rickster

작동하지 않음, referhControl이 uiviewcontroller에 대해 정의되어 있지 않음
— OMGPOP
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.