I am stuck with the following code:
I am trying to build a segue between a table view and a detail view with an attached json file
error: Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
What am I doing wrong?
Code:
// This code is for the transfer to the next page
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = storyboard?.instantiateViewController(withIdentifier: "ActionDetailViewController") as? ActionDetailViewController
let action = result?.data3[indexPath.row]
vc?.ActionTitleDetail.text = action?.actionTitle
self.navigationController?.pushViewController(vc!, animated: true)
Also I need help to use more details from the json file on the detail view besides the elements in the table view.
Thanks
Post
Replies
Boosts
Views
Activity
I have parsed a json file with the following structure into a table view succesfully.
import Foundation
struct ActionResult: Codable {
let data3: [Datum]
}
struct Datum: Codable {
let actionGoal, actionGoalDescription, actionGoalImage: String
let actions: [Action]
}
struct Action: Codable {
let actionTitle: String
let actionID: Int
let select, completed, favorite: Bool
let actionType, actionDescription, actionTips, actionImage: String
let actionSponsor, actionSponsorURL: String
Now I am preparing a segue to a detail ViewController but is giving me an error.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "showDetail", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? ActionDetailViewController {
destination.action = result?.data3.actions[(tableView.indexPathForSelectedRow?.row)!]
Error description. Value of type '[Datum]' has no member 'actions'
Who can help me?
I have parsed a json file with the following structure into a table view succesfully.
import Foundation
struct ActionResult: Codable {
let data3: [Datum]
}
struct Datum: Codable {
let actionGoal, actionGoalDescription, actionGoalImage: String
let actions: [Action]
}
struct Action: Codable {
let actionTitle: String
let actionID: Int
let select, completed, favorite: Bool
let actionType, actionDescription, actionTips, actionImage: String
let actionSponsor, actionSponsorURL: String
Now I am preparing a segue to a detail ViewController but is giving me an error.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "showDetail", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? ActionDetailViewController {
destination.action = result?.data3.actions[(tableView.indexPathForSelectedRow?.row)!]
Error description. Value of type '[Datum]' has no member 'actions'
Who can help me?
Additional info: DetailViewController set up
import UIKit
import SwiftUI
class ActionDetailViewController: UIViewController {
@IBOutlet weak var ActionImageDetail: UIImageView!
@IBOutlet weak var ActionTitleDetail: UILabel!
@IBOutlet weak var ActionDescriptionDetail: UITextView!
@IBOutlet weak var ActionTipsDetail: UITextView!
var action: Action?
override func viewDidLoad() {
super.viewDidLoad()
ActionTitleDetail.text = action?.actionTitle
ActionImageDetail.image = UIImage(named: action!.actionImage)
ActionDescriptionDetail.text = action?.actionDescription
ActionTipsDetail.text = action?.actionTips
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
I have data with a section. I followed the instructions to add a search bar but I am running into errors due to my sections.
My data model looks like this:
struct ActionResult: Codable {
let data3: [Datum]
}
struct Datum: Codable {
let actionGoal, actionGoalDescription, actionGoalImage: String
let actions: [Action]
}
struct Action: Codable {
let actionTitle: String
let actionID: Int
let select, completed, favorite: Bool
let actionType, actionDescription, actionTips, actionImage: String
let actionSponsor, actionSponsorURL: String
My table view code looks like this:
import SwiftUI
class ActionViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate {
@IBOutlet weak var ActionTableView: UITableView!
@IBOutlet weak var SearchBar: UISearchBar!
var result: ActionResult?
var index = 0
var filteredData: [String]?
private let tableView: UITableView = {
let table = UITableView(frame: .zero,
style: .grouped)
table.register(UITableViewCell.self, forCellReuseIdentifier: "ActionCell")
return table
}()
override func viewDidLoad() {
super.viewDidLoad()
parseJSON()
view.addSubview(tableView)
self.tableView.frame = view.bounds
self.tableView.delegate = self
self.tableView.dataSource = self
SearchBar.delegate = self
filteredData = result?.data3.actions
The last line has the error code: Value of type [Datum] has no member actions.
The code for the search bar looks like this:
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
filteredData = []
if searchText == "" {
filteredData = result?.data3.actions
}
else {
for action in result?.data3.actions {
if action.lowercase().contains(searchText.lowercased()) {
filteredData.append(action)
}
}
}
self.tableView.reloadData()
}
And this code has the same errors.
Value of type [Datum] has no member actions.
I need help how to declare that my data model has sections.
Thanks!
I am trying to create a note pad in Xcode with core data but I am hitting a wall when I create the table view.
The error is at the code: noteCell.titleLabel.text = thisNote.title
The error is :Value of type 'UITableView' has no member 'text'
var noteList = [Note]()
class NoteTableView: UITableViewController
{
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
var noteCell = tableView.dequeueReusableCell(withIdentifier: "noteCellID", for: indexPath) as! NoteCell
let thisNote: Note!
thisNote = noteList[indexPath.row]
noteCell.titleLabel.text = thisNote.title
noteCell.descriptionLabel.text = thisNote.desc
return noteCell
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return noteList.count
}
override func viewDidAppear(_ animated: Bool) {
tableView.reloadData()
}
}
The noteCell is defined as follows.
class NoteCell: UITableViewCell
{
@IBOutlet var titleLabel: UITableView!
@IBOutlet var descriptionLabel: UITableView!
}
The core date is defined as follows:
import CoreData
@objc(Note)
class Note: NSManagedObject
{
@NSManaged var id: NSNumber!
@NSManaged var title: String?
@NSManaged var desc: String?
@NSManaged var deletedDate: Date?
}
Thank you!
I am trying to use the following data model to create a table view.
I have 3 questions?
where can I find more detailed information to set up table views?
how do I set up my section statement in the case I want to use a dictionary/array? (actionGoal)
in 'numberOfsections' and 'titleForHeaderinSection'
how do I set up an int and an dictionary/array in 'cellForRowAt'.
This is the data model.
import Foundation
struct ActionResult: Codable {
let data: [ActionElement]
}
struct ActionElement: Codable {
let actionID: Int
let actionItem: String
let actionGoal: ActionGoal
let actionImage: String
let actionBenefit: ActionBenefit
let actionSavings: Int
let actionType: ActionType
let actionDescription, actionTips: String
let actionInformationURL: String
let actionSponsorURL: String
enum CodingKeys: String, CodingKey {
case actionID = "ActionID"
case actionItem = "ActionItem"
case actionGoal = "ActionGoal"
case actionImage = "ActionImage"
case actionBenefit = "ActionBenefit"
case actionSavings = "ActionSavings"
case actionType = "ActionType"
case actionDescription = "ActionDescription"
case actionTips = "ActionTips"
case actionInformationURL = "ActionInformationURL"
case actionSponsorURL = "ActionSponsorURL"
}
}
enum ActionBenefit: String, Codable {
case costs = "Costs"
case education = "Education"
case environment = "Environment"
case health = "Health"
}
enum ActionGoal: String, Codable {
case cleanEnergy = "Clean Energy"
case cleanWater = "Clean Water"
case climateAction = "Climate Action"
case economicGrowth = "Economic Growth"
case goodHealth = "Good Health"
case noPoverty = "No *******"
case promoteEquality = "Promote Equality"
case qualityEducation = "Quality Education"
case responsibleConsumption = "Responsible Consumption"
case zeroHunger = "Zero Hunger"
}
enum ActionType: String, Codable {
case sticky = "Sticky"
case todoe = "Todoe"
}
typealias Action = [ActionElement]
This is the code for the sections:
return result?.data.count ?? 0
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return result?.data[section].actionGoal
}
Error: Type of expression is ambiguous without more context.
And this is the 'cellForRowAt' code:
cell.actionBenefit.text = action?.actionBenefit
cell.actionSavings.text = action?.actionSavings
error codes:
Cannot assign value of type 'ActionType?' to type 'String?'
Cannot assign value of type 'Int?' to type 'String?'
I know I have asked this type of question before but I am trying to understand the concept. Please support me.
I implemented core data and UISteppers in some fields. Every time I am trying to edit a record the UIStepper start counting from 1.
import CoreData
class AktieViewController: UIViewController
{
@IBOutlet weak var titleTF: UITextField!
@IBOutlet weak var typeTF: UITextField!
@IBOutlet weak var notesTV: UITextView!
@IBOutlet weak var counterTF: UITextField!
@IBOutlet weak var pointTF: UITextField!
@IBOutlet weak var savingsTF: UITextField!
@IBOutlet weak var completedTF: UITextField!
@IBOutlet weak var counterStepper: UIStepper!
@IBOutlet weak var pointsStepper: UIStepper!
@IBOutlet weak var savingsStepper: UIStepper!
var selectedAktie: Aktie? = nil
override func viewDidLoad()
{
super.viewDidLoad()
if(selectedAktie != nil)
{
titleTF.text = selectedAktie?.title
typeTF.text = selectedAktie?.type
notesTV.text = selectedAktie?.notes
savingsTF.text = selectedAktie?.saving
counterTF.text = selectedAktie?.counter
pointTF.text = selectedAktie?.point
completedTF.text = selectedAktie?.completed
}
}
// Mark: this is to save the action
@IBAction func saveAction(_ sender: Any) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context: NSManagedObjectContext = appDelegate.persistentContainer.viewContext
if(selectedAktie == nil)
{
let entity = NSEntityDescription.entity(forEntityName: "Aktie", in: context)
let newAktie = Aktie (entity: entity!, insertInto: context)
newAktie.id = aktieList.count as NSNumber
newAktie.title = titleTF.text
newAktie.type = typeTF.text
newAktie.notes = notesTV.text
newAktie.saving = savingsTF.text
newAktie.point = pointTF.text
newAktie.counter = counterTF.text
newAktie.completed = completedTF.text
do {
try context.save()
aktieList.append(newAktie)
navigationController?.popViewController(animated: true)
}
catch
{
print("context save error")
}
}
else // edit
{
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Aktie")
do {
let results: NSArray = try context.fetch(request) as NSArray
for result in results {
let aktie = result as! Aktie
if(aktie == selectedAktie)
{
aktie.title = titleTF.text
aktie.type = typeTF.text
aktie.notes = notesTV.text
aktie.saving = savingsTF.text
aktie.point = pointTF.text
aktie.counter = counterTF.text
aktie.completed = completedTF.text
try context.save()
navigationController?.popViewController(animated: true)
}
}
}
catch
{
print("Fetch Failed")
}
}
}
// this is to delete the action
@IBAction func deletedAktie(_ sender: Any) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context: NSManagedObjectContext = appDelegate.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Aktie")
do {
let results: NSArray = try context.fetch(request) as NSArray
for result in results {
let aktie = result as! Aktie
if(aktie == selectedAktie)
{
aktie.deletedDate = Date ()
try context.save()
navigationController?.popViewController(animated: true)
}
}
}
catch
{
print("Fetch Failed")
}
}
// This function adds the stepper to a field
//issue: it does not remember the score when i edit it and starts over
@IBAction func counterStepperPressed(_ sender: UIStepper) {
counterTF.text = Int(sender.value).description
}
@IBAction func pointStepperPressed(_ sender: UIStepper) {
pointTF.text = Int(sender.value).description
}
@IBAction func savingsStepperPressed(_ sender: UIStepper) {
savingsTF.text = Int(sender.value).description
}
}
I created a core data data model and now I want to total/sum one of the attributes. The data model is as follows:
import CoreData
@objc(Aktie)
class Aktie: NSManagedObject
{
@NSManaged var deletedDate: Date?
@NSManaged var id: NSNumber!
@NSManaged var title: String?
@NSManaged var point: String?
}
The code for the ViewController to show the total is:
import UIKit
import CoreData
var points = [Aktie]()
var firstLoad = true
class TotalPointsViewController: UIViewController {
@IBOutlet weak var totalPoints: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
if(firstLoad)
{
firstLoad = false
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context: NSManagedObjectContext = appDelegate.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Aktie")
do {
let results: NSArray = try context.fetch(request) as NSArray
for result in results {
let aktie = result as! Aktie
points.append(aktie)
}
}
catch
{
print("Fetch Failed")
}
}
}
// Mark: Add total of points
func calculateSumPoints() -> [Aktie] {
let sum = 0
for punt in points.point {
sum += Int(punt)
}
totalPoints.text = "\(sum)"
}
}
What am I doing wrong?
Data model
struct ActionResult: Codable {
let data: [Datum]
}
struct Datum: Codable {
let goalTitle, goalDescription, goalImage: String
let action: [Action]
}
struct Action: Codable {
let actionTitle: String
let actionGoal: String
let actionImage: String
Code
var action: Action? // this is for the segue
var result: ActionResult? {
didSet {
guard let result = result else { return }
allSectionDataActionMap = Dictionary(uniqueKeysWithValues: result.data.enumerated().map { ($0.0, ($0.1, $0.1.action)) })
updateFilteredData()
}
}
var allSectionDataActionMap = [Int: (datum: Datum, actions: [Action])]()
// Maps the section index to the Datum & filtered [Action]
var filteredSectionDataActions = [Int: (datum: Datum, actions: [Action])]()
let searchController = UISearchController()
override func viewDidLoad() {
super.viewDidLoad()
title = "Search"
searchController.searchBar.delegate = self
navigationItem.searchController = searchController
parseJSON()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return filteredSectionDataActions.count
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filteredSectionDataActions[section]?.actions.count ?? 0
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = ActionTableView.dequeueReusableCell(withIdentifier: "ActionCell", for: indexPath) as! ActionTableCell
let action = filteredSectionDataActions[indexPath.section]?.actions[indexPath.row]
// setup cell for action
cell.actionItem.text = action?.actionTitle
cell.actionImage.image = UIImage(named: action!.actionImage)
cell.actionImage.layer.cornerRadius = cell.actionImage.frame.size.width / 2
cell.actionGoal.text = action?.actionGoal
return cell
}
// Mark: This code is to implement the searchBar
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
updateFilteredData(for: searchText.lowercased())
tableView.reloadData()
}
func updateFilteredData(for searchText: String = String()) {
if searchText.isEmpty {
filteredSectionDataActions = allSectionDataActionMap
} else {
for (index, (datum, actions)) in allSectionDataActionMap {
let filteredActions = actions.filter { $0.actionTitle.lowercased().contains(searchText) }
if filteredActions.isEmpty {
filteredSectionDataActions[index] = (datum, actions)
} else {
filteredSectionDataActions[index] = (datum, filteredActions)
}
}
I am trying to filter a json with a UICollectionView. It sorts but does not filter. What is going wrong. The collectionView works, the segue works, the records are sorted, but not filtered on the subjectitem. I am working with the storyboard and connected the segue from the cell to the fragment.
class SubjectViewController: UIViewController {
@IBOutlet var collectionView: UICollectionView!
var subjects: [SubjectItem] = [
SubjectItem(imageName: "grace", name:"Grace"),
SubjectItem(imageName: "family", name: "Family"),
SubjectItem(imageName: "life", name: "Life"),
SubjectItem(imageName: "love", name: "Love"),
SubjectItem(imageName: "nature", name: "Nature"),
SubjectItem(imageName: "telios", name: "Telios"),
SubjectItem(imageName: "words", name: "Words"),
SubjectItem(imageName: "work", name: "Work"),
// Add other subjects
]
override func viewDidLoad() {
super.viewDidLoad()
collectionView.dataSource = self
collectionView.delegate = self
}
}
struct SubjectItem {
let imageName: String
let name: String
}
extension SubjectViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return subjects.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SubjectCell", for: indexPath) as! SubjectCell
let subject = subjects[indexPath.item]
cell.configure(with: subject)
return cell
}
}
extension SubjectViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let selectedSubject = subjects[indexPath.item]
navigateToPoemFragment2(with: selectedSubject)
}
func navigateToPoemFragment2(with subject: SubjectItem) {
print("Selected Subject: \(subject.name)")
if let poemFragment2 = storyboard?.instantiateViewController(withIdentifier: "PoemSortedList") as? PoemFragment2 {
poemFragment2.selectedSubject = subject // Set the selectedSubject property
navigationController?.pushViewController(poemFragment2, animated: true)
}
}
}
class SubjectCell: UICollectionViewCell {
@IBOutlet var imageView: UIImageView!
@IBOutlet var nameLabel: UILabel!
func configure(with subject: SubjectItem) {
imageView.image = UIImage(named: subject.imageName)
nameLabel.text = subject.name
}
}
import UIKit
class PoemFragment2: UITableViewController {
@IBOutlet var poemTableView2: UITableView!
var allPoems: [Poem] = [] // Store all poems here
var filteredPoems: [Poem] = [] // Store filtered poems here
var selectedSubject: SubjectItem? // This should be set when navigating from SubjectViewController
override func viewDidLoad() {
super.viewDidLoad()
parseJSON()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filteredPoems.count // Use filtered poems for table view data source
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let poem = filteredPoems[indexPath.row]
let cell = poemTableView2.dequeueReusableCell(withIdentifier: "PoemCell2", for: indexPath) as! PoemTableViewCell2
cell.poemName2.text = poem.poemName
cell.subject2.text = poem.subject
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "poemDetail2", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? PoemDetailFragment2,
let indexPath = tableView.indexPathForSelectedRow {
destination.poem = filteredPoems[indexPath.row] // Pass the selected poem
}
}
private func parseJSON() {
guard let path = Bundle.main.path(forResource: "poem", ofType: "json") else {
return
}
let url = URL(fileURLWithPath: path)
do {
let jsonData = try Data(contentsOf: url)
allPoems = try JSONDecoder().decode(PoemData.self, from: jsonData).poem
print("All Poems: \(allPoems)")
filterAndSortPoems() // After parsing, apply filter and sort
} catch {
print("Error: \(error)")
}
}
func filterAndSortPoems() {
if let selectedSubject = selectedSubject {
// Print the selected subject for debugging
print("Selected Subject: \(selectedSubject.name)")
// Filter poems by selected subject
filteredPoems = allPoems.filter { poem in
return poem.subject.localizedCaseInsensitiveCompare(selectedSubject.name) == .orderedSame
}
// Sort the filtered poems by subject
filteredPoems.sort { $0.subject.localizedCaseInsensitiveCompare($1.subject) == .orderedAscending }
} else {
// If no subject is selected, show all poems
filteredPoems = allPoems
// Sort all poems by subject
filteredPoems.sort { $0.subject.localizedCaseInsensitiveCompare($1.subject) == .orderedAscending }
}
// Print the filtered result for debugging
print("Filtered Result: \(filteredPoems)")
tableView.reloadData() // Reload the table view with filtered data
}
}