What identifier should I add for this optional? - swift

I want to add this optional
var mapRegion : MKCoordinateRegion
It gives me an error that I need an identifier next to class:
class TableViewController: UITableViewController, NSFetchedResultsControllerDelegate,
What's that identifier?
The file looks like this:
import UIKit
import CoreData
import MapKit
class TableViewController: UITableViewController, NSFetchedResultsControllerDelegate, {
let moc = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
var frc : NSFetchedResultsController = NSFetchedResultsController()
var mapRegion : MKCoordinateRegion
func fetchRequest() -> NSFetchRequest {
let fetchRequest = NSFetchRequest(entityName: "Item")
let sortDescriptor = NSSortDescriptor(key: "name",
ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
return fetchRequest
}
func getFRC() -> NSFetchedResultsController {
frc = NSFetchedResultsController(fetchRequest: fetchRequest(), managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)
return frc
}
override func viewDidLoad() {
super.viewDidLoad()
frc = getFRC()
frc.delegate = self
do {
try frc.performFetch()
} catch {
print("Failed to perform initial fetch.")
return
}
self.tableView.rowHeight = 480
self.tableView.backgroundView = UIImageView( image: UIImage(named: "flatgrey2"))
self .tableView.reloadData()
}
override func viewDidAppear(animated: Bool) {
frc = getFRC()
frc.delegate = self
do {
try frc.performFetch()
} catch {
print("Failed to perform initial fetch.")
return
}
self .tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
let numberOfSections = frc.sections?.count
return numberOfSections!
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
let numberofRowsInSection = frc.sections?[section].numberOfObjects
return numberofRowsInSection!
//return 0
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
if indexPath.row % 2 == 0 {
cell.backgroundColor = UIColor.clearColor()
} else {
cell.backgroundColor = UIColor.whiteColor().colorWithAlphaComponent(0.2)
cell.textLabel?.backgroundColor = UIColor.whiteColor().colorWithAlphaComponent(0.0)
cell.detailTextLabel?.backgroundColor = UIColor.whiteColor().colorWithAlphaComponent(0.0)
}
// Configure the cell...
cell.textLabel?.textColor = UIColor.darkGrayColor()
cell.detailTextLabel?.textColor = UIColor.darkGrayColor()
let item = frc.objectAtIndexPath(indexPath) as! Item
cell.textLabel?.text = item.name
cell.imageView?.image = UIImage(data: (item.image)!)
return cell
}
/*
// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
*/
// Override to support editing the table view.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
let managedObject : NSManagedObject = frc.objectAtIndexPath(indexPath) as! NSManagedObject
moc.deleteObject(managedObject)
do {
try moc.save()
} catch {
print ("Failed to save.")
return
}
}
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
tableView.reloadData()
}
/*
// Override to support rearranging the table view.
override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
*/
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
if segue.identifier == "edit" {
let cell = sender as! UITableViewCell
let indexPath = tableView.indexPathForCell(cell)
let itemController : AddEditVC = segue.destinationViewController as! AddEditVC
let item : Item = frc.objectAtIndexPath(indexPath!) as! Item
itemController.item = item
}
}
}

The variable should have a value when it is declared otherwise it will show this error. Assign a value to your variable var mapRegion : MKCoordinateRegion. If the value is given at a later stage i.e., if it depends on any calculations then make it an optional like this var mapRegion : MKCoordinateRegion? But you have to unwrap the variable whenever you want to use mapRegion value by placing an exclamation mark at the end of the variable name.

You have declared var mapRegion : MKCoordinateRegion but don't have any initializers or default value. To make it an optional, just add ? to it, so declare:
var mapRegion : MKCoordinateRegion?

Related

How to reload a collectionview when I tap on back?

My collectionview did not reload when I tap back from the tableview where I the list reorder.
I have read a few topics but I don't know what's wrong. Can anybody find it?
And can I the speak part of the code place in an apart swift file and include this ViewController. So yes, how? Because I use that in more ViewControllers.
Below is my code.
Thank you very much.
import UIKit
import AVFoundation
class CollectionViewController: UICollectionViewController {
#IBOutlet var soundBoard: UICollectionView!
var list = ["January","February","March","April","May","June", "July","August","September","October","November", "December"]
var bgColor = [""]
var buttonOn: Bool = true
override func viewDidLoad() {
super.viewDidLoad()
let blockItems = UserDefaults.standard.object(forKey:"soundboard")
if(blockItems != nil) {
list = blockItems as! [String]
}
let itemSize = UIScreen.main.bounds.width/2 - 2
let itemHeight = itemSize / 2
let layout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsetsMake(3, 0, 3, 0)
layout.itemSize = CGSize(width: itemSize, height: itemHeight)
layout.minimumInteritemSpacing = 3
layout.minimumLineSpacing = 3
soundBoard.collectionViewLayout = layout
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
self.collectionView!.reloadData()
}
// MARK: - Collection View
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of items
return list.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> MyCollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! MyCollectionViewCell
cell.cellTitle.text = list[indexPath.row]
return cell
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
Speak(currentTitle: list[indexPath.row])
}
// MARK: - Speak function
let synth = AVSpeechSynthesizer()
var myUtterance = AVSpeechUtterance(string: "")
func Speak(currentTitle: String) {
if !synth.isSpeaking {
// Controleert volume
let volume = AVAudioSession.sharedInstance().outputVolume
if volume < 0.5 {
MuteButton()
}
// Spreekt de tekst uit
let myUtterance = AVSpeechUtterance(string: currentTitle)
myUtterance.rate = 0.4
myUtterance.volume = 1
if let theVoice = UserDefaults.standard.object(forKey:"voice") {
myUtterance.voice = AVSpeechSynthesisVoice(language: theVoice as? String)
}
synth.speak(myUtterance)
}
}
func MuteButton() {
let alertController = UIAlertController(title: "Check your volume", message:
"Please check your volume or mute button.", preferredStyle: UIAlertControllerStyle.alert)
alertController.addAction(UIAlertAction(title: "Close", style: UIAlertActionStyle.default,handler: nil))
self.present(alertController, animated: true, completion: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: -- Save UserDefaults
func save() {
UserDefaults.standard.set(self.list, forKey:"soundboard")
UserDefaults.standard.synchronize()
self.collectionView?.reloadData()
}
// MARK: -- Add new sound item
#IBAction func addNew(_ sender: Any) {
let alertController = UIAlertController(title: "Create a new sound", message: "", preferredStyle: UIAlertControllerStyle.alert)
alertController.addTextField { (textField: UITextField) in
textField.keyboardAppearance = .dark
textField.keyboardType = .default
textField.autocorrectionType = .default
textField.placeholder = "Type something here"
textField.clearButtonMode = .whileEditing
}
alertController.addAction(UIAlertAction(title: "Create", style: .default) { [weak alertController] _ in
if let alertController = alertController {
let loginTextField = alertController.textFields![0] as UITextField
self.list.append( loginTextField.text!)
self.save()
}
})
alertController.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.default,handler: nil))
self.present(alertController, animated: true, completion: nil)
}
}
Two things are happening here. First you appear to have two different collection views in CollectionViewController; collectionView which is inherited from the superclass and soundboard which you declare. In viewWillAppear you tell collectionView to reload. If this is not the one that is hooked up in IB nothing will work.
The second issue is that while in soundboardTableViewController you update the user default with the correct data you never read it after the view loads in CollectionViewController.
You should move this:
let blockItems = UserDefaults.standard.object(forKey:"soundboard")
if(blockItems != nil) {
list = blockItems as! [String]
}
into viewWillAppear before your call to reload the collection view and then verify you are telling the right collection view to reload.
I see a few things that could be going wrong here. It would help to see the code in the other view controller however.
First are you sure that you're reordering your model array properly? Remember in swift an array is a value type. Meaning that if you pass the array to another view you're passing a copy of that array and not the array in your collection view controller. It may be a better idea to wrap your model array in an object which you can pass a reference to. More on that here.
Also it's better to tie a reload to a change in your model instead of the view lifecycle. To do that with your current code you could do something like this:
var list = ["January","February","March","April","May","June", "July","August","September","October","November", "December"] {
didSet {
self.collectionView?.reloadData()
// or
self.soundBoard.reloadData()
// I'm confused about which collection view you're using/trying to reload.
}
}
Please let me know if you have any questions. I'll keep an eye out and can edit my answer if needed.
This is the code of the other ViewController where you can reorder the rows and can tap on < Back.
import UIKit
class soundboardTableViewController: UITableViewController {
var list = ["January","February","March","April","May","June", "July","August","September","October","November", "December"]
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.rightBarButtonItem = self.editButtonItem
let blockItems = UserDefaults.standard.object(forKey:"soundboard")
if(blockItems != nil) {
list = blockItems as! [String]
}
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return list.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = list[indexPath.row]
return cell
}
// Override to support conditional editing of the table view.
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
/* Override to support editing the table view.*/
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
list.remove(at: indexPath.row)
UserDefaults.standard.set(self.list, forKey:"soundboard")
UserDefaults.standard.synchronize()
tableView.reloadData()
}
}
// Override to support rearranging the table view.
override func tableView(_ tableView: UITableView, moveRowAt indexPath: IndexPath, to: IndexPath) {
/*let itemToMove = list[indexPath.row]
list.remove(at: indexPath.row)
list.insert(itemToMove, at: indexPath.row)
UserDefaults.standard.set(self.list, forKey:"soundboard")
UserDefaults.standard.synchronize()*/
let itemToMove = list[indexPath.row]
list.remove(at: indexPath.row)
list.insert(itemToMove, at: to.row)
UserDefaults.standard.set(self.list, forKey:"soundboard")
}
override func setEditing(_ editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
if(self.isEditing) {
}
}
// Override to support conditional rearranging of the table view.
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
}

Not able to add items to list with Core Data

When I press Add no item gets added to the list. What is wrong with my code?
I am trying to make a grocery list with persistence using Core Data.
Please help me.
Is it a mistake in the Core Data part or with the alertController?
import UIKit
import CoreData
class GroceryTableTableViewController: UITableViewController {
var groceries = [NSManagedObject]()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
}
override func viewWillAppear(_ animated: Bool) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managedContext = appDelegate.persistentContainer.viewContext
super.viewWillAppear(animated)
loadData()
}
func loadData(){
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managedContext = appDelegate.persistentContainer.viewContext
let request:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Groceries")
do {
let results = try managedContext.fetch(request)
groceries = results as! [NSManagedObject]
}
catch {
//print(<#T##items: Any...##Any#>)("Error in retrieving Grocery items")
let fetchError = error as NSError
print(fetchError)
}
}
#IBAction func addAction(_ sender: UIBarButtonItem) {
let alertController = UIAlertController(title: "Grocery List", message: "Add Item", preferredStyle: UIAlertControllerStyle.alert)
alertController.addTextField { (textField : UITextField!) -> Void in
}
let addAction = UIAlertAction(title: "Add", style:UIAlertActionStyle.default) { (action: UIAlertAction) -> Void in
func saveItem(itemToSave : String) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managedContext = appDelegate.persistentContainer.viewContext
let entityDescription = NSEntityDescription.entity(forEntityName: "Groceries", in: managedContext)
let item = NSManagedObject(entity: entityDescription!, insertInto: managedContext)
item.setValue(itemToSave, forKey: "item")
do {
try managedContext.save()
self.groceries.append(item)
}
catch {
print("Error in storing to Core Data")
}
}
self.loadData()
}
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.default) { (action: UIAlertAction) -> Void in
}
alertController.addAction(addAction)
alertController.addAction(cancelAction)
present(alertController, animated: true, completion: nil)
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return groceries.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let item = groceries[indexPath.row]
cell.textLabel?.text = item.value(forKey: "item") as! String
return cell
}
/*
// Override to support conditional editing of the table view.
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
*/
/*
// Override to support editing the table view.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
tableView.deleteRows(at: [indexPath], with: .fade)
} else if editingStyle == .insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
*/
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}

UITableview doesn't show the cell I made as nib File in swift

Hello I'm in trouble with making UITableview. I made cell as nib file and want to display the cell in the UITableView. But nib file doesn't show in the UItableview when I start the app. I don't know how to figure this out. the source is below
import UIKit
class DownLoadPlayViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
#IBOutlet var tableview: UITableView!
#IBOutlet var totalNumSizeInfo:UILabel!
let cellID:String = "DownLoadPlayViewControllerCell"
var downloadedContents: [Dictionary<String,String>] = []
var showContents: Dictionary<String,String> = [:]
override func viewDidLoad() {
super.viewDidLoad()
self.tableview.delegate = self
self.tableview.dataSource = self
self.tableview.registerClass(DownLoadPlayViewControllerCell.classForCoder(), forCellReuseIdentifier: "DownLoadPlayViewControllerCell")
// self.tableview.registerClass(DownLoadPlayViewControllerCell.self, forCellReuseIdentifier: "DownLoadPlayViewControllerCell")
// self.tableview.registerNib(UINib(nibName: "DownLoadPlayViewControllerCell", bundle: nil), forCellReuseIdentifier: "DownLoadPlayViewControllerCell")
downloadedContents = getDownloadInformation()!;
totalNumSizeInfo.text = "초기화 상태"
// let contentInfo : Dictionary<String,String> = self.downloadedContents[0]
// print(contentInfo["contentTitle"])
// print(contentInfo["viewDate"])
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*Podlist에 있는 다운로드 파일정보를 가져온다. */
func getDownloadInformation() -> [Dictionary<String,String>]?{
var returnValue : [Dictionary<String,String>]? =
NSUserDefaults.standardUserDefaults().objectForKey("downloadedContents") as? [Dictionary<String,String>]
if((returnValue?.isEmpty) == true){
returnValue = nil
}
return returnValue
}
// func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// return 1
// }
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return downloadedContents.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
// let cell = tableView.dequeueReusableCellWithIdentifier("DownLoadPlayViewControllerCell", forIndexPath: indexPath) as! DownLoadPlayViewControllerCell
let cell = tableView.dequeueReusableCellWithIdentifier("DownLoadPlayViewControllerCell") as! DownLoadPlayViewControllerCell
let contentInfo : Dictionary<String,String> = self.downloadedContents[indexPath.row]
cell.titleLabel?.text = contentInfo["contentTitle"]
cell.dateLabel?.text = contentInfo["viewDate"]
return cell;
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
let contentInfo : Dictionary<String,String> = self.downloadedContents[indexPath.row]
print(contentInfo["downLoadURL"])
}
//MARK: ButtonClickArea
#IBAction func closeButtonClick(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
}
You need reloadData for your tableview after run the command downloadedContents = getDownloadInformation()!. Just run tableview.reloadData() like that:
downloadedContents = getDownloadInformation()!;
tableview.reloadData() //---------> add new like here
totalNumSizeInfo.text = "초기화 상태"
Here is how to use a custom created cell.
Note: I am not using StoryBoard and I have created the cell in a nib.
CustoMCell Class Code:
import UIKit
class ActivityTableViewCell: UITableViewCell {
// MARK: - Constants & variable
// your outlets if any
// MARK: - UITableViewCell methods
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
}
// MARK: - helper methods
class func cellForTableView(tableView: UITableView, atIndexPath indexPath: NSIndexPath) -> ActivityTableViewCell {
let kActivityTableViewCellIdentifier = "kActivityTableViewCellIdentifier"
tableView.registerNib(UINib(nibName: "ActivityTableViewCell", bundle: NSBundle.mainBundle()), forCellReuseIdentifier: kActivityTableViewCellIdentifier)
let cell = tableView.dequeueReusableCellWithIdentifier(kActivityTableViewCellIdentifier, forIndexPath: indexPath) as! ActivityTableViewCell
return cell
}
}
And this is how I use it in my TableView
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = ActivityTableViewCell.cellForTableView(tableView, atIndexPath: indexPath)
// access your cell properties here
return cell
}
I solve the problem by modifying the tablecellController like this
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
self.alpha = 0
UIView.animateWithDuration(0.2, delay: 0, options: .CurveEaseIn, animations: {
self.alpha = 1
}, completion: { finished in
})
}

Saving values to UserDefults from Textfield in TableView : Swift

I am trying to save values from a tableview that users will input into the textfield, the problem is that I do not know how to access the new value and replace the string in the array.
So basically the app will display fields based on what the user wants and then the user can edit those values to their liking. Once the textfields have been updated, the values are stored again in userdefaults so that the next time the tableview is opened, the update values will appear.
This is what the tableviewcontroller looks like at the moment:
//
// Asset1TableViewController.swift
// Net Calc 2
//
// Created by Joshua Peterson on 30/06/2015.
// Copyright © 2015 Peterson Productions. All rights reserved.
//
import UIKit
class Asset1TableViewController: UITableViewController {
var dataHolder: [NSString] = [NSString]()
var finalDataHolder: [NSString] = [NSString]()
var acountAmountHolder: [NSString] = [NSString]()
var finalAccountAmountHolder: [NSString] = [NSString]()
let defaults = NSUserDefaults.standardUserDefaults()
let key1 = "keySave1"
let key2 = "keySave2"
override func viewDidLoad() {
super.viewDidLoad()
dispatch_async(dispatch_get_main_queue(), { () -> Void in
if let storedTitleValue : NSArray? = self.defaults.arrayForKey(self.key1) {
if storedTitleValue == nil {
self.dataHolder = [NSString]()
} else {
let readArray : [NSString] = storedTitleValue as! [NSString]
for element in readArray {
self.dataHolder.append(element as String)
self.finalDataHolder.append(element as String)
}
}
}
if let storedAmountValue : NSArray? = self.defaults.arrayForKey(self.key2) {
if storedAmountValue == nil {
self.acountAmountHolder = [NSString]()
} else {
let readArray : [NSString] = storedAmountValue as! [NSString]
for element in readArray {
self.acountAmountHolder.append(element as String)
self.finalAccountAmountHolder.append(element as String)
}
}
}
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataHolder.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Account1Cell", forIndexPath: indexPath) as! Account1Cell
cell.AccountLabel.text = dataHolder[indexPath.row] as String
cell.AccountAmount.text = acountAmountHolder[indexPath.row] as String
return cell
}
#IBAction func addButtonTapped(sender: AnyObject) {
let newAccounTitle = "Account Name"
let newAccountAmount = "R0.00"
dataHolder.append(newAccounTitle)
acountAmountHolder.append(newAccountAmount)
tableView.reloadData()
}
#IBAction func saveButtonTapped(sender: AnyObject) {
// Save
defaults.setObject(dataHolder as Array, forKey: key1)
defaults.setObject(acountAmountHolder as Array, forKey: key2)
defaults.synchronize()
}
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == UITableViewCellEditingStyle.Delete {
dataHolder.removeAtIndex(indexPath.row)
acountAmountHolder.removeAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
}
}
/*
// Override to support rearranging the table view.
override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return NO if you do not want the item to be re-orderable.
return true
}
*/
}
I have tried to apply some of the code that i have found on the website but the problem is that I cant actually connect to the cell.
Ok so after some research I have added a few functions to the custom cell class so that it looks like this:
import UIKit
protocol TableViewCellDelegate {
// Indicates that the edit process has begun for the given cell
func cellDidBeginEditing(editingCell: Account1Cell)
// Indicates that the edit process has committed for the given cell
func cellDidEndEditing(editingCell: Account1Cell)
}
class Account1Cell: UITableViewCell, UITextFieldDelegate {
#IBOutlet weak var AccountLabel: UITextField!
#IBOutlet weak var AccountAmount: UITextField!
var delegate: TableViewCellDelegate?
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
AccountLabel.delegate = self
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
// close the keyboard on Enter
AccountLabel.resignFirstResponder()
return false
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
// disable editing of completed to-do items
return true
}
func textFieldDidEndEditing(textField: UITextField) {
if AccountLabel != nil {
let newAccountLabel = AccountLabel.text
print(newAccountLabel) // Prints out the new edited text!!!!!!!!
}
if delegate != nil {
delegate!.cellDidEndEditing(self)
}
}
func textFieldDidBeginEditing(textField: UITextField) {
if delegate != nil {
delegate!.cellDidBeginEditing(self)
}
}
}
Now what I need to do is either replace that value in the Array at the index (which i think is going to be rather complicated) or create some sort of loop that will read ALL the values and simply store all of the new values to UserDefaults. Maybe there is something else?
Any help is appreciated!!
You should have a protocol in your custom cell like this, and call it when the text field in the cell gets modified:
protocol TableViewCellToTVController{
func cellCurrentlyEditing(editingCell: Account1Cell) -> Int
}
....
func textFieldShouldReturn(textField: UITextField) -> Bool {
// close the keyboard on Enter
let myrow: Int? = self.delegate_special?.cellCurrentlyEditing(self)
println("cellCurrentlyEditing got called from delegate" , myrow)
AccountLabel.resignFirstResponder()
return false
}
implement this function in tableviewcontroller to know which row got selected :
func cellCurrentlyEditing(editingCell: Account1Cell) -> Int{
var rowNum = 0
let indexP: NSIndexPath = tableView.indexPathForCell(editingCell)!
rowNum = indexP.row
return rowNum
}
also make your tableviewcontroller the delegate for each cell:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Account1Cell", forIndexPath: indexPath) as! Account1Cell
cell.AccountLabel.text = dataHolder[indexPath.row] as String
cell.AccountAmount.text = acountAmountHolder[indexPath.row] as String
cell.delegate_special = self;
return cell
}

swift refresh control fatal error: unexpectedly found nil while unwrapping an Optional value

I'm working with tableview controller and try to add pull refresh features but i'm having unexpectedly found nil while unwrapping an Optional value error when test the pull to refresh feature in my iPhone 5. The error happen at connectionDidFinishLoading function.
class FixtureTableTableViewController: UITableViewController,UITableViewDelegate,NSURLConnectionDelegate {
var fixtures:[Fixture] = []
var data = NSMutableData()
var jsonResults:NSArray! = nil
override func viewDidLoad() {
println("view did load")
super.viewDidLoad()
connectToServer();
self.refreshControl = UIRefreshControl()
//self.refreshControl?.attributedTitle = NSAttributedString(string: "pull to refresh")
self.refreshControl?.addTarget(self, action: Selector("refresh"), forControlEvents: UIControlEvents.ValueChanged)
//self.fixtures = Fixture().listAll()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
func refresh(){
println("refresh table")
fixtures = []
connectToServer()
self.refreshControl?.endRefreshing()
}
func connectToServer(){
println("connect to server")
let plist = NSBundle.mainBundle().pathForResource("hijaukuningapp",ofType: "plist")
let dict = NSDictionary(contentsOfFile: plist!)
var serverURL = dict["serverURL"] as String
println("server url \(serverURL)")
let urlPath:String = serverURL + "mobileFixture/list"
println(urlPath)
var url = NSURL(string: urlPath)
var request = NSURLRequest(URL: url)
var connect = NSURLConnection(request: request, delegate: self, startImmediately: true)
connect.start()
}
func connection(connection: NSURLConnection, didReceiveData _data: NSData!){
println("receivedata")
data.appendData(_data)
println("end append data")
}
func connectionDidFinishLoading(connection: NSURLConnection){
println("finished loading data\(data)")
var err: NSError
// throwing an error on the line below (can't figure out where the error message is)
jsonResults = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSArray
println(jsonResults)
fixtures = Fixture().listAll(jsonResults)
self.tableView.reloadData()
}
override func viewWillAppear(animated: Bool) {
println("viewWillAppear")
super.viewWillAppear(animated)
}
/*
override func viewWillAppear(animated: Bool) {
//startConnection();
println(jsonResults)
for result : AnyObject in jsonResults {
//println(result)
if let fixture = result as? Dictionary<String,AnyObject>{
var fixtureID = fixture["day"]
println(fixtureID)
var monthNamne = fixture["monthname"]
var tempFixture = Fixture()
tempFixture.day = fixtureID as String
tempFixture.month = monthNamne as String
var f2 = Fixture()
f2.homeTeam="KELANTAN"
f2.awayTeam = "KEDAH"
f2.venue = "STADIUM SULTAN MOHAMED, ALOR SETAR"
f2.day = "13"
f2.month = "OCT"
f2.time = "2045"
fixtures.append(f2)
self.tableView.reloadData()
}
println(fixtures.count)
}
}
*/
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// 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.
return fixtures.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("myCell", forIndexPath: indexPath) as FixtureTableViewCell
cell.lblVenue.text = fixtures[indexPath.row].venue
cell.lblHome.text = fixtures[indexPath.row].homeTeam.name
cell.lblAway.text = fixtures[indexPath.row].awayTeam.name
cell.lblDay.text = fixtures[indexPath.row].day
cell.lblMonth.text = fixtures[indexPath.row].month
cell.lblTime.text = fixtures[indexPath.row].time
var code:String = fixtures[indexPath.row].homeTeam.code + ".png"
var awayCode:String = fixtures[indexPath.row].awayTeam.code + ".png"
cell.homeLogo.image = UIImage(named: code);
cell.awayLogo.image = UIImage(named: awayCode)
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
println("indexpat " )
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
println("prepare for sergues")
var detailController:FixtureDetailViewController = segue.destinationViewController as FixtureDetailViewController
var indexPath = self.tableView.indexPathForSelectedRow()
detailController.fixture = fixtures[indexPath!.row]
}
/*
// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView!, canEditRowAtIndexPath indexPath: NSIndexPath!) -> Bool {
// Return NO if you do not want the specified item to be editable.
return true
}
*/
/*
// Override to support editing the table view.
override func tableView(tableView: UITableView!, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath!) {
if editingStyle == .Delete {
// Delete the row from the data source
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
} else if editingStyle == .Insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
override func tableView(tableView: UITableView!, moveRowAtIndexPath fromIndexPath: NSIndexPath!, toIndexPath: NSIndexPath!) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(tableView: UITableView!, canMoveRowAtIndexPath indexPath: NSIndexPath!) -> Bool {
// Return NO if you do not want the item to be re-orderable.
return true
}
*/
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
}
In this line your data object is nil.
jsonResults = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSArray
Fix it by doing:
if let d = data {
//Only executed if data isn't nil
jsonResults = NSJSONSerialization.JSONObjectWithData(d, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSArray
}
In swift, an optional value means that it could be nil. If you don't get the actual value out of the optional, your code won't compile. The pattern above will only execute the code if the value is not nil.