UITableViewController के बिना UIRefreshControl


308

बस उत्सुक, क्योंकि यह तुरंत संभव नहीं लगता है, लेकिन वहाँ UIRefreshControlएक UITableViewControllerउपवर्ग का उपयोग किए बिना नए iOS 6 वर्ग का लाभ उठाने के लिए एक डरपोक तरीका है ?

मैं अक्सर UIViewControllerएक UITableViewसबव्यू के साथ उपयोग करता हूं और एक समान उपयोग करने के बजाय UITableViewDataSourceऔर UITableViewDelegateइसके अनुरूप होता हूं UITableViewController


6
@DaveDeLong: नहीं, डेव, उसे क्या करना चाहिए? बाद में इस पृष्ठ पर आप कहते हैं कि उसका समाधान समर्थित नहीं है, इसलिए सही समाधान क्या है?
मैट

3
@matt वह एक का उपयोग करना चाहिए UITableViewControllerऔर एपीआई के UIRefreshControlसाथ एक बग का UITableViewसीधे अनुरोध करने के लिए उपयोग करना चाहिए ।
डेव डोंगलांग

31
UITableViewController पड़ा है (और जारी है) बहुत अस्पष्ट और आला कीड़े और गैर तुच्छ दृश्य पदानुक्रम के साथ समस्याओं ... कि जब आप एक मानक वीसी का उपयोग कर TableView सबव्यू के साथ स्विच करने पर सभी जादुई रूप से गायब हो जाते हैं। "यूआईटीवीसी का उपयोग करें" किसी भी समाधान के लिए एक खराब शुरुआत है, आईएमएचओ।
एडम

@Adam चाइल्ड व्यू कंट्रोलर के रूप में 'UITableViewController' का उपयोग करते समय इन बग्स की सतह का उपयोग करें (इस प्रकार tableViewControllers पदानुक्रम में चारों ओर mucking के बिना अनुकूलन देखने के लिए पहुँच दे)? मैं इस तरह का उपयोग करते समय मुद्दों का सामना कभी नहीं किया है।
मेमन

जवाबों:


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
FYI करें, यह असमर्थित व्यवहार है और भविष्य में बदल सकता है। एकमात्र गारंटी जो ऐप्पल बनाती है वह यह है कि प्रदान की गई एपीआई के अनुसार इसका उपयोग करना (इस मामले में -[UITableViewController setRefreshControl:]) कार्य करना जारी रखेगा।
डेव डोंगलांग

18
इस कार्यान्वयन के साथ, ऐसा लगता है कि ट्रिगर करने से ठीक पहले handleRefresh:स्क्रॉल व्यू के मूल्य में एक अनपेक्षित contentInsetsदूसरे के लिए एक अप्रत्याशित परिवर्तन है । किसी और को यह अनुभव है या इसके लिए एक तय है? (हाँ, मुझे पता है कि यह पहली जगह में असमर्थित है!)
टिम

6
आपको वास्तव में इसके लिए एक कंटेनर दृश्य का उपयोग करना चाहिए। बस अपने कस्टम उपवर्ग के दृश्य नियंत्रक की कक्षा सेट करें UITableViewControllerऔर आप "इसे सही तरीके से" कर रहे होंगे।
यूजीन

3
IOS7 में (iOS6 के लिए अज्ञात) संपादित संस्करण तब ठीक काम करता है, जब आप एप को बंद करते हैं और फिर से खोलते हैं। जब तक आप रिफ्रेश नहीं करते तब तक एनिमेशन नहीं चलता है। ऐप को फिर से खोलने के बाद पहली बार रिफ्रेशिंग, इसके सिर्फ एक पूर्ण चक्र के बजाय वृद्धिशील सर्कल के आधार पर कि आप कितना नीचे खींचते हैं। क्या कोई फिक्स है?
david2391

30
UITableViewController को दरकिनार करते हुए जैसा कि ऊपर बताया गया है, "स्लैटर" होने से बचने के लिए, बस टेबल व्यू के नीचे रिफ्रेश कंट्रोल जोड़ें जैसे [_tableView insertSubview:_refreshControl atIndex:0];:। IOS 7 और 8 दोनों के साथ परीक्षण किया गया;)
ptitvinou

95

स्वीकृत उत्तर के कारण होने वाले हकलाने को समाप्त करने के लिए, आप अपने UITableViewको असाइन कर सकते हैं 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 को केवल कहें: मौजूदाTableView.style - और फिर बाद में newTableViewController.tableView = मौजूदाTableView करें और ताज़ा करेंControl असाइन करें। इसे तीन लाइनों तक उबालते हैं।
Trenskow

[_tablewViewController didMoveToParentViewController:self];सबव्यू जोड़ने के बाद कॉल करना न भूलें ।
क्यूइक्स

4
self.tableView = _tableViewController.tableView;होना चाहिए_tableViewController.tableView = self.tableView
अली ५

@Linus वह परिंदे क्यों है? मैंने अपने कस्टम दृश्य में एक दृश्य के रूप में _tableViewController.view को जोड़ा है नियंत्रक का दृश्यडायोड विधि और वह चाल को करने के लिए लग रहा था। मैं भी करने के लिए सेट _tableViewController.tableView जरूरत नहीं थी
Taber

कारण यह है कि मैं एक UITableViewController उपयोगकर्ता नहीं कर सकता और एक UIViewController w / अंदर तालिका दृश्य का उपयोग कर रहा हूं। stackoverflow.com/questions/18900428/…
खोया हुआ

21

आप जो प्रयास करेंगे, वह आपके द्वारा उपयोग किए जा रहे ViewController के अंदर कंटेनर दृश्य का उपयोग करेगा। आप समर्पित तालिका दृश्य के साथ UITableViewController उपवर्ग को परिभाषित कर सकते हैं और ViewController में रख सकते हैं।


2
संक्षेप में, सबसे साफ तरीका UITableViewController प्रकार के चाइल्ड व्यू कंट्रोलर को जोड़ना प्रतीत होता है।
ज़ेडेनेक

तब आप UITableViewController का उपयोग करके हड़प सकते हैं self.childViewControllers.firstObject
cbh2000

^ आप prepareForSegueकंटेनर दृश्य में UITableViewController ऑब्जेक्ट का संदर्भ प्राप्त करने के लिए उपयोग करने पर विचार करना चाह सकते हैं क्योंकि यह स्टोरीबोर्ड से इंस्टेंटेशन पर एक सेग इवेंट के रूप में तुरंत चालू हो जाता है।
crarho

18

वैसे UIRefreshControl एक UIView उपवर्ग है, इसलिए आप इसे स्वयं उपयोग कर सकते हैं। मुझे यकीन नहीं है, हालांकि यह खुद को कैसे प्रस्तुत करता है। रेंडरिंग केवल फ्रेम पर निर्भर हो सकता है, लेकिन यह UIScrollView या UITableViewController पर भी भरोसा कर सकता है।

किसी भी तरह, यह एक सुरुचिपूर्ण समाधान की तुलना में अधिक हैक होने जा रहा है। मैं आपको उपलब्ध 3 पार्टी क्लोनों में से एक को देखने या अपने खुद के लिखने की सलाह देता हूं।

ODRefreshControl

यहां छवि विवरण दर्ज करें

SlimeRefresh

यहां छवि विवरण दर्ज करें


1
आपकी प्रतिक्रिया के लिए धन्यवाद, लेकिन वास्तव में मैं क्या देख रहा था नहीं। हालाँकि, आपकी पोस्ट का पहला वाक्य मुझे यह बताने के लिए प्रेरित करता है कि क्या समाधान होने के बावजूद क्या हुआ!
केलर

7
ODRefreshControl कमाल है - टिप के लिए धन्यवाद! बहुत सरल है, और काम करता है। और निश्चित रूप से एप्पल की तुलना में बहुत अधिक लचीला है। मुझे कभी समझ में नहीं आया कि कोई भी यूआईटेबल व्यूकंट्रोलर, आईएमओ को पूरे एपीआई में सबसे खराब वर्ग का उपयोग क्यों करेगा। यह (अगले) कुछ भी नहीं करता है, लेकिन आपके विचारों को अनम्य बनाता है।
n13

यह वास्तव में आपकी परियोजना पर निर्भर करता है कि आप वहां क्या उपयोग करते हैं .. मेरे मामले में एक लाभकारी का उपयोग करते हुए परियोजना की जटिलता बढ़ रही थी और अब मैं uitableviewcontroller में बदल गया, जो मेरे कोड को दो खंडों में विभाजित करता है मुझे खुशी है कि मेरे पास 2 छोटी फाइलें हैं एक विशाल फ़ाइल के बजाय डीबग करने के लिए उपयोग किया जा सकता है ..
कुश

@ n13 नमस्ते, UITableViewController का उपयोग करने का एक अच्छा कारण स्थिर कोशिकाओं के साथ डिजाइन करने में सक्षम होना है। UIViewController में रहने वाले तालिका दृश्य में दुर्भाग्य से अनुपलब्ध है।
जीन ले मूइगन

@JeanLeMoignanThe iOS उपकरण और लाइब्रेरी तेज़ी से बदल रहे हैं इसलिए मेरी एक 3 साल पुरानी टिप्पणी अब मान्य नहीं है। मैंने SnapKit के साथ कोड में सभी उपयोगकर्ता इंटरफेस बनाने के लिए स्विच किया है और ईमानदारी से यह इंटरफ़ेस टर्नर में 10 हजार बार क्लिक करने की तुलना में बहुत अधिक कुशल है। UIVableController के UITableViewController को बदलना भी आसान है और केवल एक सेकंड लगता है, जबकि IB में यह एक बड़ा दर्द है।
n13

7

-endRefreshTableView के अपनी सामग्री को पुनः लोड करने के बाद, या तो NSObject -performSelector:withObject:afterDelay:या GCD's का उपयोग करके रीफ्रेशकंट्रोल विधि को कॉल को एक सेकंड के अंश तक करने का प्रयास करें 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

मैंने इसका परीक्षण किया और यह संग्रह दृश्य पर भी काम करता है। मैंने देखा है कि 0.01 सेकंड के रूप में छोटे रूप में एक देरी पर्याप्त है:

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

4
विलंब और प्रतीक्षा वास्तव में खराब शैली है।
orkoden

2
@orkoden मैं सहमत हूँ। यह पहले से असमर्थित उपयोग के लिए एक समाधान है UIRefreshControl

आप एक विधि को विलंब के साथ बहुत आसान कह सकते हैं। [self performSelector:@selector(endRefreshing) withObject:nil afterDelay:0.01]
१६

2
अंतिम प्रभाव बिल्कुल समान है, और 'हैक' को अधिक / कम सुरुचिपूर्ण नहीं बनाता है। इसके लिए उपयोग करना है -performSelector:withObject:afterDelay:या जीसीडी व्यक्तिगत स्वाद के मामले पर निर्भर है।
बोलिवा

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संपत्ति को एम्बेडेड एक, और viola की ओर इंगित करने के लिए बदल दिया ! न्यूनतम कोड बदलता है। :-)

कदम:

  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!

आपके विचार मेंDidLoad () विधि जोड़ें:

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 के टेबलव्यू b / c का उपयोग करते समय टूट जाता है, तालिका दृश्य UITableViewController का मूल दृश्य है self.view) और न केवल एक नियमित दृश्य, इसने असंगत नियंत्रक / दृश्य पदानुक्रम बनाए और दुर्घटना का कारण बना।

मूल रूप से UITableViewController के अपने स्वयं के उपवर्ग बनाएं और self.view को अलग दृश्य देने के लिए loadView और ओवरराइड ओवरराइड करें, और एक अलग तालिका दृश्य वापस करने के लिए 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

जब केलर के समाधान के साथ संयुक्त इस अर्थ में अधिक मजबूत होगा कि टेबल व्यू अब एक नियमित दृश्य है, न कि वीसी का मूल दृष्टिकोण, और दृश्य पदानुक्रमों के खिलाफ अधिक मजबूत होना। इस तरह इसका उपयोग करने का उदाहरण:

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.able को self.tableView से अलग करता है, इसलिए अब इस UITableViewController को एक नियमित नियंत्रक के रूप में उपयोग करना संभव है, और UITableView में साक्षात्कार जोड़ने की विषमताओं के बिना self.view में अन्य साक्षात्कार जोड़ें, इसलिए कोई भी उनके बनाने पर विचार कर सकता है। नियंत्रक UITableViewController बच्चों के बजाय सीधे UITableViewController का एक उपवर्ग देखें।

कुछ चीजें देखने के लिए:

चूंकि हम सुपर को कॉल किए बिना टेबल व्यू की संपत्ति को ओवरराइड कर रहे हैं, इसलिए कुछ चीजें देखने के लिए हो सकती हैं और जहां आवश्यक हो उसे संभालना चाहिए। उदाहरण के लिए, मेरे ऊपर के उदाहरण में टेबलव्यू सेट करने से टेबलव्यू को स्व.व्यू में नहीं जोड़ा जाएगा और उस फ्रेम को सेट नहीं किया जाएगा जिसे आप करना चाहते हैं। इसके अलावा, इस कार्यान्वयन में क्लास के तत्काल होने पर आपको कोई डिफ़ॉल्ट तालिका दृश्य नहीं दिया जाता है, जो कि कुछ ऐसी चीज है जिसे आप जोड़ने पर विचार कर सकते हैं। मैं इसे यहां शामिल नहीं करता हूं क्योंकि यह मामला है, और यह समाधान वास्तव में केलर के समाधान के साथ अच्छी तरह से फिट बैठता है।


1
प्रश्न "UITableViewController उपवर्ग का उपयोग किए बिना" निर्दिष्ट है, और यह उत्तर UITableViewController उपवर्ग के लिए है।
ब्रायन

0

इसे इस्तेमाल करे,

उपरोक्त समाधान ठीक हैं, लेकिन टेबल व्यू.refreshControl केवल UITableViewController के लिए उपलब्ध है, iOS 9.x तक और 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)

अब तक का सर्वश्रेष्ठ समाधान
कार्तिक के.एम.

-1

Keller का पहला सुझाव iOS 7 में एक अजीब बग का कारण बनता है जहां व्यू कंट्रोलर के फिर से आने पर टेबल का इनसेट बढ़ जाता है। Uitableviewcontroller का उपयोग करते हुए, मेरे लिए निश्चित चीजों का उपयोग करते हुए, दूसरे उत्तर में बदलना।


-6

जब आप UITableViewDataSource और UITableViewDatagate और UITableViewDelegate के अनुरूप हो, तो आप निम्न का उपयोग कर सकते हैं

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

9
सहमत नहीं हैं। self.refreshControlएक के लिए एक संपत्ति है UITableViewController, न कि एक UIViewController
रिकस्टर

काम नहीं कर रहा है, referhControl uiviewcontroller के लिए परिभाषित नहीं है
OMGPOP
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.