【问题标题】:iOS reloading a UITableView from a Swift class/objectiOS 从 Swift 类/对象重新加载 UITableView
【发布时间】:2015-04-22 06:17:21
【问题描述】:

我正在尝试构建一个面向对象的 iOS 应用程序,但在从我的 swift 类文件之一调用表重新加载(UI 交互)时遇到问题。

如果我在没有对象的情况下工作并在我的 InterfaceController 的 viewDidLoad 方法中编写所有这些东西,那么一切正常......但如果我将它放入类中则不会。

我正在使用异步请求来从 web 服务加载 json 数据。收到数据后,我将此数据用作表格视图的数据源。 好像tableview是在启动后初始化的,没有数据,所以在完成异步请求后,需要在tableview上调用reload()。

下面是详细信息:

主表控制器

import UIKit;


class DeviceOverview: UITableViewController {

@IBOutlet var myTableView: UITableView!

var myDevices = Array<String>();
var myDevicesSection = NSMutableDictionary()
var deviceObjects = Array<NSDictionary>();
var mappingSectionIndex = Array<String>();
var sharedUserDefaults = NSUserDefaults(suiteName: "group.barz.fhem.SharingDefaults")

// THIS IS AN ATTEMPT TO give the class itself as PARAMETER
// ALSO TRIED TO USE myTableView (IBOutlet)
var fhem :FHEM  = FHEM(tableview : self)

override func viewDidLoad() {

    super.viewDidLoad()

}


override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return self.fhem.sections.count
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    var devicesInSection : Array<NSDictionary> = self.fhem.sections[self.fhem.mappingSectionIndex[section]] as! Array<NSDictionary>
    return devicesInSection.count;
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("device", forIndexPath: indexPath) as! TableViewCell
    let sectionName : String = fhem.mappingSectionIndex[indexPath.section]
    if let devices : Array<NSDictionary> =   self.fhem.sections.objectForKey(sectionName) as? Array<NSDictionary> {
        let device = devices[indexPath.row]
        var alias : NSString?;
        if let attr : NSDictionary = device.objectForKey("ATTR") as? NSDictionary {
            alias = attr.objectForKey("alias") as? String
        }
        if (alias != nil) {
            cell.deviceLabel.text = alias as? String
        }else{
            if let deviceName : String = device.objectForKey("NAME") as? String {
                cell.deviceLabel.text = deviceName
            }
        }
    }
    return cell
}

FHEM 类

import UIKit


class FHEM: NSObject {

var devices : [NSDictionary]
var sections : NSMutableDictionary
var deviceNames : [String]
var mappingSectionIndex : [String]
var myTableViewController : DeviceOverview

init(tableview : DeviceOverview){
    self.devices = Array<NSDictionary>()
    self.sections = NSMutableDictionary()
    self.deviceNames = Array<String>()
    self.mappingSectionIndex = Array<String>()
    self.myTableViewController = tableview
    super.init()

    let url = NSURL(string: "xyz");
    var request = NSURLRequest(URL: url!);

    NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {
        (response, data, error) in
        if let jsonData: NSData? = data {
            // do some great stuff
            //
            // this is an attempt to call the table view to reload
            self.myTableViewController.myTableView.reloadData()
        }
    }
}
}

如果我尝试将 self 变量放入我的构造函数的构造函数中,它会引发编译错误

var fhem :FHEM  = FHEM(tableview : self)

如果我尝试将UITableView 直接放入构造函数中,它也不起作用

var fhem :FHEM  = FHEM(tableview : myTableView)

我是否在使用对象并与 ui 交互时沿着完全错误的路径行走?

【问题讨论】:

  • 您可以为您的表格视图重新加载发布通知,并向您的表格视图控制器添加一个观察者以触发那里的 reloadData
  • 有意思,有例子吗?

标签: ios uitableview swift


【解决方案1】:

您可以在异步任务完成时发布通知:

NSNotificationCenter.defaultCenter().postNotificationName("refreshMyTableView", object: nil)

将观察者添加到您的 DeviceOverview 类方法 viewDidLoad 的通知中:

NSNotificationCenter.defaultCenter().addObserver(self, selector: "refreshList:", name:"refreshMyTableView", object: nil) 

并添加将在您的 DeviceOverview 类中触发的方法

func refreshList(notification: NSNotification){
    myTableView.reloadData()
}

【讨论】:

  • 谢谢你,成功了!请您为这个问题投票吗?
【解决方案2】:

您好,您可以按照上述答案中的建议使用通知,否则您可以使用委托来解决此问题

代表正在做与您所做的类似的事情,但方式很简单。

在这里,您可以在自定义类中传递表格视图控制器。您可以使用委托来执行此操作。在您的自定义类中创建自定义委托方法。使用表视图控制器对象设置委托。

这里你不需要获取你的表视图的 IBOutlet,因为你的控制器继承自表视图控制器,所以它的视图是表视图

import UIKit


class DeviceOverview: UITableViewController,FHEMDelegate {

    @IBOutlet var myTableView: UITableView!

    var myDevices = Array<String>();
    var myDevicesSection = NSMutableDictionary()
    var deviceObjects = Array<NSDictionary>();
    var mappingSectionIndex = Array<String>();
    var sharedUserDefaults = NSUserDefaults(suiteName: "group.barz.fhem.SharingDefaults")
    var fhem :FHEM?
    // THIS IS AN ATTEMPT TO give the class itself as PARAMETER
    // ALSO TRIED TO USE myTableView (IBOutlet)


    override func viewDidLoad() {

        super.viewDidLoad()
        fhem = FHEM ()
        fhem?.delegate = self

    }


    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1;
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//        var devicesInSection : Array<NSDictionary> = self.fhem!.sections[self.fhem!.mappingSectionIndex[section]] as Array<NSDictionary>

        return 5;
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("device", forIndexPath: indexPath) as UITableViewCell
        let sectionName : String = fhem!.mappingSectionIndex[indexPath.section]
        if let devices : Array<NSDictionary> =   self.fhem!.sections.objectForKey(sectionName) as? Array<NSDictionary> {
            let device = devices[indexPath.row]
            var alias : NSString?;
            if let attr : NSDictionary = device.objectForKey("ATTR") as? NSDictionary {
                alias = attr.objectForKey("alias") as? String
            }
            if (alias != nil) {
              //  cell.deviceLabel.text = alias as? String
            }else{
                if let deviceName : String = device.objectForKey("NAME") as? String {
                  //  cell.deviceLabel.text = deviceName
                }
            }
        }
        return cell
    }
    func reloadDataOfTable()
    {
        self.tableView.reloadData()
    }
}

FHEM

import UIKit
protocol FHEMDelegate{

   func reloadDataOfTable()
}
class FHEM : NSObject {
    var devices : [NSDictionary]
    var sections : NSMutableDictionary
    var deviceNames : [String]
    var mappingSectionIndex : [String]
    //var myTableViewController : DeviceOverview
    var delegate :FHEMDelegate?

 override init(){
        self.devices = Array<NSDictionary>()
        self.sections = NSMutableDictionary()
        self.deviceNames = Array<String>()
        self.mappingSectionIndex = Array<String>()
        self.delegate = nil
        super.init()

    let url = NSURL(string: "http://google.com");
        var request = NSURLRequest(URL: url!);

        NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {
            (response, data, error) in
            if let jsonData: NSData? = data {
                // do some great stuff
                //
                // this is an attempt to call the table view to reload
              self.delegate?.reloadDataOfTable()
            }
        }
    }
}

在 FHEM 类中创建一个自定义委托方法 reloadDataOfTable,该方法在您的 viewcontroller 类中实现,因此当收到代码响应时,它会调用该方法和此方法 (reloadDataOfTable) 内容代码以重新加载表数据。

【讨论】:

  • 有没有办法将 self.tableView.reloadData() 移动到 FHEM 协议的扩展?
  • @2ank3th 你能告诉我为什么你想要 self.tableView.reloadData() 来扩展协议。你在你的视图控制器中得到了协议的 reloadDataOfTable() 方法,你可以这样做。
【解决方案3】:

我不太了解 Swift,但我已经为 iOS 编写 Objective-C 有一段时间了。 (至少在 Objective-C 中)您必须在访问 self 之前在 super 上调用 init,否则您的对象未正确初始化。您也没有将 self 分配给 super.init() 的结果,这在 Objective-C 中是必需的,但在 Swift 中似乎没有。

tl;dr -- 将对super.init() 的调用移至FHEM 类'init 方法的第一行。

【讨论】:

  • 这将导致此错误:属性'self.devices'未在super.init调用时初始化
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多