iOS + Firebase - Send data from view controller to detail view controller - ios

I have a ViewController, where a list of data is being fetched from the RealtimeDatabase and being displayed in the UITableView. When a post is clicked, I want the data from the ViewController such as Title, Description, and Image to be carried forward into a DetailView i.e: PostController.Swift where I can further call more data from the RealtimeDatabase to be displayed in the PostController.Swift
I tried to use didSelectRowAt but was unable to fetch and display data in the PostController, I'm also currently trying to use prepare but getting stuck at the same place.
Here is the ViewController.Swift:
import UIKit
import Firebase
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var tableView:UITableView!
var posts = [Post]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tableView = UITableView(frame: view.bounds, style: .plain)
view.addSubview(tableView)
let cellNib = UINib(nibName: "PostTableViewCell", bundle: nil)
tableView.register(cellNib, forCellReuseIdentifier: "postCell")
var layoutGuide:UILayoutGuide!
layoutGuide = view.safeAreaLayoutGuide
tableView.leadingAnchor.constraint(equalTo: layoutGuide.leadingAnchor).isActive = true
tableView.topAnchor.constraint(equalTo: layoutGuide.topAnchor).isActive = true
tableView.trailingAnchor.constraint(equalTo: layoutGuide.trailingAnchor).isActive = true
tableView.bottomAnchor.constraint(equalTo: layoutGuide.bottomAnchor).isActive = true
tableView.delegate = self
tableView.dataSource = self
tableView.tableFooterView = UIView()
tableView.reloadData()
observePosts()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func observePosts() {
let postsRef = Database.database().reference().child("Data")
postsRef.observe(.value, with: { snapshot in
var tempPosts = [Post]()
for child in snapshot.children{
if let childSnapshot = child as? DataSnapshot,
let dict = childSnapshot.value as? [String:Any],
let title = dict["title"] as? String,
let logoImage = dict["image"] as? String,
let url = URL(string:logoImage),
let description = dict["description"] as? String{
let userProfile = UserProfile(title: title, photoURL: url)
let post = Post(id: childSnapshot.key, title: userProfile, description: description, image: userProfile)
print(post)
tempPosts.append(post)
}
}
self.posts = tempPosts
self.tableView.reloadData()
})
}
func getImage(url: String, completion: #escaping (UIImage?) -> ()) {
URLSession.shared.dataTask(with: URL(string: url)!) { data, response, error in
if error == nil {
completion(UIImage(data: data!))
} else {
completion(nil)
}
}.resume()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "postCell", for: indexPath) as! PostTableViewCell
cell.set(post: posts[indexPath.row])
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
tableView.estimatedRowHeight = 50
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "PostDetailSegue" {
if let indexPaths = self.tableView!.indexPathForSelectedRow{
}
}
}
}

You need to store a reference to the Post in your DetailViewController.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "PostDetailSegue" {
let detailViewController = segue.destinationViewController as! DetailViewController
let indexPath = tableView.indexPathForSelectedRow
let post = posts[indexPath.row]
detailViewController.setPost(post)
}
}
And in your DetailViewController:
func detailViewController.setPost(_ post: Post) {
// Store the post and fetch other data as necessary
self.post = post
}

try this one.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let postsInfo = posts[indexPath.row]
print(postsInfo)
performSegueWithIdentifier("PostDetailSegue", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "PostDetailSegue" {
if let indexPaths = posts[indexPath.row]{
//add parmaters which passed to another viewcontroller
}
}
}

Related

Send data from detail view controller to table view controller

I create an app which uses https://newsapi.org/.
There is a table view that contains news and they have their detail page (Detail View Controller).
Detail view controller has a tab bar button item which is favorites button(<3).
This button send data to favorites table view. But can't send data. Also, in favorites table view you can click the cell and go detail view controller again. So there is two way. And i want to go BACK segue.
main.storyboard:
this is NewsTableViewController:
import UIKit
import Alamofire
class NewsTableViewController: UITableViewController , UISearchBarDelegate {
#IBOutlet weak var searchBar: UISearchBar!
var arr : [Article]? = []
var filteredData: [Article] = []
override func viewDidLoad() {
super.viewDidLoad()
searchBar.delegate = self
//
// let parameters = ["q":"%20", "page": "1", "apiKey":"06c2318ea4c64504b48b3d126168203c"]
let parameters = ["q":"saliha", "page": "1", "apiKey":"06c2318ea4c64504b48b3d126168203c"]
let url = "https://newsapi.org/v2/everything"
AF.request(url, method: .get, parameters: parameters) .responseJSON { (res) in
if(res.response?.statusCode == 200) {
print("res data: ",res.data as Any)
let news = try? JSONDecoder().decode(News.self, from: res.data!)
self.arr = news?.articles
self.tableView.reloadData()
print("kaç sonuç var?",news?.totalResults as Any)
}
}
}
// 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 {
if(filteredData.count > 0) {
return filteredData.count
} else {
return arr!.count
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! NewsTableViewCell
let item: Article
if filteredData.count > 0 {
item = filteredData[indexPath.row]
} else {
item = arr![indexPath.row]
}
DispatchQueue.main.async {
let url = URL(string: item.urlToImage!)
let data = try! Data(contentsOf: url!)
cell.newsImage.image = UIImage(data: data)
}
cell.newsTitle.text = item.title
cell.newsAbout.text = item.description
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let sender: Article
if filteredData.count > 0 {
sender = filteredData[indexPath.row]
}
else {
sender = arr![indexPath.row]
}
performSegue(withIdentifier: "detail", sender: sender)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if ( segue.identifier == "detail" ) {
let vc = segue.destination as! DetailViewController
vc.item = (sender as! Article)
}
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
filteredData = []
if searchText == ""{
filteredData = arr!
}
else{
for item in arr!{
if item.title!.lowercased().contains(searchText.lowercased()){
filteredData.append(item)
}
}
}
self.tableView.reloadData()
}
}
this is DetailViewController:
import UIKit
import Alamofire
class DetailViewController: UIViewController {
var item: Article!
var arr: [Article] = []
var favArr: [Article] = []
#IBOutlet weak var dTitle: UILabel!
#IBOutlet weak var dImage: UIImageView!
#IBOutlet weak var dDate: UILabel!
#IBOutlet weak var dAbout: UITextView!
#IBAction func btnWebview(_ sender: Any) {
performSegue(withIdentifier: "goWeb", sender: item)
}
#IBAction func btnFav(_ sender: UIBarButtonItem) {
print("favoriler ekleme butonuna basıldı")
}
#IBAction func btnShare(_ sender: UIBarButtonItem) {
let items = [URL(string: item.url!)]
let ac = UIActivityViewController(activityItems: items as [Any], applicationActivities: nil)
present(ac, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: item.urlToImage!)
let data = try! Data(contentsOf: url!)
dImage.image = UIImage(data: data)
dTitle.text = item.title
dAbout.text = item.description
dDate.text = item.publishedAt
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if ( segue.identifier == "goWeb" ) {
let vc = segue.destination as! WebViewViewController
vc.item = (sender as! Article)
}
}
}
this is FavoriteTableViewController:
import UIKit
import Alamofire
class FavoriteTableViewController: UITableViewController {
var item: Article!
var arr : [Article]? = []
var favArr: [Article] = []
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.reloadData()
}
// 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 favArr.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "favcell", for: indexPath) as! FavoriteTableViewCell
let url = URL(string: item.urlToImage!)
let data = try! Data(contentsOf: url!)
cell.fImage.image = UIImage(data: data)
cell.fTitle.text = item.title
cell.fDetail.text = item.description
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "detail", sender: item)
}
/*
// 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: UITableViewCell.EditingStyle, 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.destination.
// Pass the selected object to the new view controller.
}
*/
}

Pass API data when tap on CollectionVC to TableVC

I'm trying to pass data from a news Api to a tableView, but I'm having an issue, the data is returning nil when it get's pass to the SectorNewsVC, And by the time it gets to the infoVC it's still nil, however when I print the data before it gets pass it there. Can someone explain what I am doing wrong and, how I can go about fixing it? Thank You!!
This is where I'm creating the URLSession and fetching the data, and attempting to pass the data over to the Viewcontroller which is calling the fetchSectorNews() to retrive the data from an API.
struct FetchCategoryResponse {
let sectorUrl = "https://stocknewsapi.com/api/v1/category?section=alltickers&items=50&type=article&token=\(Key.api_key)"
func fetchSectorNews(sector: String) {
let urlString = "\(sectorUrl)&sector=\(sector)"
performRequest(urlString: urlString)
print(urlString)
}
func performRequest(urlString: String) {
// create url
if let url = URL(string: urlString) {
// create url session
let session = URLSession(configuration: .default)
// give session a task
let task = session.dataTask(with: url) { (data, response, error) in
if error != nil {
print(error!)
return
}
if let safeData = data {
if let news = self.parseJson(sectorData: safeData) {
DispatchQueue.main.async {
let vc = SectorNewsVC()
vc.dataToPass = news
}
}
}
}
task.resume()
}
}
// parse the jason data
func parseJson(sectorData: Data) -> SectorModel? {
let decoder = JSONDecoder()
do {
let decodedData = try decoder.decode(CatergoryData.self, from: sectorData)
let newsUrl = decodedData.data[1].title
let imageUrl = decodedData.data[1].news_url
let title = decodedData.data[1].title
let source = decodedData.data[1].source_name
let sectorPayload = SectorModel(url: newsUrl, image: imageUrl, title: title, source: source)
// this sectorpayload gets saved to the news var in the performrequest() bc its being return
return sectorPayload
}
catch {
print(error)
return nil
}
}
} // END Struct
so in this ViewController I'm setting up the collectionViewController and calling the fetchSectorNews() and passing in the title of the label as the argunemt for the function, while trying to pass the data over to the detialViewController
var titleArr = ["Technology", "Materials", "HealthCare"]
var dataToPass: SectorModel?
var fetchNews = FetchCategoryResponse()
extension SectorNewsVC: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return titleArr.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) as! SectorCollectionCell
cell.listLabel.text = titleArr[indexPath.row]
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let curentIndex = indexPath.item
if curentIndex == 0 {
fetchNews.fetchSectorNews(sector: "technology")
}
else if curentIndex == 1 {
fetchNews.fetchSectorNews(sector: "materials")
}
else if curentIndex == 2 {
fetchNews.fetchSectorNews(sector: "healthcare")
}
performSegue(withIdentifier: "segue", sender: nil)
} // end cv()
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segue" {
if let indexPath = self.collectionView.indexPathsForSelectedItems {
let detailVC = segue.destination as! infoVC
detailVC.newData = dataToPass
print(indexPath)
}
}
}
}
Here is where I want to display the data
class infoVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var newData: SectorModel?
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
tableView.separatorStyle = .none
tableView.showsVerticalScrollIndicator = false
tableView.backgroundColor = #colorLiteral(red: 0.1926331222, green: 0.2233074605, blue: 0.3540094197, alpha: 1)
tableView.register(UINib(nibName: "DifferentSectorCell", bundle: nil), forCellReuseIdentifier: "cellId")
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
cell.backgroundColor = UIColor.clear
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("tap")
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! DifferentSectorCell
cell.titleLabel.text = "hey"
cell.sourceLabel.text = "hello"
return cell
}
}
I would suggest a different approach. Sending the section to the child controller, and do the request on the child. Here is what has worked for me before
on the parent controller:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let curentIndex = indexPath.item
var sector = ""
if curentIndex == 0 {
sector = "technology"
}
else if curentIndex == 1 {
sector = "materials"
}
else if curentIndex == 2 {
sector = "healthcare"
}
performSegue(withIdentifier: "segue", sender: sector)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segue" {
let detailVC = segue.destination as! infoVC
detailVC.sector = sender as! String
}
}
}
on the child controller:
var sector = ""
override func viewWillAppear() {
super.viewWillAppear()
fetchNews.fetchSectorNews(sector: self.sector)
}

How do i navigate to another view from search results displayed in table view?

The following code is my viewController code. The words from the json file are displayed in a tableView on click of a word it is taken to another page where elements associated with that word are displayed. However i am not able to navigate to that page when the search results are displayed in table view.
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchResultsUpdating{
#IBOutlet weak var mainTableView: UITableView!
var words = [wordStats]()
var filteredArray = [wordStats]()
var searchController = UISearchController()
var resultsController = UITableViewController()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
getJson {
self.mainTableView.reloadData()
}
mainTableView.delegate = self
mainTableView.dataSource = self
searchController = UISearchController(searchResultsController: resultsController)
mainTableView.tableHeaderView = searchController.searchBar
searchController.searchResultsUpdater = self
resultsController.tableView.delegate = self
resultsController.tableView.dataSource = self
}
func updateSearchResults(for searchController: UISearchController) {
filteredArray = words.filter({ (words: wordStats) -> Bool in
if words.word.contains(searchController.searchBar.text!){
return true
}else{
return false
}
})
resultsController.tableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == resultsController.tableView{
return filteredArray.count
}else{
return words.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier: nil)
if tableView == resultsController.tableView{
cell.textLabel?.text = filteredArray[indexPath.row].word.capitalized
}else{
cell.textLabel?.text = words[indexPath.row].word.capitalized
}
//cell.textLabel?.text = words[indexPath.row].word.capitalized
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "wordDetails", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? HeroViewController{
destination.word = words[(mainTableView.indexPathForSelectedRow?.row)!]
}
}
func getJson(completed: #escaping () -> ()){
let path = Bundle.main.path(forResource: "week_14", ofType: "json")
let url = URL(fileURLWithPath: path!)
let data = try! Data(contentsOf: url)
do {
self.words = try JSONDecoder().decode([wordStats].self, from: data)
DispatchQueue.main.async{
completed()
}
}catch{
print("JSON error")
}
}
}
Initially after getting the data from the JSON file the data is displayed in mainTableView but after searching when i click on the item app crashes. Can someone help me out please?
struct wordStats:Decodable{
let word: String
let synonym: String
let meaning: String
let example: String
let video: String
}
this is the wordStats
Post the crash log. My guess based on what little we have here is that you are crashing in prepareForSegue on this:
destination.word = words[(mainTableView.indexPathForSelectedRow?.row)!]
It's probably an index error when using the filtered results. This might address it:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? HeroViewController{
if tableView == resultsController.tableView {
destination.word = filteredArray[(mainTableView.indexPathForSelectedRow?.row)!]
} else {
destination.word = words[(mainTableView.indexPathForSelectedRow?.row)!]
}
}
}
This is what worked in the end
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? HeroViewController {
if let indexPath = mainTableView.indexPathForSelectedRow{
if isFiltering(){
destination.word = filteredArray[indexPath.row]
}else{
destination.word = words[indexPath.row]
}
}
}
}

How to connect to tableview containers?

I am a beginner to Xcode and Swift and I am currently creating an application where the user adds a person on the application and after that it right the amount of money they owe that person or that person owes him/her.
Note: I have used core data to store all the value
I have ViewController called PeopleTableViewController where the user adds the name of the person they owe. Then I have PersonDetailTableViewController which shows the list of details the user owes that particular person the selected in PeopleTableViewController. The problem I am facing is that if I add three people in PeopleTableViewController and when I select any one of the people then I am directed to same tableview in PersonDetailTableViewController but I want different tableviews for different person the user selects in PeopleTableViewController.
PersonDetailTableViewController:
import UIKit
class PersonDetailTableViewController: UITableViewController {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var totalLabel: UILabel?
var person: People?
var owe: Owe?
#IBOutlet var personTable: UITableView!
var dataInfo: [Owe] = []
var selectedObject: [Owe] = []
var balanceAmount = "Balance: "
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (dataInfo.count)
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = personTable
.dequeueReusableCell(withIdentifier: "detailsCell", for: indexPath)
cell.textLabel?.text = dataInfo[indexPath.row].name
cell.detailTextLabel?.text = "₹ \(dataInfo[indexPath.row].amount)"
// if dataInfo[indexPath.row].amount < 0 {
// cell.detailTextLabel?.textColor = UIColor.red
// } else {
// cell.detailTextLabel?.textColor = UIColor.green
// }
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedObject = [dataInfo[indexPath.row]]
performSegue(withIdentifier: "addOweDetails", sender: nil)
tableView.deselectRow(at: indexPath, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
getData()
personTable.dataSource = self
addTotalToNav()
print(dataInfo as Any)
}
// MARK: - Table view data source
func addTotalToNav() -> Void {
if let navigationBar = self.navigationController?.navigationBar {
let totalFrame = CGRect(x: 10, y: 0, width: navigationBar.frame.width/2, height: navigationBar.frame.height)
totalLabel = UILabel(frame: totalFrame)
totalLabel?.text = balanceAmount
totalLabel?.tag = 1
totalLabel?.font = UIFont.boldSystemFont(ofSize: 14)
totalLabel?.textColor = UIColor.red
// navigationBar.large = totalLabel?.text
self.title = totalLabel?.text
}
}
func getData() -> Void {
do{
dataInfo = try context.fetch(Owe.fetchRequest())
var total:Double = 0.00
for i in 0 ..< dataInfo.count {
total += dataInfo[i].amount as! Double
}
balanceAmount = "Balance: ₹" + (NSString(format: "%.2f", total as CVarArg) as String)
}
catch{
print("Fetching Failed")
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vc = segue.destination as! NewOweTableViewController
vc.dataInfo = selectedObject
selectedObject.removeAll()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
getData()
personTable.reloadData()
if (self.navigationController?.navigationBar.viewWithTag(1)?.isHidden == true){
self.navigationController?.navigationBar.viewWithTag(1)?.removeFromSuperview()
addTotalToNav()
}
}
}
PeopleTableViewController:
import UIKit
import CoreData
class PeopleTableViewController: UITableViewController {
#IBOutlet weak var peopleTableView: UITableView!
var people: [People] = []
override func viewDidLoad() {
super.viewDidLoad()
peopleTableView.separatorStyle = .none
// 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
}
//ViewWillAppear allows us to fetch all the data in the backend and help us display to the user
override func viewWillAppear(_ animated: Bool) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext = appDelegate.persistentContainer.viewContext
let fetchRequest: NSFetchRequest<People> = People.fetchRequest()
do {
people = try managedContext.fetch(fetchRequest)
peopleTableView.reloadData()
} catch {
print("Could not fetch")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func addButtonPressed(_ sender: UIBarButtonItem) {
}
//Following function is called right before the user segues from one viewcontroller to another viewcontroller
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let destination = segue.destination as? PersonDetailTableViewController,
let selectedRow = self.peopleTableView.indexPathForSelectedRow?.row else {
return
}
destination.person = people[selectedRow]
// destination.owe = people[selectedRow]
}
func deletePerson(at indexPath: IndexPath) {
let person = people[indexPath.row]
guard let managedContext = person.managedObjectContext else {
return
}
managedContext.delete(person)
do {
try managedContext.save()
people.remove(at: indexPath.row)
peopleTableView.deleteRows(at: [indexPath], with: .automatic)
} catch {
print("Could not delete")
peopleTableView.reloadRows(at: [indexPath], with: .automatic)
}
}
}
extension PeopleTableViewController{
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return people.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = peopleTableView.dequeueReusableCell(withIdentifier: "peopleCell", for: indexPath)
let person = people[indexPath.row]
cell.textLabel?.text = person.title
return cell
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
deletePerson(at: indexPath)
}
}
}
The following images shows what I exactly require:
PeopleTableViewController
PeopleTableViewController
On clicking Mike I get following:
PersonDetailTableViewController
On clicking John I get following:
PersonDetailTableViewController
I want that the records for Mike and John should be different that is on PersonDetailTableViewController.
You can try (Both in PeopleTableViewController) , create a segue named shoePersonDetails from PeopleTableViewController to PersonDetailTableViewController
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let person = people[indexPath.row]
performSegue(withIdentifier: "shoePersonDetails", sender: person)
tableView.deselectRow(at: indexPath, animated: true)
}
//
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vc = segue.destination as! PersonDetailTableViewController
vc.dataInfo = sender as! People
}

How to pass data in tableview using swift 3?

I want to get, store & pass an URL in tableview to another table view in swift 3?
I am trying a lot but i can't do it? Please help me.
class EpisodesTableViewController: UITableViewController
{
var episodes = Episode
var audioPlayer : AVAudioPlayer!
var selectedVideoIndex: Int!
override func viewDidLoad()
{
super.viewDidLoad()
episodes = Episode.downloadAllEpisodes()
self.tableView.reloadData()
tableView.estimatedRowHeight = tableView.rowHeight
tableView.rowHeight = UITableViewAutomaticDimension
tableView.separatorStyle = .none
}
override var preferredStatusBarStyle : UIStatusBarStyle {
return .lightContent
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int
{
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return episodes.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "Episode Cell", for: indexPath) as! EpisodeTableViewCell
let episode = episodes[indexPath.row]
cell.episode = episode
return cell
}
// MARK: - UITableViewDelegate
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath:
IndexPath)
{
tableView.deselectRow(at: indexPath, animated: true)
performSegue(withIdentifier: "secondView", sender: indexPath.row)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
var next = segue.PViewController as! PlayTableViewController
next.index = sender as? Int
}
here is the another code
class PlayTableViewController: UITableViewController
{
var play = [PlayView]()
var audioPlayer : AVAudioPlayer!
var indexOfCell:Int?
override func viewDidLoad() {
super.viewDidLoad()
super.viewDidLoad()
play = PlayView.downloadAllEpisodes()
self.tableView.reloadData()
tableView.estimatedRowHeight = tableView.rowHeight
tableView.rowHeight = UITableViewAutomaticDimension
tableView.separatorStyle = .none
}
override var preferredStatusBarStyle : UIStatusBarStyle {
return .lightContent
}
override func numberOfSections(in tableView: UITableView) -> Int
{
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return play.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "Player Cell", for: indexPath) as! PlayerTableViewCell
let playV = play[indexPath.row]
cell.PV = playV
return cell
}
// MARK: - UITableViewDelegate
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath:
IndexPath)
{
tableView.deselectRow(at: indexPath, animated: true)
let episode = play[indexPath.row]
let player = AVPlayer(url: episode.url!)
let playerViewController = AVPlayerViewController()
playerViewController.player = player
self.present(playerViewController, animated: true) {
playerViewController.player!.play()
}
}
}
class PlayView {
var name: String?
var thumbnailURL: URL?
var url: URL?
init(name: String, thumbnailURL: URL, url: URL)
{
self.name = name
self.thumbnailURL = thumbnailURL
self.url = url
}
init(pvDictionary: [String : Any]) {
self.name = pvDictionary["name"] as? String
// url, createdAt, author, thumbnailURL
url = URL(string: pvDictionary["alt_url"] as! String)
thumbnailURL = URL(string: pvDictionary["alt_image"] as! String)
}
static func downloadAllEpisodes() -> [PlayView]
{
var playView = [PlayView]()
let url2 = URL(string: "http://nix2.iotabdapps.com/apk/items.json")
let jsonData = try? Data(contentsOf: url2!)
if let jsonDictionary = NetworkService.parseJSONFromData(jsonData) {
let pvDictionaries = jsonDictionary["items"] as! [[String : Any]]
for pvDictionary in pvDictionaries {
let newPlayView = PlayView(pvDictionary: pvDictionary)
playView.append(newPlayView)
}
}
return playView
}
}
I want to get the URL from tableview when user clicked.
I want to get an URL when click the Tableview then save it and pass it to the another tableview.
I can do this in JAVA but i am failed to convert in SWIFT 3
here is my java Example
itemView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
resultp = data.get(position);
Intent intent = new Intent(context, FragmentDemoActivity.class);
intent.putExtra("videoId", resultp.get(Main.VIDEO_ID));
context.startActivity(intent);
// Get the position
}
});
return itemView;
Can anyone help me please?
You need to implement prepareForSegue method
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath:
IndexPath)
{
tableView.deselectRow(at: indexPath, animated: true)
performSegue(withIdentifier: "secondView", sender: indexPath.row)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
var next = segue.destinationViewController as! PlayTableViewController
next.indexOfCell = sender as? Int
}
//
class PlayTableViewController:UITableViewController
{
var indexOfCell:Int?
}

Resources