wake-up-neo.net

Wie benutze ich Pull, um in Swift zu aktualisieren?

Ich baue einen RSS-Reader mit Swift und muss Pull implementieren, um die Funktionalität neu zu laden.

So versuche ich es zu tun.

class FirstViewController: UIViewController,
    UITableViewDelegate, UITableViewDataSource {

   @IBOutlet var refresh: UIScreenEdgePanGestureRecognizer
   @IBOutlet var newsCollect: UITableView

   var activityIndicator:UIActivityIndicatorView? = nil

   override func viewDidLoad() {
       super.viewDidLoad()
       self.newsCollect.scrollEnabled = true
      // Do any additional setup after loading the view, typically from a nib.

      if nCollect.news.count <= 2{
          self.collectNews()
       }
      else{
          self.removeActivityIndicator()
       }
      view.addGestureRecognizer(refresh)
   }



@IBAction func reload(sender: UIScreenEdgePanGestureRecognizer) {
    nCollect.news = News[]()
    return newsCollect.reloadData()
}

Ich bekomme : 

Die Eigenschaft 'self.refresh' wurde beim Aufruf von super.init nicht initialisiert

Bitte helfen Sie mir, das Verhalten von Gestenerkennern zu verstehen. Ein funktionierender Beispielcode ist eine große Hilfe.

Vielen Dank.

185
xrage

Zum Aktualisieren ziehen ist in iOS integriert. Du könntest das in Swift gerne machen 

var refreshControl = UIRefreshControl()

override func viewDidLoad() {
   super.viewDidLoad()

   refreshControl.attributedTitle = NSAttributedString(string: "Pull to refresh")
   refreshControl.addTarget(self, action: #selector(refresh(_:)), for: UIControl.Event.valueChanged)
   tableView.addSubview(refreshControl) // not required when using UITableViewController
}

@objc func refresh(sender:AnyObject) {
   // Code to refresh table view  
}

Irgendwann könnte man die Erfrischung beenden.

refreshControl.endRefreshing()
491
Anil Varghese

Eine Lösung mit Storyboard und Swift ...

1.) Öffnen Sie die .storyboard-Datei, wählen Sie einen TableViewController in Ihrem Storyboard aus und aktivieren Sie die Funktion TableView Controller - Refreshing in den Dienstprogrammen.

enter image description here

2.) Öffnen Sie die zugehörige UITableViewController-Klasse und fügen Sie die folgende Zeile in die viewDidLoad-Methode ein.

self.refreshControl?.addTarget(self, action: "refresh:", forControlEvents: UIControlEvents.ValueChanged)

ODERin Swift 2.2:

self.refreshControl?.addTarget(self, action: #selector(TestTableViewController.refresh(_:)), forControlEvents: UIControlEvents.ValueChanged)

3.) Fügen Sie die folgende Methode über der viewDidLoad-Methode hinzu

func refresh(sender:AnyObject)
{
    // Updating your data here...

    self.tableView.reloadData()
    self.refreshControl?.endRefreshing()
}
119
Blank

iOS 10 - Swift 3 (Gilt auch für iOS 11 - Swift 4)

Ich möchte eine PRETTY COOL - Funktion erwähnen, die seit iOS 10 enthalten ist.

Für jetzt wird UIRefreshControl direkt in jeder von UICollectionView, UITableView und UIScrollView unterstützt!

Jede dieser Ansichten hat refreshControl instance -Eigenschaft, was bedeutet, dass Sie müssen es nicht mehr als Unteransicht in Ihrer Bildlaufansicht hinzufügen

@IBOutlet weak var collectionView: UICollectionView!

override func viewDidLoad() {
    super.viewDidLoad()

    let refreshControl = UIRefreshControl()
    refreshControl.addTarget(self, action: #selector(doSomething), for: .valueChanged)

    // this is the replacement of implementing: "collectionView.addSubview(refreshControl)"
    collectionView.refreshControl = refreshControl
}

func doSomething(refreshControl: UIRefreshControl) {
    print("Hello World!")

    // somewhere in your code you might need to call:
    refreshControl.endRefreshing()
}

Ich persönlich finde es natürlicher, es als eine Eigenschaft für die Bildlaufansicht zu behandeln, anstatt es als Unteransicht hinzuzufügen, insbesondere weil die einzige geeignete Ansicht als Ubersicht für ein UIRefreshControl-Objekt eine Bildlaufansicht ist nützlich bei der Arbeit mit einer Bildlaufansicht; Aus diesem Grund sollte dieser Ansatz offensichtlicher sein, um die Aktualisierungssteuerungsansicht einzurichten.

Sie haben jedoch immer noch die Möglichkeit, die addSubview basierend auf der iOS-Version zu verwenden:

if #available(iOS 10.0, *) {
  collectionView.refreshControl = refreshControl
} else {
  collectionView.addSubview(refreshControl)
}
61
Ahmad F

Swift 4

var refreshControl: UIRefreshControl!

override func viewDidLoad() {
    super.viewDidLoad()

    refreshControl = UIRefreshControl()
    refreshControl.attributedTitle = NSAttributedString(string: "Pull to refresh")
    refreshControl.addTarget(self, action: #selector(refresh), for: .valueChanged)
    tableView.addSubview(refreshControl) 
}

@objc func refresh(_ sender: Any) {
    //  your code to refresh tableView
}

Und Sie könnten aufhören zu erfrischen mit:

refreshControl.endRefreshing()
34
Gilad Brunfman

In Swift benutze das,

Wenn Sie möchten, dass Pull in WebView aktualisiert wird,

Also versuche diesen Code:

override func viewDidLoad() {
    super.viewDidLoad()
    addPullToRefreshToWebView()
}

func addPullToRefreshToWebView(){
    var refreshController:UIRefreshControl = UIRefreshControl()

    refreshController.bounds = CGRectMake(0, 50, refreshController.bounds.size.width, refreshController.bounds.size.height) // Change position of refresh view
    refreshController.addTarget(self, action: Selector("refreshWebView:"), forControlEvents: UIControlEvents.ValueChanged)
    refreshController.attributedTitle = NSAttributedString(string: "Pull down to refresh...")
    YourWebView.scrollView.addSubview(refreshController)

}

func refreshWebView(refresh:UIRefreshControl){
    YourWebView.reload()
    refresh.endRefreshing()
}
6
Zaid Pathan

Anhils Antwort hat mir sehr geholfen.

Nach weiterem Experimentieren bemerkte ich jedoch, dass die vorgeschlagene Lösung manchmal eine nicht so hübsche UI-Störung verursacht.

Stattdessen habe ich diesen Ansatz * gewählt.

* Schnell 2.1

//Create an instance of a UITableViewController. This will Host your UITableView.
private let tableViewController = UITableViewController()

//Add tableViewController as a childViewController and set its tableView property to your UITableView.
self.addChildViewController(self.tableViewController)
self.tableViewController.tableView = self.tableView
self.refreshControl.addTarget(self, action: "refreshData:", forControlEvents: .ValueChanged)
self.tableViewController.refreshControl = self.refreshControl
5
Leverin

Der Fehler sagt Ihnen, dass refresh nicht initialisiert wird. Beachten Sie, dass Sie refresh nicht optional machen, was in Swift bedeutet, dass haseinen Wert hat, bevor Sie super.init aufrufen (oder implizit aufgerufen wird, was in Ihrem Fall der Fall zu sein scheint). Machen Sie entweder refresh optional (wahrscheinlich, was Sie möchten) oder initialisieren Sie es irgendwie.

Ich würde vorschlagen, die Swift-Einführungsdokumentation erneut zu lesen, die dies ausführlich behandelt.

Eine letzte Sache, die nicht Teil der Antwort ist, wie von @Anil hervorgehoben, ist eine eingebaute Pull-Aktualisierungssteuerung in iOS mit dem Namen UIRefresControl, die möglicherweise einen Blick wert ist.

2
JustSid

Ich habe eine RSS-Feed-App erstellt, in der ich eine Pull To Refresh-Funktion habe, die ursprünglich einige der oben aufgeführten Probleme hatte. 

Aber zu den obigen Antworten der Benutzer habe ich überall nach meinem Anwendungsfall gesucht und konnte ihn nicht finden. Ich habe Daten aus dem Internet heruntergeladen (RSSFeed) und wollte meine TableView der zu aktualisierenden Stories nach unten ziehen. 

Was oben erwähnt wurde, umfasst die richtigen Bereiche, aber mit einigen Problemen, die die Leute haben, habe ich Folgendes getan und es funktioniert sehr gut:

Ich habe @Blankarschs Ansatz gewählt, bin zu meinem main.storyboard gegangen und habe die Tabellensicht zum Aktualisieren gewählt. Was nicht erwähnt wurde, ist das Erstellen von IBOutlet und IBAction, um die Aktualisierung effizient zu verwenden

//Created from main.storyboard cntrl+drag refresh from left scene to assistant editor
@IBOutlet weak var refreshButton: UIRefreshControl

override func viewDidLoad() {
  ...... 
  ......
  //Include your code
  ......
  ......
  //Is the function called below, make sure to put this in your viewDidLoad 
  //method or not data will be visible when running the app
  getFeedData()
}

//Function the gets my data/parse my data from the web (if you havnt already put this in a similar function)
//remembering it returns nothing, hence return type is "-> Void"
func getFeedData() -> Void{
  .....
  .....
}

//From main.storyboard cntrl+drag to assistant editor and this time create an action instead of outlet and 
//make sure arguments are set to none and note sender
@IBAction func refresh() {
  //getting our data by calling the function which gets our data/parse our data
  getFeedData()

  //note: refreshControl doesnt need to be declared it is already initailized. Got to love xcode
  refreshControl?.endRefreshing()
}

Ich hoffe, das hilft jedem, der sich in derselben Situation wie ich befindet

2
Dom Bryan

Ich empfehle eine Erweiterung von Pull To Refresh, die in jeder Klasse verwendet werden kann.

1) Machen Sie eine leere Swift-Datei: Datei - Neu - Datei - Swift-Datei. 

2) Fügen Sie Folgendes hinzu

    //  AppExtensions.Swift

    import Foundation
    import UIKit    

    var tableRefreshControl:UIRefreshControl = UIRefreshControl()    

    //MARK:- VIEWCONTROLLER EXTENSION METHODS
    public extension UIViewController
    {
        func makePullToRefreshToTableView(tableName: UITableView,triggerToMethodName: String){

            tableRefreshControl.attributedTitle = NSAttributedString(string: "TEST: Pull to refresh")
            tableRefreshControl.backgroundColor = UIColor.whiteColor()
            tableRefreshControl.addTarget(self, action: Selector(triggerToMethodName), forControlEvents: UIControlEvents.ValueChanged)
            tableName.addSubview(tableRefreshControl)
        }
        func makePullToRefreshEndRefreshing (tableName: String)
        {
            tableRefreshControl.endRefreshing()
//additional codes

        }
    }    

3) Rufen Sie in Ihrem View Controller diese Methoden auf als: 

  override func viewWillAppear(animated: Bool) {

self.makePullToRefreshToTableView(bidderListTable, triggerToMethodName: "pullToRefreshBidderTable")
}

4) Irgendwann wollten Sie die Aktualisierung beenden:

  func pullToRefreshBidderTable() {
self.makePullToRefreshEndRefreshing("bidderListTable")    
//Code What to do here.
}
OR    
self.makePullToRefreshEndRefreshing("bidderListTable")
1
A.G

Einzelheiten

  • Xcode Version 10.3 (10G8), Swift 5

Eigenschaften

  • Möglichkeit, programmgesteuert "Pull to Refresh" durchzuführen
  • Schutz vor Multi- "Pull to Refresh" -Ereignissen
  • Möglichkeit, die Animation der Aktivitätsanzeige fortzusetzen, wenn der Ansichts-Controller umgeschaltet wird (z. B. im Fall von TabController)

Lösung

import UIKit

class RefreshControl: UIRefreshControl {

    private weak var actionTarget: AnyObject?
    private var actionSelector: Selector?
    override init() { super.init() }

    convenience init(actionTarget: AnyObject?, actionSelector: Selector) {
        self.init()
        self.actionTarget = actionTarget
        self.actionSelector = actionSelector
        addTarget()
    }

    private func addTarget() {
        guard let actionTarget = actionTarget, let actionSelector = actionSelector else { return }
        addTarget(actionTarget, action: actionSelector, for: .valueChanged)
    }

    required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }

    func endRefreshing(deadline: DispatchTime? = nil) {
        guard let deadline = deadline else { endRefreshing(); return }
        DispatchQueue.global(qos: .default).asyncAfter(deadline: deadline) { [weak self] in
            DispatchQueue.main.async { self?.endRefreshing() }
        }
    }

    func refreshActivityIndicatorView() {
        guard let selector = actionSelector else { return }
        let _isRefreshing = isRefreshing
        removeTarget(actionTarget, action: selector, for: .valueChanged)
        endRefreshing()
        if _isRefreshing { beginRefreshing() }
        addTarget()
    }

    func generateRefreshEvent() {
        beginRefreshing()
        sendActions(for: .valueChanged)
    }
}

public extension UIScrollView {

    private var _refreshControl: RefreshControl? { return refreshControl as? RefreshControl }

    func addRefreshControll(actionTarget: AnyObject?, action: Selector, replaceIfExist: Bool = false) {
        if !replaceIfExist && refreshControl != nil { return }
        refreshControl = RefreshControl(actionTarget: actionTarget, actionSelector: action)
    }

    func scrollToTopAndShowRunningRefreshControl(changeContentOffsetWithAnimation: Bool = false) {
        _refreshControl?.refreshActivityIndicatorView()
        guard   let refreshControl = refreshControl,
                contentOffset.y != -refreshControl.frame.height else { return }
        setContentOffset(CGPoint(x: 0, y: -refreshControl.frame.height), animated: changeContentOffsetWithAnimation)
    }

    private var canStartRefreshing: Bool {
        guard let refreshControl = refreshControl, !refreshControl.isRefreshing else { return false }
        return true
    }

    func startRefreshing() {
        guard canStartRefreshing else { return }
        _refreshControl?.generateRefreshEvent()
    }

    func pullAndRefresh() {
        guard canStartRefreshing else { return }
        scrollToTopAndShowRunningRefreshControl(changeContentOffsetWithAnimation: true)
        _refreshControl?.generateRefreshEvent()
    }

    func endRefreshing(deadline: DispatchTime? = nil) { _refreshControl?.endRefreshing(deadline: deadline) }
}

Verwendungszweck

// Add refresh control to UICollectionView / UITableView / UIScrollView
private func setupTableView() {
    let tableView = UITableView()
    // ...
    tableView.addRefreshControll(actionTarget: self, action: #selector(refreshData))
}

@objc func refreshData(_ refreshControl: UIRefreshControl) {
    tableView?.endRefreshing(deadline: .now() + .seconds(3))
}

// Stop refreshing in UICollectionView / UITableView / UIScrollView
tableView.endRefreshing()

// Simulate pull to refresh in UICollectionView / UITableView / UIScrollView
tableView.pullAndRefresh()

Vollständige Probe

Vergessen Sie nicht fügen Sie den Lösungscode hier hinz

import UIKit

class ViewController: UIViewController {

    private weak var tableView: UITableView?

    override func viewDidLoad() {
        super.viewDidLoad()
        setupTableView()
    }

    private func setupTableView() {
        let tableView = UITableView()
        view.addSubview(tableView)
        tableView.translatesAutoresizingMaskIntoConstraints = false
        tableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        tableView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        tableView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
        tableView.dataSource = self
        tableView.delegate = self
        tableView.addRefreshControll(actionTarget: self, action: #selector(refreshData))
        self.tableView = tableView
    }
}

extension ViewController {
    @objc func refreshData(_ refreshControl: UIRefreshControl) {
        print("refreshing")
        tableView?.endRefreshing(deadline: .now() + .seconds(3))
    }
}

extension ViewController: UITableViewDataSource {
    func numberOfSections(in tableView: UITableView) -> Int { return 1 }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 20 }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell()
        cell.textLabel?.text = "\(indexPath)"
        return cell
    }
}

extension ViewController: UITableViewDelegate {
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.pullAndRefresh()
    }
}
1

sie können diese Unterklasse von tableView verwenden:

import UIKit

protocol PullToRefreshTableViewDelegate : class {
    func tableViewDidStartRefreshing(tableView: PullToRefreshTableView)
}

class PullToRefreshTableView: UITableView {

    @IBOutlet weak var pullToRefreshDelegate: AnyObject?
    private var refreshControl: UIRefreshControl!
    private var isFirstLoad = true

    override func willMoveToSuperview(newSuperview: UIView?) {
        super.willMoveToSuperview(newSuperview)

        if (isFirstLoad) {
            addRefreshControl()
            isFirstLoad = false
        }
    }

    private func addRefreshControl() {
        refreshControl = UIRefreshControl()
        refreshControl.attributedTitle = NSAttributedString(string: "Pull to refresh")
        refreshControl.addTarget(self, action: "refresh", forControlEvents: .ValueChanged)
        self.addSubview(refreshControl)
    }

    @objc private func refresh() {
       (pullToRefreshDelegate as? PullToRefreshTableViewDelegate)?.tableViewDidStartRefreshing(self)
    }

    func endRefreshing() {
        refreshControl.endRefreshing()
    }

}

1 - im Interface Builder ändern Sie die Klasse Ihrer tableView in PullToRefreshTableView oder erstellen Sie PullToRefreshTableView programmgesteuert

2 - Implementieren Sie die PullToRefreshTableViewDelegate in Ihrem View-Controller

3 - tableViewDidStartRefreshing(tableView: PullToRefreshTableView) wird in Ihrem View-Controller aufgerufen, wenn die Aktualisierung der Tabellenansicht beginnt

4 - Rufen Sie yourTableView.endRefreshing() auf, um die Aktualisierung zu beenden

0
Chuy47

Für den Pull zum Aktualisieren verwende ich 

DGElasticPullToRefresh 

https://github.com/gontovnik/DGElasticPullToRefresh

Installation

pod 'DGElasticPullToRefresh'

import DGElasticPullToRefresh

und fügen Sie diese Funktion in Ihre Swift-Datei ein und rufen Sie diese Funktion von Ihrem auf 

override func viewWillAppear (_ animiert: Bool)

     func Refresher() {
      let loadingView = DGElasticPullToRefreshLoadingViewCircle()
      loadingView.tintColor = UIColor(red: 255.0/255.0, green: 255.0/255.0, blue: 255.0/255.0, alpha: 1.0)
      self.table.dg_addPullToRefreshWithActionHandler({ [weak self] () -> Void in

          //Completion block you can perfrom your code here.

           print("Stack Overflow")

           self?.table.dg_stopLoading()
           }, loadingView: loadingView)
      self.table.dg_setPullToRefreshFillColor(UIColor(red: 255.0/255.0, green: 57.0/255.0, blue: 66.0/255.0, alpha: 1))
      self.table.dg_setPullToRefreshBackgroundColor(self.table.backgroundColor!)
 }

Und vergessen Sie nicht, die Referenz zu entfernen, während die Ansicht verschwindet

zum Entfernen von Pull zum Aktualisieren fügen Sie diesen Code in Ihr ein 

override func viewDidDisappear (_ animiert: Bool)

override func viewDidDisappear(_ animated: Bool) {
      table.dg_removePullToRefresh()

 }

Und es sieht so aus

 enter image description here

Viel Spaß beim Codieren :)

0

So habe ich es mit Xcode 7.2 zum Laufen gebracht, was meiner Meinung nach ein schwerwiegender Fehler ist. Ich verwende es in meiner UITableViewController in meiner viewWillAppear

refreshControl = UIRefreshControl()
refreshControl!.addTarget(self, action: "configureMessages", forControlEvents: .ValueChanged)
refreshControl!.beginRefreshing()

configureMessages()

func configureMessages() {
    // configuring messages logic here

    self.refreshControl!.endRefreshing()
}

Wie Sie sehen können, muss ich die configureMessage()-Methode nach dem Einrichten meiner UIRefreshControl buchstäblich aufrufen. Danach funktionieren nachfolgende Aktualisierungen einwandfrei.

0
jaytrixz

func pullToRefresh () {

    let refresh = UIRefreshControl()
    refresh.addTarget(self, action: #selector(handleTopRefresh(_:)), for: .valueChanged )
    refresh.tintColor = UIColor.appBlack
    self.tblAddressBook.addSubview(refresh)

}
@objc func handleTopRefresh(_ sender:UIRefreshControl){
    self.callAddressBookListApi(isLoaderRequired: false)
    sender.endRefreshing()
}
0
hiren