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
Selecting any option will automatically load the page
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 Poverty"
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
}
}