I am using a DTTableViewManager for my UIViewController with a UITableView contained within.
My View Controller only contains:
class ViewController: UIViewController, DTTableViewManageable {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
let users = ["Test User 1", "Test User 2"]
manager.startManaging(withDelegate: self)
manager.register(PersonsCell.self)
manager.memoryStorage.addItem(users, toSection: 0)
}
}
This is conform their Github example
My UITableViewCell looks as follows:
class PersonsCell: UITableViewCell, ModelTransfer {
func update(with model: String) {
self.nameLabel = model
}
#IBOutlet weak var nameLabel: UILabel!
}
This is also conform their example on Github.
But still I'm getting this error:
fatal error: Cell mapping is missing for model: ["Test User 1", "Test User 2"]: file ~~ ~/Pods/DTTableViewManager/Source/DTTableViewManager.swift, line 737
I have tried to find examples for people with similar problems but I could not find them.
Related
I'm building an app with multiple scenes and a table view with custom cells in each. I got the home screen table view to work fine and then I segue to the new scene from the custom cells. When it segues, my second view controller crashes.
Here is my code for the view controller
import UIKit
class QuestionViewController: UIViewController {
#IBOutlet weak var questionLabel: UILabel!
#IBOutlet weak var submitButton: UIButton!
#IBOutlet weak var qTableView: UITableView!
var answers : [QuestionOption] = []
override func viewDidLoad() {
super.viewDidLoad()
answers = [QuestionOption(text: "test"), QuestionOption(text: "test"), QuestionOption(text: "test"), QuestionOption(text: "test")]
qTableView.delegate = self
qTableView.dataSource = self
submitButton.setTitle("Submit", for: .normal)
questionLabel.text = "test question"
}
}
extension QuestionViewController: UITableViewDataSource, UITableViewDelegate{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return answers.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let a = answers[indexPath.row]
let cell = qTableView.dequeueReusableCell(withIdentifier: "QuestionOptionCell") as! QuestionOptionCell
cell.setOption(option: a)
return cell
}
}
Here's my code for the cell
import UIKit
class QuestionOptionCell: UITableViewCell {
#IBOutlet weak var cellTitle: UILabel!
func setOption(option: QuestionOption){
cellTitle.text = option.text
}
}
Here's my code for the QuestionOption class
import Foundation
import UIKit
class QuestionOption{
var text: String
init(text: String){
self.text = text
}
}
Crash log
2019-02-20 14:33:28.394695-0800 iQuiz[8935:822409] *** NSForwarding: warning: object 0x7fd608407c40 of class 'iQuiz.QuestionOption' does not implement methodSignatureForSelector: -- trouble ahead
Unrecognized selector -[iQuiz.QuestionOption initWithCoder:]
2019-02-20 14:33:28.395281-0800 iQuiz[8935:822409] Unrecognized selector -[iQuiz.QuestionOption initWithCoder:]
Here's my storyboard if that helps at all
I've made sure my identifier matches and I don't have any extraneous or unconnected outlets, those are the only solution to this problem I can find online.
The crash log says that QuestionOption must be a subclass of NSObject and adopt NSCoding which is overkill in this case. Actually a struct would be sufficient.
You can avoid it by deleting the method in QuestionOptionCell
func setOption(option: QuestionOption){
cellTitle.text = option.text
}
and set the value in cellForRowAt directly by replacing
cell.setOption(option: a)
with
cell.cellTitle.text = a.text
Things to check:
Verify that "QuestionOptionCell" is indeed the reuse identifier for the cell.
Verify that the selected type for the cell is QuestionOptionCell.
In cellForRowAt, use tableView.dequeueReusableCell instead of qTableView.dequeueReusableCell.
Otherwise, share the crash log with us.
I am running into a weird issue when creating a customHeader for my tableView. the error that I am receiving is the following:
nib must contain exactly one top level object which must be a UITableViewHeaderFooterView instance
I ran through my code and xib file as well as examples but I couldnt find anything wrong any ideas I am missing?
The header Xib was created with a regular view and then a sub view with a label, the class was created with the following:
CustomTableHeader Class:
class CustomTableHeader: UITableViewHeaderFooterView {
static var CustomTableHeaderIdentifier = "CustomTableHeader"
#IBOutlet weak var titleLabel: UILabel!
override awakeFromNib(){
super.awakeFromNib()
self.titleLabel.text = "Header"
}
override func prepareForReuse() {
super.prepareForReuse()
}
}
ViewController Class:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.register(UINib.init(nibName: CustomTableHeader.CustomTableHeaderIdentifier, bundle: nil), forHeaderFooterViewReuseIdentifier: CustomTableHeader.CustomTableHeaderIdentifier)
}
//Other Methods
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: CustomTableHeader.CustomTableHeaderIdentifier) as? CustomTableHeader {
header.titleLabel.text = "Section 1"
return header
}
}
I figured out my issue! Just in case anybody ever runs into this, make sure that your first view is truly the only object in the XIB file. For example on mine I was trying to add a gesture to the header view and this is considered an object as well. If you want to add a gesture you can do so programmatically:
addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(/* FUNCTION */)))
I'm trying to pass text from one textField to another textField (both of them are located in two different containerViews). I try to accomplish this with delegate. I've already read tons of related questions here, at stack overflow and read a couple of articles, so, I think I'm doing well except one thing: I don't know how to delegate without segue. Here's the code:
protocol AddOneWordViewControllerDelegate: class {
func changeTexeValue(_ text: String?)
}
class AddOneWordViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var oneWordAddWord: UITextField!
weak var delegate: AddOneWordViewControllerDelegate?
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func addOneWordWordChanged(_ sender: UITextField) {
self.delegate?.changeTexeValue(oneWordAddWord.text!)
print ("Value of the textField did change \(oneWordAddWord.text!)")
} // this action is from textField, named "Value Changed"
}
class AddTwoWordsViewController: UIViewController, UITextFieldDelegate, AddOneWordViewControllerDelegate {
#IBOutlet weak var twoWordsAddWord: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
func changeTexeValue(_ text: String?) {
self.twoWordsAddWord.text = text
print("Delegate is working")
}
}
I am making an app to keep track of my homework and for some reason when I call reloadData it doesn't work, some people have already asked about this but I have tried there fixes and they don't work for me, here is the file where I add new homework:
import UIKit
class AddHomework : UIViewController {
#IBOutlet weak var HomeworkNameLbl: UILabel!
#IBOutlet weak var HomeworkNameTxt: UITextField!
#IBOutlet weak var DueDateLbl: UILabel!
#IBOutlet weak var DueDateTxt: UITextField!
#IBOutlet weak var DueTimeLbl: UILabel!
#IBOutlet weak var DueTimeTxt: UITextField!
#IBOutlet weak var AddHomeworkBtn: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
self.hideKeyboardWhenTappedAround()
}
#IBAction func AddHomework(sender: UIButton) {
let HomeworkName = HomeworkNameTxt.text
let DueDate = DueDateTxt.text
let DueTime = DueTimeTxt.text
homeworkTableView().AddObject([DueDate!, DueTime!], HomeworkName: HomeworkName!)
}
func hideKeyboardWhenTappedAround() {5
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
view.addGestureRecognizer(tap)
}
func dismissKeyboard() {
view.endEditing(true)
}
}
Here is the file where I have my tableview:
import UIKit
class homeworkTableView: UIViewController, UITableViewDelegate, UITableViewDataSource{
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.reloadData()
}
var homework : [String: [String]] = [
"Spanish Test": ["Aug 12", "12:00 AM", "Spanish"],
"Math Sheet": ["Aug 13", "10:30 PM","Math"],
"Code Thing": ["Aug 11","12:00 AM","Coding"]
]
var titles = [
"Spanish Test", "Math Sheet", "Code Thing"
]
func AddObject(newArray: [String], HomeworkName: String){
titles.append(HomeworkName)
homework.updateValue(newArray, forKey: HomeworkName)
print(homework)
print(titles)
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return titles.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let Cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! CustomCell
Cell.Title.text = titles[indexPath.row]
let currentTitle = titles[indexPath.row]
let current = homework[currentTitle]!
Cell.DueDate.text = "Due Date: \(current[0])"
Cell.Class.text = "Due Time: \(current[1])"
self.tableView.rowHeight = 100.00
return Cell
}
}
And the whole project is posted on git here:
https://github.com/IndyBob2019/HomeworkHelper
Any help is much appreciated, thanks!
You need to do what you do in viewDidLoad in viewWillAppear. viewDidLoad is only called at startup, so despite changing the data, your view never changes its own local data, so when you call reloadData it still uses the old data.
Taken from tableView reloadData does not work.
Here are some pointers based from your code,
First:
You're just calling -reloadData() once in viewDidLoad()..
Second:
If you want to see the changes made, it has to be in this order Update your -dataSource > -reloadData()
ex. from your code...
func AddObject(newArray: [String], HomeworkName: String){
titles.append(HomeworkName)
homework.updateValue(newArray, forKey: HomeworkName)
// check is changes was made
print(homework)
print(titles)
// reload after updating datasource
self.tableView.reloadData()
}
Edit:
After checking your project, i must say that your approach different from what i have in mind..
Calling calling -reloadData() once in viewDidLoad() is correct, but the problem is your
table dataSource which was updated inside File.swift by:
homeworkTableView().AddObject([DueDate!, DueTime!], HomeworkName: HomeworkName!)
You initialized homeworkTableView class and added or appended the data within that class
but upon presenting the homeworkTableView viewController from navigationController, you are
presenting new homeworkTableView class (not the homeworkTableView that was update)..
Calling self.tableView.reloadData() says:
fatal error: unexpectedly found nil while unwrapping an Optional value
because self.tableView was nil during the time of the update,
Here the solution I made:
First:
Globalizing your dataSource for Cross class updating, like so:
import Foundation
import UIKit
// I just moved your variables outside the class
//
var homework : [String: [String]] = [
"Spanish Test": ["Aug 12", "12:00 AM", "Spanish"],
"Math Sheet": ["Aug 13", "10:30 PM","Math"],
"Code Thing": ["Aug 11","12:00 AM","Coding"]
]
var titles = [
"Spanish Test", "Math Sheet", "Code Thing"
]
class homeworkTableView: UIViewController, UITableViewDelegate, UITableViewDataSource{
...
// codes
...
}
Second:
Removing self.tableView.reloadData() inside func AddObject(.. which i suggested before (without knowledge of your approach/implementation),
like:
func AddObject(newArray: [String], HomeworkName: String){
titles.append(HomeworkName)
homework.updateValue(newArray, forKey: HomeworkName)
// check is changes was made
print(homework)
print(titles)
}
I have created two custom labels in a table cell in order to be able to dynamically resize the cell(s) to it's content. I first tried using the "Subtitle" style and this worked out great except that the cell(s) didn't resize the way i wanted to and it looked really messy.
My question is: how do I access these labels in order to append my value's from my API to them?
View controller code:
import UIKit
class nyheterViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, APIControllerProtocol {
#IBOutlet weak var nyheterTableView: UITableView!
#IBOutlet weak var titleLabel: UILabel!
var searchResultsData: NSArray = []
var api: APIController = APIController()
func JSONAPIResults(results: NSArray) {
dispatch_async(dispatch_get_main_queue(), {
self.searchResultsData = results
print(self.searchResultsData)
self.nyheterTableView.reloadData()
})
}
override func viewDidLoad() {
super.viewDidLoad()
var APIBaseUrl: String = "http://*.se/*/*.php"
var urlString:String = "\(APIBaseUrl)"
//Call the API by using the delegate and passing the API url
self.api.delegate = self
api.GetAPIResultsAsync(urlString, elementName:"news")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//print(self.searchResultsData.count)
return self.searchResultsData.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier: String = "nyheterResultsCell"
let cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as UITableViewCell
//nyheterTableViewCell.cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier);
//Create a variable that will contain the result data array item for each row
var cellData: NSDictionary = self.searchResultsData[indexPath.row] as NSDictionary
//Assign and display the Title field
var releaseDate: String = cellData["date"] as String
var titleVar: String = cellData["title"] as String
var titleMix: String = "\(titleVar)" + " - " + "\(releaseDate)"
cell.textLabel?.text = titleMix //textLabel worked out fine using "Subtitle" style.
// Get the release date string for display in the subtitle
cell.detailTextLabel?.text = cellData["content"] as String? //Same
return cell
}
}
I understand that I can't access these labels without somehow connecting them to the ViewController. Creating outlets to the ViewController generates an error about that I can't use connections from the prototype cell to the ViewController.
So, i created a new class, called nyheterTableViewCell which i connect to the table cell and connected outlets to my labels.
nyhterTableViewCell code:
import UIKit
class nyheterTableViewCell: UITableViewCell {
#IBOutlet weak var nyhetLabel: UILabel!
#IBOutlet weak var titleLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
I'm an beginner at Swift-programming and Xcode.
Cheers!
You don't need the labels connected to the view controller. Your example of the custom table view cell looks correct.
To access the label properties, you're going to want to change the line
let cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as UITableViewCell
to
let cell: nyheterTableViewCell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as nyheterTableViewCell