How to add UITableView inside expanded UICollectionView row? - ios

There are two basic functionalities I want to attach to my collection view:
The cells show expand and collapse behaviour on didSelectItem method.
Cell which gets expanded show a new tableView relevant to the row that was selected.
Presumptions:
Multiple expansions don't take place.
Upon clicking any unexpanded cell,that particular cell should expand and rest all should collapse.
The click of the cells in collection view and internal UITableView inside each cell has to be handled.
Each row of the UICollectionView can attain different height with respect to the size of the UITableView it will load upon click it.
I tried How to expand collectionview cell on didselect to show more info?, but it does not call cellForItemAtIndexPath, and so I am unable to add the new tableView to the cell, or http://www.4byte.cn/question/465532/how-to-expand-collectionview-cell-on-didselect-to-show-more-info.html
while Animate UICollectionViewCell collapsing is still unanswered.
I have a custom cell for this collectionView.
Any help in this regard is appreciated.
Thanks in advance.

Here is a sample, hope it helps to understand, how to implement.
class WSCustomCollectionViewCell: UICollectionViewCell, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var tableView: UITableView!
var tableViewData: Array<String>?
// MARK: UITableviewDataSource
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("wsTableViewCell") as UITableViewCell!
var value = self.tableViewData![indexPath.row] as String
cell.textLabel?.text = value
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if self.tableViewData != nil {
return self.tableViewData!.count
}
return 0
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
// MARK: Configure Cell
func configureWithDictionary(value: Dictionary<String, AnyObject>) {
var title = value["name"] as? String
if title != nil {
self.titleLabel.text = title
}
var items = value["items"] as? Array<String>
if items != nil {
self.tableViewData = items
self.tableView.reloadData()
}
}
}
--
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
#IBOutlet weak var collectionView: UICollectionView!
var collectionViewData: Array<Dictionary<String,AnyObject>>?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var value: Dictionary<String, AnyObject> = ["name":"Some title", "items":["item 1", "item 2"]]
self.collectionViewData = [value]
self.collectionView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: UICollectionViewDataSource
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if self.collectionViewData != nil {
return collectionViewData!.count
}
return 0
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
var cell = collectionView.dequeueReusableCellWithReuseIdentifier("wsCell", forIndexPath: indexPath) as WSCustomCollectionViewCell
let value = self.collectionViewData![indexPath.row] as Dictionary<String, AnyObject>?
if value != nil {
cell.configureWithDictionary(value!)
}
return cell
}
}
Do not forget set dataSource and delegate in storyboard.
Result:
EDIT
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let value = self.collectionViewData![indexPath.row] as Dictionary<String, AnyObject>?
// WARNING: very dirty solution, only for understanding!
if value != nil {
var isExpand = value!["expand"] as? String
if isExpand != nil && isExpand == "1" {
return CGSizeMake(280, 200)
}
}
return CGSizeMake(280, 44)
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
let value = self.collectionViewData![indexPath.row] as Dictionary<String, AnyObject>?
if value != nil {
// WARNING: very dirty solution, only for understanding!
var isExpand = value!["expand"] as? String
if isExpand != nil && isExpand == "0" {
var newValue: Dictionary<String, AnyObject> = ["name":"Some title", "items":["item 1", "item 2"], "expand":"1"]
self.collectionViewData = [newValue]
self.collectionView.reloadData()
}
else {
var newValue: Dictionary<String, AnyObject> = ["name":"Some title", "items":["item 1", "item 2"], "expand":"0"]
self.collectionViewData = [newValue]
self.collectionView.reloadData()
}
}
}
And update configureWithDictionary() method:
func configureWithDictionary(value: Dictionary<String, AnyObject>) {
var title = value["name"] as? String
if title != nil {
self.titleLabel.text = title
}
var items = value["items"] as? Array<String>
var isExpand = value["expand"] as? String
if items != nil && isExpand != nil && isExpand == "1" {
self.tableViewData = items
self.tableView.reloadData()
}
else {
self.tableViewData = nil
self.tableView.reloadData()
}
}

Related

TableView cells becomes inactive

I am using a tableView to take some surveys.
Header I use for a question. Footer for «back» and «next» buttons. And tableView cells for answer options.
Now I started to have a problem, with some user interaction: when you simultaneously click on the “next” button and select an answer, the answer options cease to be active, nothing can be selected. Although the buttons remain active.
Tell me in what direction to look for the problem and how you can debug this problem in order to understand what's wrong.
It all started after fixing bugs, when the application crashed when simultaneously (or almost) pressing the "next" button and choosing an answer. Because the didSelectRowAt method worked after I changed the current array of answer options, and the selected index in the previous question turned out to be larger than the size of the array with the answers to the new question.
class AssessmentVC: UIViewController {
#IBOutlet weak var tableView: UITableView!
var footer: FooterTableView?
var header: UIView?
var arrayAssessmnet = [AssessmentDM]()
var assessment: AssessmentDM!
var question: QuestionDM!
var viewSeperationHeader = UIView()
var arrayOptions: [Option]?
var countAssessment = 0
var numberAssessment = 0
var numberQuestion = 0
var countQuestion = 0
var numberQusttionForLabel = 1
var arrayQuestion = [QuestionDM]()
var arrayAnswers = [AnswerDM]()
var arrayEvents = [EventDM]()
override func viewDidLoad() {
super.viewDidLoad()
settingAssessment()
}
//MARK: - settingAssessment()
private func settingAssessment() {
let id = self.assessment.serverId
arrayQuestion = QuestionDM.getQuestions(id: id)
assessmentName.text = assessment.name
countQuestion = arrayQuestion.count
let day = self.assessment.day
arrayAnswers = AnswerDM.getAnswers(idAssessment: id, day: day)
settingQuestion(eventType: .start)
}
//MARK: - settingQuestion()
private func settingQuestion(eventType: EventType? = nil) {
let prevQuestion = question
question = arrayQuestion[numberQuestion]
timeQuestion = 0
footer!.grayNextButton()
//first question
if numberQuestion == 0 && numberAssessment == 0 {
footer!.previousButton.isHidden = true
} else {
footer!.previousButton.isHidden = false
}
arrayOptions = [Option]()
let sortOption = question.options!.sorted {$0.numberOption < $1.numberOption}
for option in sortOption {
arrayOptions?.append(Option(label: option.label, value: option.value))
}
tableView.rowHeight = UITableView.automaticDimension
tableView.reloadData()
heightTableView()
tableView.setContentOffset(.zero, animated: false)
}
//MARK: - heightTableView()
func heightTableView() {
}
//MARK: - UITableViewDataSource
extension AssessmentVC: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
viewSeperationHeader.isHidden = false
footer?.viewSeperationFooter.isHidden = false
tableView.separatorStyle = .singleLine
return question.options?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(forIndexPath: indexPath as IndexPath) as AnswerAssessmentCell
cell.initCell(text: arrayOptions![indexPath.row].label, value: arrayOptions![indexPath.row].value, arrayValue: arrayAnswers[numberQuestion].response, isCheckbox: true)
return cell
}
}
//MARK: - UITableViewDelegate
extension AssessmentVC: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
isChangAnswerInAssessment = true
if question.answerType == "Radio" || question.answerType == "Checkbox"{
selectRadioOrChekbox(indexPath: indexPath)
}
}
}
//MARK: - selectRadioOrChekbox
extension AssessmentVC {
private func selectRadioOrChekbox(indexPath: IndexPath) {
if question.answerType == "Radio" {
let cells = tableView.visibleCells as! Array<AnswerAssessmentCell>
for cell in cells {
cell.select = false
cell.isSelected = false
}
let cell = tableView.cellForRow(at: indexPath) as! AnswerAssessmentCell
cell.select = true
cell.isSelected = true
if arrayOptions?.count ?? 0 > indexPath.row {
arrayAnswers[numberQuestion].response = arrayOptions![indexPath.row].value
footer?.greenNextButton()
}
}
if question.answerType == "Checkbox" {
if arrayOptions?.count ?? 0 > indexPath.row {
//если нажато что-то, что должно сбросить "None"
// question.options![0].isSelect = false
let cells = tableView.visibleCells as! Array<AnswerAssessmentCell>
if cells[0].answerLabel.text == "None" {
cells[0].select = false
cells[0].isSelected = false
}
var array = arrayAnswers[numberQuestion].response?.components(separatedBy: ";")
array?.removeAll { $0 == "0"}
if array?.count == 0 {
arrayAnswers[numberQuestion].response = nil
} else {
arrayAnswers[numberQuestion].response = array?.joined(separator: ";")
}
let cell = tableView.cellForRow(at: indexPath) as! AnswerAssessmentCell
cell.select = !cell.select
cell.isSelected = cell.select
arrayAnswers[numberQuestion].response = array.joined(separator: ";")
if array.count == 0 {
arrayAnswers[numberQuestion].response = nil
footer?.grayNextButton()
} else {
footer?.greenNextButton()
}
}
}
}
}
//MARK: - Navigation between questions
extension AssessmentVC {
func nextQuestion() {
footer!.grayNextButton()
numberQuestion += 1
numberQusttionForLabel += 1
settingQuestion(eventType: .next)
} else {
}
func previousQuestion() {
numberQusttionForLabel -= 1
settingQuestion(eventType: .previous)
}
}
Some snippets that can help you :
// Answer type : use enum . Here the Strong/Codable is if you want to
// save using JSON encoding/decoding
enum AnswerType: String, Codable {
case checkBox = "CheckBox"
case radio = "Radio"
}
Setup of your cell :
class AnswerAssessmentCell: UITableViewCell {
...
// work with Option type
func initCell(option: Option, response: String?, answerType: AnswerType) {
// setup cell contents (labels)
// check for selected status
switch answerType {
case .checkBox:
// check if option is in response
// set isSelected according
break
case .radio:
// check if option is response
// set isSelected according
break
}
}
}
In table view data source :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! AnswerAssessmentCell
// Use the option to init the cell
// this will also set the selected state
let optionNumber = indexPath.row
cell.initCell(option: arrayOptions![optionNumber], response: arrayAnswers[numberQuestion].response, answerType: question.answerType)
return cell
}
In Table view delegate :
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
isChangAnswerInAssessment = true
let optionNumber = indexPath.row
switch question.answerType {
case .radio:
selectRadio(optionNumber: optionNumber)
case .checkBox:
selectCheckBox(optionNumber: optionNumber)
}
// Reload tableview to show changes
tableView.reloadData()
}
// Separate in 2 function for smaller functions
// in this function work only with model data, the reload data will do
// cell update
// only the footer view button cooler may need to be changed
private func selectRadio(optionNumber: Int) {
// Reset current response
// set response to optionNumber
// update footer button cooler if necessary
}
private func selectCheckBox(optionNumber: Int) {
// if option is in response
// remove option from response
// else
// add response to option
// update footer button cooler if necessary
}
Hope this can help you

Embedded UICollectionView in View Controller not getting called Swift

For some strange reason the collectionView isn't called. I put break points at numberOfItemsInSection and cellForItemAtIndexPath but they are never called. Here is my code:
class ChannelViewController: UIViewController, UISearchResultsUpdating, UICollectionViewDataSource, UICollectionViewDelegate {
var channelArray: [ChannelInfo] = []
var filteredSearchResults = [ChannelInfo]()
var resultsSearchController = UISearchController(searchResultsController: nil)
var logosShown = [Bool](count: 50, repeatedValue: false)
var detailUrl: String?
var apiKey = ""
var channel: String!
var channelForShow: String!
var task: NSURLSessionTask?
#IBOutlet var channelCollectionView: UICollectionView!
override func viewDidLoad() {
let baseURL = ""
getJSON(baseURL)
}
//MARK: CollectionView
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if resultsSearchController.active && resultsSearchController.searchBar.text != ""
{
return filteredSearchResults.count
} else {
return channelArray.count
}
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("ChannelCell", forIndexPath: indexPath) as! ChannelCell
let channel: String
if resultsSearchController.active && resultsSearchController.searchBar.text != "" {
channel = self.filteredSearchResults[indexPath.row].logo
} else {
channel = self.channelArray[indexPath.row].logo
}
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
var replacedTitle: String?
if resultsSearchController.active && resultsSearchController.searchBar.text != "" {
channelForShow = filteredSearchResults[indexPath.row].channelName
}
} else {
channelForShow = self.channelArray[indexPath.row].channelName
}
}
self.dismissSearchBar()
performSegueWithIdentifier("channelCollectToShowSegue", sender: self)
}
}
I also have a cell subclassed for the collectionView Cell:
class ChannelCell : UICollectionViewCell {
#IBOutlet var channelImageView: UIImageView!
}
You need to set the datasource of collection view to the controller.
1) In Interface builder, just drag from the collection view to the controller. and choose both the delegate and datasource..
2) Programatically
override func viewDidLoad() {
super.viewDidLoad()
channelCollectionView.delegate = self
channelCollectionView.dataSource = self
let baseURL = ""
getJSON(baseURL)
}
Did you set the collectionView's delegate and dataSource properties? If not, change your viewDidLoad to this, in order to set those two properties programmatically:
override func viewDidLoad() {
channelCollectionView.delegate = self
channelCollectionView.dataSource = self
let baseURL = ""
getJSON(baseURL)
}
If you don't set the delegate and dataSource, the collectionView won't know where to look to call the appropriate methods, such as cellForItemAtIndexPath. Hopefully this fixes your problem.

how to add element under collection reusable view in collection view

i have a problem and confusing i want to ask how can i make a new object ( i want to make date ) under the icons, and under the date there's icon again.. like gallery on iPhone,
in example:
august
(photos)
september
(photos)
and so on..thx
will be looks like this, but how
there is my code in this view
import UIKit
let reuseIdentifier = "Cell"
class SummaryViewController: UICollectionViewController, UICollectionViewDataSource, UICollectionViewDelegate {
#IBOutlet var collectionview: UICollectionView!
var photos:NSArray?
var items = NSMutableArray()
var TableData:Array< String > = Array < String >()
var json:String = ""
var arrayOfMenu: [ImageList] = [ImageList]()
override func viewDidLoad() {
super.viewDidLoad()
self.setUpMenu()
collectionview.dataSource = self
collectionview.delegate = self
NSLog("%d", items.count)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return arrayOfMenu.count //hitung banyak data pada array
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! UICollectionViewCell
let image = UIImage(named: items.objectAtIndex(indexPath.row) as! String)
let imageView = cell.viewWithTag(100) as! UIImageView
imageView.image = image
return cell
}
func setUpMenu() //membaca json pada setiap arraynya
{
var json: JSON = JSON (data: NSData())
DataManager.getactivityDataFromFileWithSuccess{ (data) -> Void in
json = JSON(data: data)
let results = json["results"]
for (index: String, subJson: JSON) in results {
}
for (var i = 0; i < json["Activity"].count; i++) {
if let icon: AnyObject = json["Activity"][i]["icon"].string {
self.items.addObject(icon)
dispatch_async(dispatch_get_main_queue(), {self.collectionView!.reloadData()})
var menu = ImageList(image: icon as! String)
self.arrayOfMenu.append(menu)
self.TableData.append(icon as! String)
}
}
}
}
override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView
{
let header = collectionView.dequeueReusableSupplementaryViewOfKind(UICollectionElementKindSectionHeader, withReuseIdentifier: "headersection", forIndexPath: indexPath) as! UICollectionReusableView
return header
}
}
You can set number of sections to required number of months.
Like this :
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int
{
return 3
}
And for the menu, you need to give it according to section(month).
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
if section == 0
{
return arrayOfFirstMenu.count
}
else if section == 1
{
return arrayOfSecondMenu.count
}
else
{
return arrayOfThirdMenu.count
}
}
Hope this helps!

Loading an Array to TableView based on Segment-Control

I am relatively new to Swift. I tried to search and google the problem but i can't find any answers. It shouldn't be that hard. Hope you guys can help me out. I‘ve been struggling with this Issue over days now:
I created a Tableview which loads an array of tuples from another .swift file. That is working fine! Now I want the tableview to choose the .swift based on a "segment control". So if the Segment-Control is switched to "A" I want it to show the Array of "PSSCBOOKMac.Swift", for B it would be the Array of "PSSCBOOKWin.swift".
The Action ist written properly, I guess (print-statements are working). But the change of the segment-control doesn't effect the Tableview. My guess: The segment-control doesn't effect the Tableview because it has been loaded before and I can't change the value. How can I achieve that?
Cheers for any answers!
Here is the Code:
import UIKit
class ViewController: UIViewController, UITableViewDataSource {
#IBOutlet weak var PSSCSegmentControl: UISegmentedControl!
//LOAD ARRAY FROM PSSCBOOK.SWIFT
var PSSCBook = PSSCBOOKMac()
#IBAction func PSSCSegmentControlChoose(sender: AnyObject) {
if PSSCSegmentControl.selectedSegmentIndex == 0 {
var PSSCBook = PSSCBOOKMac()
println("im mac")
} else {
var PSSCBook = PSSCBOOKWin()
println("im win")
}
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return PSSCBook.PSSCTools.count
} else {
return PSSCBook.PSSCFile.count
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("PSCell", forIndexPath: indexPath) as! UITableViewCell
if indexPath.section == 0 {
let (shortCutTitle,shortCutKey) = PSSCBook.PSSCTools[indexPath.row]
cell.textLabel?.text = shortCutTitle
cell.detailTextLabel?.text = shortCutKey
} else {
let (shortCutTitle,shortCutKey) = PSSCBook.PSSCFile[indexPath.row]
cell.textLabel?.text = shortCutTitle
cell.detailTextLabel?.text = shortCutKey
}
/* var PSIcon = UIImage(named: "PSIcon")
cell.imageView?.image = PSIcon */
return cell
}
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if section == 0 {
return "Tools"
} else {
return "File"
}
}
}
When you update the datasource of your table view, it won't magically update itself.
You have to reload the table view for the changes to take place:
#IBAction func PSSCSegmentControlChoose(sender: AnyObject) {
if PSSCSegmentControl.selectedSegmentIndex == 0 {
var PSSCBook = PSSCBOOKMac()
println("im mac")
} else {
var PSSCBook = PSSCBOOKWin()
println("im win")
}
self.tableView.reloadData();
}
I spend the last two days trying to figure out what was wrong with my code. I implemented the suggested reloadData() without having errors. The println Values in the console change.. But the tableview just won't refresh. I really don’t know where else to look, is searched for hours. Could somebody please tell me what type of silly mistake I am doing? Thanks guys!
import UIKit
class ViewController: UIViewController, UITableViewDataSource {
//LOAD ARRAY FROM PSSHORTCUTSBOOK.SWIFT
var PSSCBook = PSShortCutsBook()
#IBOutlet weak var SCOutlet: UISegmentedControl!
#IBOutlet weak var SCtableviewOutlet: UITableView!
#IBAction func SCAction(sender: AnyObject) {
if SCOutlet.selectedSegmentIndex == 1 {
var PSSCBook = PSShortCutsBook()
println("There are \(PSSCBook.shortCutsPS.count) items in this Array")
self.SCtableviewOutlet.reloadData();
} else {
var PSSCBook = PSShortCutsBook2()
println("There are \(PSSCBook.shortCutsPS.count) items in this Array")
self.SCtableviewOutlet.reloadData();
}
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return PSSCBook.shortCutsPS.count
} else {
return PSSCBook.shortCutsPS2.count
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("PSCell", forIndexPath: indexPath) as! UITableViewCell
if indexPath.section == 0 {
let (shortCutTitle,shortCutKey) = PSSCBook.shortCutsPS[indexPath.row]
cell.textLabel?.text = shortCutTitle
cell.detailTextLabel?.text = shortCutKey
} else {
let (shortCutTitle,shortCutKey) = PSSCBook.shortCutsPS2[indexPath.row]
cell.textLabel?.text = shortCutTitle
cell.detailTextLabel?.text = shortCutKey
}
/* var PSIcon = UIImage(named: "PSIcon")
cell.imageView?.image = PSIcon */
return cell
}
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if section == 0 {
return "Tools"
} else {
return "Help"
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

Swift filter UITableView with out search bar

I have a UITableView that I want to filter based on a selection from slide panel view controller. This is the function that gets the returned value form the panel.
func itemSelected(type: Item) {
self.selectedItem = Item.title
delegate?.collapseSidePanels?()
}
Table view code.
var myData: Array<AnyObject> = []
var selectedItem:Array<AnyObject> = []
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellID: NSString = "Cell"
var Cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier(cellID as String) as! UITableViewCell
var data: NSManagedObject = myData[indexPath.row] as! NSManagedObject
if tableView == selectedItem {
data = self.selectedItem[indexPath.row] as! NSManagedObject
} else
{
data = myData[indexPath.row] as! NSManagedObject
}
Cell.textLabel?.text = data.valueForKeyPath("itemname") as? String
var tt = data.valueForKeyPath("itemtype") as! String
Cell.detailTextLabel?.text = ("Item Type: \(tt)")
return Cell
}
I need to filter on the itemtype.
edit - Will not filter still so here is the full code for the tableViewController.
import UIKit
import CoreData
import Foundation
#objc
protocol tableViewControllerDelegate {
optional func toggleLeftPanel()
optional func toggleRightPanel()
optional func collapseSidePanels()
}
class tableViewController: UITableViewController, NSFetchedResultsControllerDelegate, SidePanelViewControllerDelegate {
var delegate: tableViewControllerDelegate?
var myData: Array<AnyObject> = []
var myFilteredData: Array<AnyObject> = []
#IBAction func leftTapped(sender: AnyObject) {
delegate?.toggleLeftPanel?()
}
// Use this to change table view to edit mode
// and to Change the title when clicked on.
// Make sure to have sender set as UIBarButtonItem
// or you can not change the title of the button.
var condition: Bool = true
#IBAction func buttonEdit(sender: UIBarButtonItem) {
if(condition == true) {
tableView.editing = true
sender.title = "Done"
condition = false
} else {
tableView.editing = false
sender.title = "Edit"
condition = true
}
}
let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
var fetchedResultController: NSFetchedResultsController = NSFetchedResultsController()
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(animated: Bool) {
// This is neeed when using panel view controller to show the bottom navbar.
self.navigationController?.setToolbarHidden(false, animated: true)
// ref app del
let appDel: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
// Ref data
let context: NSManagedObjectContext = appDel.managedObjectContext!
let freq = NSFetchRequest(entityName: "Products")
myData = context.executeFetchRequest(freq, error: nil)!
}
override func viewDidAppear(animated: Bool) {
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
if (self.myFilteredData.count != 0) {
return self.myFilteredData.count
} else {
return self.myData.count
}
}
func getFetchedResultController() -> NSFetchedResultsController {
fetchedResultController = NSFetchedResultsController(fetchRequest: NSFetchRequest(), managedObjectContext: managedObjectContext!, sectionNameKeyPath: nil, cacheName: nil)
return fetchedResultController
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellID: String = "Cell"
var cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier(cellID as String) as! UITableViewCell
var data: NSManagedObject
if (self.myFilteredData.count != 0){
data = myFilteredData[indexPath.row] as! NSManagedObject
cell.textLabel?.text = data.valueForKeyPath("productname") as? String
var tt = data.valueForKeyPath("itemtype") as! String
cell.detailTextLabel?.text = ("Item J Type: \(tt)")
} else {
data = myData[indexPath.row] as! NSManagedObject
cell.textLabel?.text = data.valueForKeyPath("productname") as? String
var tt = data.valueForKeyPath("itemtype") as! String
cell.detailTextLabel?.text = ("Item Type: \(tt)")
}
return cell
}
override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
override func tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath) {
let item: AnyObject = myData[sourceIndexPath.row]
myData.removeAtIndex(sourceIndexPath.row)
myData.insert(item, atIndex: destinationIndexPath.row)
}
// called when a row deletion action is confirmed
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
switch editingStyle {
case .Delete:
// remove the deleted item from the model
let appDel:AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let context:NSManagedObjectContext = appDel.managedObjectContext!
context.deleteObject(myData[indexPath.row] as! NSManagedObject)
myData.removeAtIndex(indexPath.row)
context.save(nil)
// remove the deleted item from the `UITableView`
self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
default:
return
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "showProduct"){
let selectedIndexPath:NSIndexPath = self.tableView.indexPathForSelectedRow()!
let genView:genViewController = segue.destinationViewController as! genViewController
genView.row = selectedIndexPath.row
}
else if (segue.identifier == "addProduct"){
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func itemSelected(item: Type) {
var selectedType = item.title
delegate?.collapseSidePanels?()
for (key, value) in enumerate(self.myData) {
if (value.valueForKeyPath("itemtype") !== "selectedType") {
self.myFilteredData.append(value)
dump(myFilteredData)
} else {
// do nothing with it
}
}
tableView.reloadData()
}
}
Depending on however you want the data filtered, you could loop through myData in itemSelected(), find the elements that you want in your filtered list and save them in a new array (myFilteredData).
var myFilteredData: Array<AnyObject> = []
func itemSelected(type: Item) {
self.selectedItem = Item.title
delegate?.collapseSidePanels?()
for (key, value) in enumerate(self.myData) {
if (value.valueForKeyPath("itemtype") == "yourCondition") {
self.myFilteredData.append(value)
} else {
// do nothing with it
}
}
tableView.reloadData() // use tableView.reloadSections with rowAnimation for better effect.
}
You would then reload the tableview with tableView.reloadSections(_ sections: NSIndexSet,
withRowAnimation animation: UITableViewRowAnimation), which will trigger the cellForRowAtIndexPath function. Here, you would need to decide if you want to use myData or myFilteredData for the cell's labels.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
...
var data:NSManagedObject
if (self.myFilteredData.count != 0) {
data = myFilteredData[indexPath.row] as! NSManagedObject
} else {
data = myData[indexPath.row] as! NSManagedObject
}
...
}
Also, don't forget to modify the numberOfRowsInSection function to return the size of the array you are populating the tableView with.
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if (self.myFilteredData.count != 0) {
return self.myFilteredData.count
} else {
return self.myData.count
}
}

Resources