Save UITableView names to array on button action - xcode

I want to save the names that are filled in UITableView to an array
var mineSpillere = [String]()
How can I do this on buttonAction?
This is button action for how i add names to tableview:
#IBAction func addButtonAction(sender: AnyObject) {
mineSpillere.append(namesTextBox.text)
myTableView.reloadData()
}
and also here code:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell = self.myTableView.dequeueReusableCellWithIdentifier("cell") as! UITableViewCell
cell.textLabel!.text = self.mineSpillere[indexPath.row]
return cell;
}
That only when I press the "back" button in the application, the names from the UITableView will be saved in an array.
I am going to access these names from another view controller also, so i need them to be saved as an array.

Okay so it looks like you have all the data in the mineSpillere array already as you're using cell.textLabel!.text = self.mineSpillere[indexPath.row] so to get that array back to the first view controller. You could use the following code in the view controller that is being presented when the 'back' button is being pressed:
class FirstViewController: UIViewController,SecondViewControllerDelegate {
var mineSpillereCopyFromSecondVC = [String]()
func presentSecondViewController() {
// Im not sure the class name for you're second view
// where the tableView is located.
var secondVC: SecondViewController = SecondViewController();
secondVC.delegate = self
// Also not too sure on how you're presenting the `SecondViewController` so I'm goingg to leave that empty.
// The important part is just above us.
}
func passMineSpillere(mineSpillere: [String]) {
// This class now has the mineSpiller array of name.
self.mineSpillereCopyFromSecondVC = mineSpillere
}
}
And then in you SecondViewController where the tableView is located you could add the following code.
import UIKit
protocol SecondViewControllerDelegate {
func passMineSpillere(mineSpillere:[String])
}
class SecondViewController: UIViewController {
var delegate: SecondViewControllerDelegate?
var mineSpillere = [String]()
// This will be called when the 'back' button is pressed.
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
// Pass the mineSpillere array back to the delegate
// which is the firstViewController instance.
self.delegate?.passMineSpillere(self.mineSpillere)
}
}

Related

NSTableview - Drag and Drop split into two classes and controllers

i found this helpfully tutorial for realize drag an drop with nstabelview:
https://drive.google.com/open?id=0B8PBtMQt9GdONzV3emZGQWUtdmM
this works fine.
but i would like to split both table views into differente view controllers and classes with a split view:
one split view controller:
item 1: viewcontroller with source nstableview (SourceTableView.class)
item 2: viewcontroller with target nstableview (TargetTableView.class)
how can i do this with this project?
i know how can i create a split view controller in storyboard.
but i dont know, if i have two different classes, how the iBoutlet SourceTabelView of class SourceTableView.class assign the iBoutlet TargetTableView of class TargetTableView.class
UPDATE
var person = [Person]()
NSManagedObject.class
import Foundation
import CoreData
#objc(Person)
public class Person: NSManagedObject {
#NSManaged public var firstName: String
#NSManaged public var secondName: String
}
Example of drag and drop between two table views inside a split view. Dragging inside one table view and multiple selection will work. Hold the Option key to drag a copy.
The datasource of each table view is the view controller inside the split view. Each table view has its own view controller and each view controller controls one table view. Both view controllers are the same NSViewController subclass:
class ViewController: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
#IBOutlet weak var myTableView: NSTableView!
var dataArray: NSMutableArray = ["John Doe", "Jane Doe", "Mary Jane"]
override func viewDidLoad() {
super.viewDidLoad()
myTableView.register(forDraggedTypes: ["com.yoursite.yourproject.yourstringstype"])
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
// NSTableViewDataSource data methods
func numberOfRows(in tableView: NSTableView) -> Int {
return dataArray.count
}
func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
return dataArray[row] as AnyObject!;
}
// NSTableViewDataSource drag methods
func tableView(_ tableView: NSTableView, writeRowsWith rowIndexes: IndexSet, to pboard: NSPasteboard) -> Bool {
// the dragging destination needs the strings of the rows to add to its own data,
// we, the dragging source, need the indexes of the rows to remove the dropped rows.
pboard.declareTypes(["com.yoursite.yourproject.yourstringstype", "com.yoursite.yourproject.yourindexestype"],
owner: nil)
pboard.setData(NSKeyedArchiver.archivedData(withRootObject: (dataArray as NSArray).objects(at:rowIndexes as IndexSet)), forType: "com.yoursite.yourproject.yourstringstype")
pboard.setData(NSKeyedArchiver.archivedData(withRootObject: rowIndexes), forType: "com.yoursite.yourproject.yourindexestype")
return true
}
func tableView(_ tableView: NSTableView, draggingSession session: NSDraggingSession,
endedAt screenPoint: NSPoint, operation: NSDragOperation) {
// remove the dragged rows if the rows are dragged to the trash or were moved to somewhere else.
var removeRows = false
if operation == .delete {
// trash
removeRows = true
} else if operation == .move {
// check if the point where the rows were dropped is inside our table view.
let windowRect = tableView.convert(tableView.bounds, to: nil)
let screenRect = view.window!.convertToScreen(windowRect)
if !NSPointInRect(screenPoint, screenRect) {
removeRows = true
}
}
if removeRows {
// remove the rows, the indexes are on the pasteboard
let data = session.draggingPasteboard.data(forType: "com.yoursite.yourproject.yourindexestype")!
let rowIndexes = NSKeyedUnarchiver.unarchiveObject(with: data) as! NSIndexSet
(dataArray as NSMutableArray).removeObjects(at: rowIndexes as IndexSet)
tableView.reloadData()
}
}
// NSTableViewDataSource drop methods
func tableView(_ tableView: NSTableView, validateDrop info: NSDraggingInfo, proposedRow row: Int,
proposedDropOperation dropOperation: NSTableViewDropOperation) -> NSDragOperation {
// only accept drop above rows, not on rows.
if dropOperation == .above {
// return move if the dragging source allows move
if info.draggingSourceOperationMask().contains(.move) {
return .move
}
// return copy if the dragging source allows copy
if info.draggingSourceOperationMask().contains(.copy) {
return .copy
}
}
return []
}
func tableView(_ tableView: NSTableView, acceptDrop info: NSDraggingInfo, row: Int,
dropOperation: NSTableViewDropOperation) -> Bool {
// if the rows were moved inside the same table view we do a reorder
var dropRow = row
if info.draggingSource() as AnyObject === myTableView as AnyObject &&
info.draggingSourceOperationMask().contains(.move) {
// remove the rows from their old position
let data = info.draggingPasteboard().data(forType: "com.yoursite.yourproject.yourindexestype")!
let rowIndexes = NSKeyedUnarchiver.unarchiveObject(with: data) as! NSIndexSet
(dataArray as NSMutableArray).removeObjects(at: rowIndexes as IndexSet)
// recalculate the row of the drop
dropRow -= rowIndexes.countOfIndexes(in: NSMakeRange(0, dropRow))
}
// insert the dragged rows
let data = info.draggingPasteboard().data(forType: "com.yoursite.yourproject.yourstringstype")!
let draggedStrings = NSKeyedUnarchiver.unarchiveObject(with: data) as! [Any]
dataArray.insert(draggedStrings, at:IndexSet(integersIn:dropRow..<(dropRow + draggedStrings.count)))
tableView.reloadData()
return true
}
}
To make dragging to the trash work, subclass NSTableView and override:
override func draggingSession(_ session: NSDraggingSession, sourceOperationMaskFor
context: NSDraggingContext) -> NSDragOperation {
let test = super.draggingSession(session, sourceOperationMaskFor: context)
Swift.print("sourceOperationMaskFor \(test)")
switch context {
case .withinApplication:
return [.move, .copy]
case .outsideApplication:
return [.delete]
}
}
p.s. I'm not familiar with Swift and had some trouble with arrays and indexsets so I used NSMutableArray and NSIndexSet.

How to Pass Collection View Data to a New View Controller

I am going try be as specific as possible.
What I am trying to achieve is to have one view controller which has a collection view in it and when the user clicks on of the collection view cells, it then sends the user to another view controller which has another collection view however the items displayed in the second collection view will change depending on which collection view cell the user previously tapped. I am also using CoreData to do this. With CoreData, the task is an entity and has attributes like name etc. Will I have to change this or have a relationship between the 2 collection views?
The reason for me wanting to do this is because I am creating a productivity app for iOS and the first view controller with a collection view will be where the user can create projects, within these projects which will be displayed in a collection view, the user can then tap on one of the cells and go to the next view controller and begin to create tasks specific to that project.
How can I keep the tasks stored in a specific collection view cell and have the user create different tasks in other projects. It is sort of like Wunderlist. If anybody is confused at what I am trying to do, I can ellaborate more.
This is one of my view controllers where the data from the 'create item view controller' gets sent to via CoreData and displays it in a collection view, hope it helps:
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
#IBOutlet weak var myCollView: UICollectionView!
#IBAction func addCore(_ sender: UIButton) {
}
var tasks : [Task] = []
override func viewDidLoad() {
super.viewDidLoad()
self.myCollView.delegate = self
self.myCollView.dataSource = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
getData()
myCollView.reloadData()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return tasks.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "connectCell", for: indexPath) as! MyCollectionViewCell
let task = tasks[indexPath.row]
cell.labelTe?.text = task.name!
self.myCollView.backgroundColor = UIColor.clear
cell.layer.cornerRadius = 25
return cell
}
func getData() {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
do {
tasks = try context.fetch(Task.fetchRequest())
}
catch {
print("Ahhhhhhhh")
}
}
If I am guessing right, and upon clicking a cell on the first collection view, you want to segue to another collection view, where you will display display data according to the selected cell.
In order to achieve this, simply add collectionView(_ collectionView:, didSelectItemAt indexPath:) and prepare(for segue:, sender:) functions in your first view controller.
In the collectionView(_ collectionView:, didSelectItemAt indexPath:) function get the id of the task selected by determine which cell was selected, then pass this id to the second view controller in prepare(for segue:, sender:) function.
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath) as! MyCollectionViewCell
id = cell.labelTe?.text
}
or
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
id = tasks[indexPath.row].id
}
Then pass this value in your prepare(for segue:, sender:) function to the second viewController.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "YourIdentifier"{
let destinationViewController = segue.destination as! SecondViewController
destinationViewController.id = id
}
}
Make sure to add a var id in both your viewControllers. In the second viewController, use this id to fetch the data of the selected task that you want to display.
Hope this helps.
EDIT
Simply declare a new variable id of your particular type in both the viewControllers. In your first viewController :
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
var id = ""
and in the second viewController
class secondViewController: UIViewController {
var id = ""
Just make sure that both the variable are of same type.

Xcode 7 - Cell content not displayed into an empty label

I'm trying to display a cell content into an empty UILabel, but after I upgraded to Xcode 7, the content didn't show up. I was following the same mechanism and it worked on Xcode 6, but since I'm new to Swift I may have something wrong in the code.
TableViewController:
import UIKit
class TableViewController: UITableViewController {
struct dataModel {
var name:String
var val:Double
}
let foods = [dataModel(name: "name1", val: 3.3),
dataModel(name: "name2", val: 5.5)]
#IBOutlet var table: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// 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()
}
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
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return foods.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
// Configure the cell...
let foodCell = foods[indexPath.row]
cell.textLabel?.text = foodCell.name
return cell
}
var valueToPass:String!
var valueInt:Int!
override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
let indexPath = tableView.indexPathForSelectedRow;
let currentCell = tableView.cellForRowAtIndexPath(indexPath!) as UITableViewCell!;
valueToPass = currentCell.textLabel!.text
performSegueWithIdentifier("showCalc", sender: self)
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "showCalc") {
let viewController = segue.destinationViewController as! calcViewController
viewController.passedValue = valueToPass
}
}
}
ViewController where I want to display the tapped cell into an empty label:
import UIKit
class calcViewController: UIViewController {
#IBOutlet var text: UILabel!
#IBOutlet var empty1: UILabel!
var passedValue:String!
override func viewWillAppear(animated: Bool) {
empty1.text = passedValue
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
As a result, there is no error, but there is nothing displayed inside the empty label.
The other thing I want to achieve is to display the Int value into another label and then do some calculations, but this would be another question. Thanks in advance!
There are several issues in this code. First you are obviously missing some closing braces. But I assume this is a copy-paste error.
Why do you use didDeselectRowAtIndexPath? Don't you have a segue from the table view cell to the next controller? Then you should get the text label in prepareForSegue by using tableView.indexPathForSelectedRow.
If you like to keep it this way you should use didSelect... in stead of didDeselect....
You should take the value you want to pass to the next view controller direct from the data and not from the cell. You have the data you present in the table in the foods array.
Class names should always start with a capital letter. ALWAYS!
Having the data model within the controller is poor design. You should have the struct separated in its own file. In this case you could even hand the complete data object to the next view controller.

Swift - Detail View Controller depending on Table View Cell

i have a basic table view controller with dynamic prototypes,
there can appear 4 cells, but there also can appear 6 cells.
What i want is:
Depending on which cell is clicked to switch to another "detail"-ViewController.
my first thought is like this:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if cell1clicked {
// go to viewcontrollerA
} elseif cell2clicked {
// go to viewcontrollerB
} elseif cell3clicked {
// go to viewcontrollerC
} else {
// go to viewcontrollerD
}
}
is this even possible with tableviewcontrollers?
Greetings and thanks!
Its possible to do it by using TableViewController in storyboard and use static cells instead of dynamic.
Here is the way:
1- Define 4 cells in your static tableView.
2- Drag 4 View Controller in storyboard.
3- Connect First Cell with viewcontrollerA and so on in Storyboard.
4- Be sure that you subclass your class UITableViewController and remove tableview methods.
Update :
If you want to use dynamic cells its possible to push the ViewController programmatically :
1- Drag 4 ViewControllers and go to identity inspector and give each
one a Storyboard ID.
2- Create 4 classes for your ViewControllers and connect each
storyboard with its class.
2- Add Navigation Controller to your initial ViewController in
storyboard.
Ive made you a sample class here :
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource{
var array = ["First","Second","Third","Fourth"]
#IBOutlet weak var tableviewmy: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 4
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel?.text = array[indexPath.row]
return cell;
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.row == 0 {
var controller1 : FirstViewController = storyboard?.instantiateViewControllerWithIdentifier("ViewControllerA") as! FirstViewController
self.navigationController?.pushViewController(controller1, animated: true)
}else if indexPath.row == 1{
var controller2 : SecondViewController = storyboard?.instantiateViewControllerWithIdentifier("ViewControllerB") as! SecondViewController
self.navigationController?.pushViewController(controller2, animated: true)
}else if indexPath.row == 2 {
// controller 3
}else {
// controller 4
}
}
}
You may download a sample project :
https://yadi.sk/d/F5Qb85MLiMPqk

Passing variables between classes in Swift

I have a table view controller named ThirdViewController which displays a list of transactions. When a user presses the add button, the app segues to the FifthViewController where they can enter the transaction name, value and date. I am trying to get this data entered in FifthViewController into a class named ArrayData so that I can add it to the array which will then add the payment to the ThirdViewController table view.
This is my code for the ThirdViewController.swift:
var arrayObject = ArrayData()
class ThirdViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
// 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
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// #pragma 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 arrayObject.paymentsArray().count
}
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
var cell:CustomTransactionTableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as CustomTransactionTableViewCell
cell.paymentNameLabel.text = (arrayObject.paymentsArray().objectAtIndex(indexPath.row)) as String
cell.costLabel.text = (arrayObject.costArray().objectAtIndex(indexPath.row)) as String
cell.dateLabel.text = (arrayObject.dateArray().objectAtIndex(indexPath.row)) as String
return cell
}
}
This is the code for arrayData.swift:
class ArrayData: NSObject {
func paymentsArray() -> NSMutableArray {
var arrayDataPayments: NSMutableArray = ["Test"]
return arrayDataPayments
}
func costArray() -> NSMutableArray {
var arrayDataCost: NSMutableArray = ["£100"]
return arrayDataCost
}
func dateArray() -> NSMutableArray {
var arrayDataDate: NSMutableArray = ["12/07/14"]
return arrayDataDate
}
}
And this is the code for FifthViewController:
class FifthViewController: UIViewController {
#IBOutlet var transactionNameInput : UITextField
#IBOutlet var transactionDateInput : UITextField
#IBOutlet var transactionValueInput : UITextField
#IBOutlet var addBackButton : UIButton
#IBAction func addTransactionButton(sender : AnyObject) {
self.navigationController.popToRootViewControllerAnimated(true)
var transactionName = transactionNameInput.text
var transactionDate = transactionDateInput.text
var transactionValue = transactionValueInput.text
}
#IBAction func viewTapped(sender : AnyObject) {
//Closes keyboard when user touches screen
transactionDateInput.resignFirstResponder()
transactionNameInput.resignFirstResponder()
transactionValueInput.resignFirstResponder()
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
How can I get the variables from the FifthViewController to the ArrayData class so they can be added to the arrays? This might be very simple but I'm new to Xcode and obviously Swift.
Any help would be greatly appreciated.
The methods in your ArrayData class are awkwardly implemented as each invocation returns a new array. Perhaps this is what you really want, but it is unusual (and you've noted that you are new to Xcode and Swift and thus I suspect it isn't really what you want). A more normal implementation would be :
class ArrayData: NSObject {
var arrayDataPayments: NSMutableArray = ["Test"]
var arrayDataCost: NSMutableArray = ["£100"]
var arrayDataDate: NSMutableArray = ["12/07/14"]
func paymentsArray() -> NSMutableArray { return arrayDataPayments }
func costArray() -> NSMutableArray { return arrayDataCost }
func dateArray() -> NSMutableArray { return arrayDataDate }
}
Now, I'm not saying that this is going to solve your bigger issue of getting the data in an out of your controller; but, I suspect that the above is a better start.

Resources