it-swarm.com.ru

Как использовать pull для обновления в Swift?

Я создаю программу чтения RSS с использованием Swift и мне нужно реализовать функцию pull для перезагрузки.

Вот как я пытаюсь это сделать.

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()
}

Я получаю : 

Свойство self.refresh не инициализируется при вызове super.init

Пожалуйста, помогите мне понять поведение распознавателей жестов. Рабочий пример кода будет отличной помощью.

Благодарю.

185
xrage

Потяните, чтобы обновить встроен в iOS. Вы могли бы сделать это в Swift, как 

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  
}

В какой-то момент вы можете закончить освежиться.

refreshControl.endRefreshing()
491
Anil Varghese

Решение с раскадровкой и Swift ...

1.) Откройте файл .storyboard, выберите TableViewController в раскадровке и «Включите» контроллер табличного представления - функция обновления в утилитах.

enter image description here

2.) Откройте связанный UITableViewController-Class и добавьте следующую строку в viewDidLoad-Method.

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

ИЛИв Swift 2.2:

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

3.) Добавьте следующий метод выше метода viewDidLoad

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

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

iOS 10 - Swift 3 (также применимо для iOS 11 - Swift 4)

Я хотел бы упомянуть функцию PRETTY COOL, которая была включена с iOS 10, а именно:

На данный момент UIRefreshControl поддерживается напрямую в каждом из UICollectionView, UITableView и UIScrollView!

Каждое из этих представлений имеет свойство refreshControl instance, что означает, что больше нет необходимости добавлять его как подпредставление в представлении прокрутки, все, что вам нужно сделать, это:

@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()
}

Лично я считаю более естественным рассматривать его как свойство для представления прокрутки, а не добавлять его как подпредставление, особенно потому, что единственное подходящее представление в качестве суперпредставления для UIRefreshControl - это представление прокрутки, то есть функциональность использования UIRefreshControl полезно при работе с прокруткой; Вот почему этот подход должен быть более очевидным для настройки представления управления обновлением.

Тем не менее, у вас все еще есть возможность использовать addSubview в зависимости от версии iOS:

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
}

И вы можете перестать освежаться с:

refreshControl.endRefreshing()
34
Gilad Brunfman

В Swift использовать это,

Если вы хотите, чтобы тянуть, чтобы обновить в WebView,

Так что попробуйте этот код:

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

Ответ Анхила мне очень помог.

Тем не менее, после дальнейших экспериментов я заметил, что предложенное решение иногда вызывает не очень красивый UI глюк .

Вместо этого, пойти на этот подход * добился цели для меня.

* Swift 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

Ошибка говорит вам, что refresh не инициализирован. Обратите внимание, что вы решили сделать refresh необязательным, что в Swift означает, что он имеет иметь значение до того, как вы вызовете super.init (или он вызывается неявно, что кажется вашим случаем). Либо сделайте refresh необязательным (возможно, тем, что вам нужно), либо инициализируйте его каким-либо образом.

Я бы посоветовал прочесть вводную документацию Swift еще раз, в которой подробно об этом говорится.

И последнее, что не является частью ответа, как отмечает @Anil, есть встроенный элемент управления обновлением в iOS, называемый UIRefresControl, на который стоит обратить внимание.

2
JustSid

Я создал приложение RSS-ленты, в котором у меня есть функция Pull To refresh , в которой изначально были некоторые проблемы, перечисленные выше. 

Но чтобы добавить к ответам пользователей выше, я искал повсюду свой вариант использования и не мог его найти. Я загружал данные из Интернета (RSSFeed), и я хотел, чтобы на моем столе отображались истории для обновления. 

То, что упомянуто выше, покрывает правильные области, но с некоторыми из проблем, с которыми сталкиваются люди, вот что я сделал, и это работает удовольствие:

Я воспользовался подходом @Blankarsch и перешел на свою main.storyboard и выбрал табличное представление для использования обновления, тогда не упоминалось создание IBOutlet и IBAction для эффективного использования обновления.

//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()
}

Надеюсь, что это помогает любому в той же ситуации, что и я

2
Dom Bryan

Я предлагаю сделать расширение pull To Refresh для использования в каждом классе.

1) Создайте пустой файл Swift: Файл - Новый - Файл - Файл Swift. 

2) Добавить следующее

    //  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) В вашем View Controller вызовите эти методы как: 

  override func viewWillAppear(animated: Bool) {

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

4) В какой-то момент вы хотели закончить обновление:

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

вы можете использовать этот подкласс tableView:

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 - в конструкторе интерфейса измените класс вашего tableView на PullToRefreshTableView или создайте PullToRefreshTableView программно

2 - реализовать PullToRefreshTableViewDelegate в вашем контроллере представления

3 - tableViewDidStartRefreshing(tableView: PullToRefreshTableView) будет вызываться в вашем контроллере представления, когда табличное представление начинает обновляться

4 - вызвать yourTableView.endRefreshing(), чтобы закончить обновление

0
Chuy47

Для тяги, чтобы обновить, я использую 

DGElasticPullToRefresh 

https://github.com/gontovnik/DGElasticPullToRefresh

Правка

pod 'DGElasticPullToRefresh'

import DGElasticPullToRefresh

и поместите эту функцию в ваш файл Swift и вызовите эту функцию из вашего 

переопределить функцию viewWillAppear (_ animated: 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!)
 }

И не забудьте удалить ссылку, пока вид исчезнет

чтобы удалить тягу, чтобы обновить, вставьте этот код в ваш 

переопределить функцию viewDidDisappear (_ animated: Bool)

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

 }

И это будет выглядеть

 enter image description here

Удачного кодирования :)

0
Azharhussain Shaikh

Вот как я заставил это работать, используя Xcode 7.2, который я считаю серьезной ошибкой. Я использую его внутри моего UITableViewController внутри моего viewWillAppear

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

configureMessages()

func configureMessages() {
    // configuring messages logic here

    self.refreshControl!.endRefreshing()
}

Как видите, я буквально должен вызывать метод configureMessage() после настройки моего UIRefreshControl, после чего последующие обновления будут работать нормально.

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