草庐IT

ios - Swift:如何从我的 TableView 中删除重复项?

coder 2023-09-14 原文

这里的问题是我在我的 TableView 中得到了重复项,我知道为什么,但我不知道如何修复它并实现一个不同的系统。

我的应用程序是一个博客阅读器,它使用 PHP 从 MYSQL 数据库读取数据并将 JSON 发送到我的 Swift 应用程序。我的 TableView 有两个部分,一个用于数据库中的所有对象,第二个部分用于当我单击单元格上的关注按钮时,基本上将对象从 mainArray 移动到 followedArray。每个部分都使用一个数组,例如,我将所有对象从 mainArray 移动到 followedArray 并更新表,我在 mainArray 中再次获取所有这些对象,显然是因为 mainarray 是空的,代码只是在做它的工作。

那么我该如何实现一个更好的系统,以便当用户将对象从一个部分移动到另一个部分(或从 mainArray 到 followedArray)时,mainArray 不会重新填充它在 followedArray 中的相同对象。

这是我使用的代码。

MainController.swift - Tableview 所在的类

var mainArray = [Blog]()
var followedArray = [Blog]()

// Title for Header
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {

    if !(searchController.isActive && searchController.searchBar.text != "") {

        if section == 0 {
            return "Followed Blogs"
        }
        else {
            return "All Blogs"
        }
    }
    return "Filtered Blogs"
}

// Number of Rows in Section
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    if !(searchController.isActive && searchController.searchBar.text != "") {

        if section == 0 {

            return followedArray.count
        }
        else if (section == 1) {

            return mainArray.count
        }
    }
    return filteredArray.count
}

// CellForRowAt indexPath
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let CellIdentifier = "Cell"
    var cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier) as! CustomCell

    if cell != cell {
        cell = CustomCell(style: UITableViewCellStyle.default, reuseIdentifier: CellIdentifier)
    }

    // Configuring the cell
    var blogObject: Blog

    if !(searchController.isActive && searchController.searchBar.text != "") {
        if indexPath.section == 0 {
            blogObject = followedArray[indexPath.row] 
            cell.populateCell(blogObject, isFollowed: true, indexPath: indexPath, parentView: self)
        }
        else if indexPath.section == 1 {
            blogObject = mainArray[indexPath.row] 
            cell.populateCell(blogObject, isFollowed: false, indexPath: indexPath, parentView: self)
        }
    }
    else {
        blogObject = filteredArray[indexPath.row] 
        cell.populateCell(blogObject, isFollowed: false, indexPath: indexPath, parentView: self)
    }

    return cell
}

// Follow Button
@IBAction func followButtonClick(_ sender: UIButton!) {

    // Adding row to tag
    let buttonPosition = (sender as AnyObject).convert(CGPoint.zero, to: self.myTableView)
    if let indexPath = self.myTableView.indexPathForRow(at: buttonPosition) {

        // Showing Status Labels
        let cell = self.myTableView.cellForRow(at: indexPath) as! CustomCell
        cell.firstStatusLabel.isHidden = false
        cell.secondStatusLabel.isHidden = false

        // Change Follow to Following
        (sender as UIButton).setImage(UIImage(named: "follow.png")!, for: .normal)
        cell.followButton.isHidden = true
        cell.followedButton.isHidden = false

        // Checking wether to import from mainArray or filteredArray to followedArray
        if !(searchController.isActive && searchController.searchBar.text != "") {

            self.myTableView.beginUpdates()

            // ----- Inserting Cell to followedArray -----
            followedArray.insert(mainArray[indexPath.row], at: 0)
            myTableView.insertRows(at: [IndexPath(row: 0, section: 0)], with: .fade)

            // ----- Removing Cell from mainArray -----
            mainArray.remove(at: indexPath.row)
            let rowToRemove = indexPath.row
            self.myTableView.deleteRows(at: [IndexPath(row: rowToRemove, section: 1)], with: .fade)

            self.myTableView.endUpdates()

            myTableView.reloadData()

            // After Updating Table, Save the Archived to UserDefaults
            saveUserDefaults()
        }
        else {

            self.myTableView.beginUpdates()

            // ----- Inserting Cell to followedArray -----
            let blogObject: Blog = filteredArray[indexPath.row]
            let indexOfObjectInArray = mainArray.index(of: blogObject)

            followedArray.insert(blogObject, at: 0)

            // ----- Removing Cell from filteredArray -----
            filteredArray.remove(at: indexPath.row)
            mainArray.remove(at: indexOfObjectInArray!)
            let rowToRemove = indexPath.row
            self.myTableView.deleteRows(at: [IndexPath(row: rowToRemove, section: 0)], with: .fade)

            self.myTableView.endUpdates()

            myTableView.reloadData()

            // After Updating Table, Save the Archived to UserDefaults
            saveUserDefaults()
        }
    }
}


// Retrieving Data from Server
func retrieveDataFromServer() {

    let getDataURL = "http://example.com/receiving.php"
    let url: NSURL = NSURL(string: getDataURL)!

    do {
        let data: Data = try Data(contentsOf: url as URL)
        let jsonArray = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! NSMutableArray

        // Looping through jsonArray
        for jsonObject in jsonArray {

            if let blog = Blog.createGame(from: jsonObject as AnyObject) {

                mainArray.append(blog)
            }
        }
    }
    catch {
        print("Error: (Retrieving Data)")
    }
    myTableView.reloadData()
}

Blog.swift - 处理我也使用 NSCoder 的博客对象

import UIKit

class Blog: NSObject, NSCoding {

var blogName: String!
var blogStatus1: String!
var blogStatus2: String!
var blogURL: String!
var blogID: String!
var blogType: String!
var blogDate: String!
var blogPop: String!

static func createBlog(from jsonObject: AnyObject) -> Blog? {

    guard let bID: String = jsonObject.object(forKey: "id") as? String,
        let bName: String = jsonObject.object(forKey: "blogName") as? String,
        let bStatus1: String = jsonObject.object(forKey: "blogStatus1") as? String,
        let bStatus2: String = jsonObject.object(forKey: "blogStatus2") as? String,
        let bURL: String = jsonObject.object(forKey: "blogURL") as? String,
        let bType: String = jsonObject.object(forKey: "blogType") as? String,
        let bDate: String = jsonObject.object(forKey: "blogDate") as? String,
        let bPop: String = jsonObject.object(forKey: "blogPop") as? String

        else {
          print("Error: (Creating Blog Object)")
          return nil
}

let blog = Blog()
    blog.blogName = bName
    blog.blogStatus1 = bStatus1
    blog.blogStatus2 = bStatus2
    blog.blogURL = bURL
    blog.blogID = bID
    blog.blogType = bType
    blog.blogDate = bDate
    blog.blogPop = bPop
    return blog
}

convenience required init?(coder aDecoder: NSCoder) {
    self.init ()
    self.blogName = aDecoder.decodeObject(forKey: "blogName") as! String
    self.blogStatus1 = aDecoder.decodeObject(forKey: "blogStatus1") as! String
    self.blogStatus2 = aDecoder.decodeObject(forKey: "blogStatus2") as! String
    self.blogURL = aDecoder.decodeObject(forKey: "blogURL") as! String
    self.blogID = aDecoder.decodeObject(forKey: "blogID") as! String
    self.blogType = aDecoder.decodeObject(forKey: "blogType") as! String
    self.blogDate = aDecoder.decodeObject(forKey: "blogDate") as! String
    self.blogPop = aDecoder.decodeObject(forKey: "blogPop") as! String
}

func encode(with aCoder: NSCoder) {
    aCoder.encode(blogName, forKey: "blogName")
    aCoder.encode(blogStatus1, forKey: "blogStatus1")
    aCoder.encode(blogStatus2, forKey: "blogStatus2")
    aCoder.encode(blogURL, forKey: "blogURL")
    aCoder.encode(blogID, forKey: "blogID")
    aCoder.encode(blogType, forKey: "blogType")
    aCoder.encode(blogDate, forKey: "blogDate")
    aCoder.encode(blogPop, forKey: "blogPop")
 }
}

在重新填充 mainArray 之前是否有一种方法可以检查 followedArray 中有什么以及丢失或添加到数据库中的任何内容以导入而不创建重复项,因为将添加新博客并且用户将跨部分传输博客所以这是一个我遇到的主要问题。

感谢您的帮助,因为我仍在学习 Swift,谢谢。

最佳答案

我建议将应在后续类别中的博客的唯一标识符保存到一个数组中,并在每次重新加载 tableView 时,将适当的单元格移动到正确的部分。

您似乎在使用 UserDefaults但没有对它们进行修改。使用我的方法,唯一需要保存到 UserDefaults 和从中加载的数组是关注博客的列表。其余的默认为主列表,即使出现新博客也是如此。

你还需要一个数组:

var mainArray = [Blog]()
var followedArray = [Blog]()
var followedIdentifiers = [String]()

或者标识符将属于的任何数据类型

您也可以使用 Set因为您不希望 followedIdentifiers 中有重复项

var followedIdentifiers = Set<String>()

以下是对代码相关部分的修改(我的更改标记为 <---- ):

// Checking whether to import from mainArray or filteredArray to followedArray
if !(searchController.isActive && searchController.searchBar.text != "") {

    self.myTableView.beginUpdates()

    // Save identifier into followedIdentifier array <--------------
    self.followedIdentifiers.insert(mainArray[indexPath.row].blogID)

    // ----- Inserting Cell to followedArray -----
    followedArray.insert(mainArray[indexPath.row], at: 0)
    myTableView.insertRows(at: [IndexPath(row: 0, section: 0)], with: .fade)

    // ----- Removing Cell from mainArray -----
    mainArray.remove(at: indexPath.row)
    let rowToRemove = indexPath.row
    self.myTableView.deleteRows(at: [IndexPath(row: rowToRemove, section: 1)], with: .fade)

    self.myTableView.endUpdates()

    myTableView.reloadData()

    // After Updating Table, Save the Archived to UserDefaults
    saveUserDefaults()
} else {

    self.myTableView.beginUpdates()

    // Remove identifier into followedIdentifier array <------------
    self.followedIdentifiers.remove(followedArray[indexPath.row].blogID)

    // ----- Inserting Cell to followedArray -----
    let blogObject: Blog = filteredArray[indexPath.row]
    let indexOfObjectInArray = mainArray.index(of: blogObject)

    followedArray.insert(blogObject, at: 0)

    // ----- Removing Cell from filteredArray -----
    filteredArray.remove(at: indexPath.row)
    mainArray.remove(at: indexOfObjectInArray!)
    let rowToRemove = indexPath.row
    self.myTableView.deleteRows(at: [IndexPath(row: rowToRemove, section: 0)], with: .fade)

    self.myTableView.endUpdates()

    myTableView.reloadData()

    // After Updating Table, Save the Archived to UserDefaults
    saveUserDefaults()
}

// Retrieving Data from Server
func retrieveDataFromServer() {

    let getDataURL = "http://example.com/receiving.php"
    let url: NSURL = NSURL(string: getDataURL)!

    do {
        let data: Data = try Data(contentsOf: url as URL)
        let jsonArray = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! NSMutableArray

        // Clear the arrays      <-------------
        self.followedArray = [Blog]()
        self.mainArray = [Blog()]

        // Looping through jsonArray
        for jsonObject in jsonArray {

            if let blog = Blog.createBlog(from: jsonObject as AnyObject) {
                // Check if identifiers match <------------
                if followedIdentifiers.contains(blog.blogID) {
                    self.followedArray.append(blog)
                } else {
                    self.mainArray.append(blog)
                }

            }
        }
    } catch {
        print("Error: (Retrieving Data)")
    }
    myTableView.reloadData()
}

为了让它跨 session 工作,你必须在你的saveUserDefaults()中有类似的东西

UserDefaults.standard.setValue(Array(self.followedIdentifiers), forKey: "someName")

这是你从 UserDefaults 加载的地方

self.followedIdentifiers = Set(UserDefaults.standard.stringArray(forKey: "someName"))

关于ios - Swift:如何从我的 TableView 中删除重复项?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44575422/

有关ios - Swift:如何从我的 TableView 中删除重复项?的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  4. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  5. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  6. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  7. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  8. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

    在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

  9. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

    我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

  10. ruby - 我可以使用 Ruby 从 CSV 中删除列吗? - 2

    查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html

随机推荐