Displaying the Image From API using DidSelectRow - ios

I am trying to send the data in including image from one view controller to another . The data is fetching from API . The data is successfully loaded into first view controller including image but when I try to reuse same code with didSelectRow function I am getting following errors . Cannot assign value of type 'Data?' to type 'UIImage' . The error on this line dc.imagemovie = presenter.getImageData(by: row). Here is the code to fetch the data from API.
class MoviePresenter: MoviePresenterProtocol {
private let view: MovieViewProtocol
private let networkManager: NetworkManager
private var movies = [Movie]()
private var cache = [Int: Data]()
var rows: Int {
return movies.count
}
init(view: MovieViewProtocol, networkManager: NetworkManager = NetworkManager()) {
self.view = view
self.networkManager = networkManager
}
func getMovies() {
let url = "https://api.themoviedb.org/3/movie/popular?language=en-US&page=3&api_key=6622998c4ceac172a976a1136b204df4"
networkManager.getMovies(from: url) { [weak self] result in
switch result {
case .success(let response):
self?.movies = response.results
self?.downloadImages()
DispatchQueue.main.async {
self?.view.resfreshTableView()
}
case .failure(let error):
DispatchQueue.main.async {
self?.view.displayError(error.localizedDescription)
}
}
}
}
func getTitle(by row: Int) -> String? {
return movies[row].originalTitle
}
func getOverview(by row: Int) -> String? {
return movies[row].overview
}
func getImageData(by row: Int) -> Data? {
return cache[row]
}
private func downloadImages() {
let baseImageURL = "https://image.tmdb.org/t/p/w500"
let posterArray = movies.map { "\(baseImageURL)\($0.posterPath)" }
let group = DispatchGroup()
group.enter()
for (index, url) in posterArray.enumerated() {
networkManager.getImageData(from: url) { [weak self] data in
if let data = data {
self?.cache[index] = data
}
}
}
group.leave()
group.notify(queue: .main) { [weak self] in
self?.view.resfreshTableView()
}
}
}
Here is the code in view controller to display the data into table view cell .
class MovieViewController: UIViewController {
#IBOutlet weak var userName: UILabel!
#IBOutlet weak var tableView: UITableView!
private var presenter: MoviePresenter!
var finalname = ""
override func viewDidLoad() {
super.viewDidLoad()
userName.text = "Hello: " + finalname
setUpUI()
// configure presenter
presenter = MoviePresenter(view: self)
presenter.getMovies()
}
private func setUpUI() {
tableView.dataSource = self
tableView.delegate = self
}
#IBAction func selectSegment(_ sender: UISegmentedControl) {
if sender.selectedSegmentIndex == 0{
setUpUI()
presenter = MoviePresenter(view: self)
presenter.getMovies()
}
}
}
extension MovieViewController: MovieViewProtocol {
func resfreshTableView() {
tableView.reloadData()
}
func displayError(_ message: String) {
let alert = UIAlertController(title: "Error", message: message, preferredStyle: .alert)
let doneButton = UIAlertAction(title: "Done", style: .default, handler: nil)
alert.addAction(doneButton)
present(alert, animated: true, completion: nil)
}
}
extension MovieViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
presenter.rows
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: MovieViewCell.identifier, for: indexPath) as! MovieViewCell
let row = indexPath.row
let title = presenter.getTitle(by: row)
let overview = presenter.getOverview(by: row)
let data = presenter.getImageData(by: row)
cell.configureCell(title: title, overview: overview, data: data)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let dc = storyboard?.instantiateViewController(withIdentifier: "MovieDeatilsViewController") as! MovieDeatilsViewController
let row = indexPath.row
dc.titlemovie = presenter.getTitle(by: row) ?? ""
dc.overview = presenter.getOverview(by: row) ?? ""
**dc.imagemovie = presenter.getImageData(by: row)**
self.navigationController?.pushViewController(dc, animated: true)
}
}
extension MovieViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
}
Here is the code for display the data .
class MovieDeatilsViewController: UIViewController {
#IBOutlet weak var movieImage: UIImageView!
#IBOutlet weak var movieTitle: UILabel!
#IBOutlet weak var movieOverview: UILabel!
var titlemovie = ""
var overview = ""
var imagemovie = UIImage()
override func viewDidLoad() {
super.viewDidLoad()
movieTitle.text = titlemovie
movieOverview.text = overview
movieImage.image = imagemovie
}
}

You need to return UIImage :
class MoviePresenter: MoviePresenterProtocol {
...
// Convert data to UIImage
func getImageData(by row: Int) -> UIImage? {
return UIImage(data: cache[row])
}
You need yo use UIImage and UIImage view to configure cell :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: MovieViewCell.identifier, for: indexPath) as! MovieViewCell
let row = indexPath.row
let title = presenter.getTitle(by: row)
let overview = presenter.getOverview(by: row)
let image = presenter.getImageData(by: row)
// cell is now configured with an image
cell.configureCell(title: title, overview: overview, image: image)
return cell
}
You need to modify cell.configureCell to handle UIImage? instead of data.
When selecting a cell you must use UIImage to init VC :
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let dc = storyboard?.instantiateViewController(withIdentifier: "MovieDeatilsViewController") as! MovieDeatilsViewController
let row = indexPath.row
dc.titlemovie = presenter.getTitle(by: row) ?? ""
dc.overview = presenter.getOverview(by: row) ?? ""
dc.imagemovie = presenter.getImageData(by: row)// now an image
self.navigationController?.pushViewController(dc, animated: true)
}
Use UIImage to initialise image movie in detail vc :
class MovieDeatilsViewController: UIViewController {
#IBOutlet weak var movieImageView: UIImageView! // Image view here
#IBOutlet weak var movieTitle: UILabel!
#IBOutlet weak var movieOverview: UILabel!
var titlemovie = ""
var overview = ""
var imagemovie : UIImage?
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated: animated)
movieTitle.text = titlemovie
movieOverview.text = overview
// here you could also display a default image
// if image is not set
if let image = imagemovie {
movieImageView.image = image
}
}
}

Related

Passing data from Table view cell using button delegate

I want to pass the data from one view controller to another view controller when the user clicked the button . I am using button with delegate to pass the table view cell values into different view controller view . In second view controller I have two labels and one image to display the fields but the problem is when I clicked the button it is empty.
Here is the cell code .
import UIKit
protocol CellSubclassDelegate: AnyObject {
func buttonTapped(cell: MovieViewCell)
}
class MovieViewCell: UITableViewCell {
weak var delegate:CellSubclassDelegate?
static let identifier = "MovieViewCell"
#IBOutlet weak var movieImage: UIImageView!
#IBOutlet weak var movieTitle: UILabel!
#IBOutlet weak var movieOverview: UILabel!
#IBOutlet weak var someButton: UIButton!
#IBAction func someButtonTapped(_ sender: UIButton) {
self.delegate?.buttonTapped(cell: self)
}
override func prepareForReuse() {
super.prepareForReuse()
self.delegate = nil
}
func configureCell(title: String?, overview: String?, data: Data?) {
movieTitle.text = title
movieOverview.text = overview
if let imageData = data{
movieImage.image = UIImage(data: imageData)
// movieImage.image = nil
}
}
}
Here is the first view controller code .
import UIKit
class MovieViewController: UIViewController, UISearchBarDelegate {
#IBOutlet weak var userName: UILabel!
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var searchBar: UISearchBar!
private var presenter: MoviePresenter!
var finalname = ""
var movieTitle = ""
var movieOverview = ""
var movieImage : UIImage?
override func viewDidLoad() {
super.viewDidLoad()
userName.text = "Hello: " + finalname
setUpUI()
presenter = MoviePresenter(view: self)
searchBarText()
}
private func setUpUI() {
tableView.dataSource = self
tableView.delegate = self
}
private func searchBarText() {
searchBar.delegate = self
}
#IBAction func selectSegment(_ sender: UISegmentedControl) {
if sender.selectedSegmentIndex == 0{
setUpUI()
presenter = MoviePresenter(view: self)
presenter.getMovies()
}
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchText == ""{
presenter.getMovies()
}
else {
presenter.movies = presenter.movies.filter({ movies in
let originalTitle = movies.originalTitle.lowercased().range(of: searchText.lowercased())
let overview = movies.overview.lowercased().range(of: searchText.lowercased())
let posterPath = movies.posterPath.lowercased().range(of: searchText.lowercased())
return (originalTitle != nil) == true || (overview != nil) == true || (posterPath != nil) == true}
)
}
tableView.reloadData()
}
}
extension MovieViewController: MovieViewProtocol {
func resfreshTableView() {
tableView.reloadData()
}
func displayError(_ message: String) {
let alert = UIAlertController(title: "Error", message: message, preferredStyle: .alert)
let doneButton = UIAlertAction(title: "Done", style: .default, handler: nil)
alert.addAction(doneButton)
present(alert, animated: true, completion: nil)
}
}
extension MovieViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
presenter.rows
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: MovieViewCell.identifier, for: indexPath) as! MovieViewCell
let row = indexPath.row
let title = presenter.getTitle(by: row)
let overview = presenter.getOverview(by: row)
let data = presenter.getImageData(by: row)
cell.delegate = self
cell.configureCell(title: title, overview: overview, data: data)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let dc = storyboard?.instantiateViewController(withIdentifier: "MovieDeatilsViewController") as! MovieDeatilsViewController
let row = indexPath.row
dc.titlemovie = presenter.getTitle(by: row) ?? ""
dc.overview = presenter.getOverview(by: row) ?? ""
dc.imagemovie = UIImage(data: presenter.getImageData(by: row)!)
self.navigationController?.pushViewController(dc, animated: true)
}
}
extension MovieViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
}
extension MovieViewController : CellSubclassDelegate{
func buttonTapped(cell: MovieViewCell) {
guard (self.tableView.indexPath(for: cell) != nil) else {return}
let customViewController = storyboard?.instantiateViewController(withIdentifier: "MovieDeatilsViewController") as? MovieDeatilsViewController
customViewController?.titlemovie = movieTitle
customViewController?.imagemovie = movieImage
customViewController?.overview = movieOverview
self.navigationController?.pushViewController(customViewController!, animated: true)
}
}
Here is the details view controller code .
class MovieDeatilsViewController: UIViewController {
#IBOutlet weak var movieImage: UIImageView!
#IBOutlet weak var movieTitle: UILabel!
#IBOutlet weak var movieOverview: UILabel!
var titlemovie = ""
var overview = ""
var imagemovie :UIImage?
override func viewDidLoad() {
super.viewDidLoad()
movieTitle.text = titlemovie
movieOverview.text = overview
movieImage.image = imagemovie
}
}
Here is the result when I clicked the button .
The problem is you don't update you're global properties when selecting each of you're row,
If you pass data over cell delegate and pass you're cell through delegate, you can pass data from cell like:
customViewController?.titlemovie = cell.movieTitle.text ?? ""
customViewController?.imagemovie = cell.movieImage.image
customViewController?.overview = cell.movieOverview.text ?? ""
of course it would be better to pass you're data model to you're cell. and then share that through you're delegate not share you're cell, like:
protocol CellSubclassDelegate: AnyObject {
func buttonTapped(cell: MovieModel)
}

Swift Image conversion failed from one view controller to another controller

I am trying to send the data in including image from one view controller to another . The data is fetching from API . The data is successfully loaded into first view controller including image but when I try to reuse same code with didSelectRow function I am getting following errors . Cannot assign value of type 'Data?' to type 'UIImage' . The error on this line dc.imagemovie = presenter.getImageData(by: row). Here is the code to fetch the data from API.
class MoviePresenter: MoviePresenterProtocol {
private let view: MovieViewProtocol
private let networkManager: NetworkManager
private var movies = [Movie]()
private var cache = [Int: Data]()
var rows: Int {
return movies.count
}
init(view: MovieViewProtocol, networkManager: NetworkManager = NetworkManager()) {
self.view = view
self.networkManager = networkManager
}
func getMovies() {
let url = "https://api.themoviedb.org/3/movie/popular?language=en-US&page=3&api_key=6622998c4ceac172a976a1136b204df4"
networkManager.getMovies(from: url) { [weak self] result in
switch result {
case .success(let response):
self?.movies = response.results
self?.downloadImages()
DispatchQueue.main.async {
self?.view.resfreshTableView()
}
case .failure(let error):
DispatchQueue.main.async {
self?.view.displayError(error.localizedDescription)
}
}
}
}
func getTitle(by row: Int) -> String? {
return movies[row].originalTitle
}
func getOverview(by row: Int) -> String? {
return movies[row].overview
}
func getImageData(by row: Int) -> Data? {
return cache[row]
}
private func downloadImages() {
let baseImageURL = "https://image.tmdb.org/t/p/w500"
let posterArray = movies.map { "\(baseImageURL)\($0.posterPath)" }
let group = DispatchGroup()
group.enter()
for (index, url) in posterArray.enumerated() {
networkManager.getImageData(from: url) { [weak self] data in
if let data = data {
self?.cache[index] = data
}
}
}
group.leave()
group.notify(queue: .main) { [weak self] in
self?.view.resfreshTableView()
}
}
}
Here is the code in view controller to display the data into table view cell .
class MovieViewController: UIViewController {
#IBOutlet weak var userName: UILabel!
#IBOutlet weak var tableView: UITableView!
private var presenter: MoviePresenter!
var finalname = ""
override func viewDidLoad() {
super.viewDidLoad()
userName.text = "Hello: " + finalname
setUpUI()
// configure presenter
presenter = MoviePresenter(view: self)
presenter.getMovies()
}
private func setUpUI() {
tableView.dataSource = self
tableView.delegate = self
}
#IBAction func selectSegment(_ sender: UISegmentedControl) {
if sender.selectedSegmentIndex == 0{
setUpUI()
presenter = MoviePresenter(view: self)
presenter.getMovies()
}
}
}
extension MovieViewController: MovieViewProtocol {
func resfreshTableView() {
tableView.reloadData()
}
func displayError(_ message: String) {
let alert = UIAlertController(title: "Error", message: message, preferredStyle: .alert)
let doneButton = UIAlertAction(title: "Done", style: .default, handler: nil)
alert.addAction(doneButton)
present(alert, animated: true, completion: nil)
}
}
extension MovieViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
presenter.rows
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: MovieViewCell.identifier, for: indexPath) as! MovieViewCell
let row = indexPath.row
let title = presenter.getTitle(by: row)
let overview = presenter.getOverview(by: row)
let data = presenter.getImageData(by: row)
cell.configureCell(title: title, overview: overview, data: data)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let dc = storyboard?.instantiateViewController(withIdentifier: "MovieDeatilsViewController") as! MovieDeatilsViewController
let row = indexPath.row
dc.titlemovie = presenter.getTitle(by: row) ?? ""
dc.overview = presenter.getOverview(by: row) ?? ""
**dc.imagemovie = presenter.getImageData(by: row) // Error on this line**
self.navigationController?.pushViewController(dc, animated: true)
}
}
/*
var titlemoview = ""
var overview = ""
var imagemovie = UIImage()
*/
extension MovieViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
}
Here is the code for display the data .
class MovieDeatilsViewController: UIViewController {
#IBOutlet weak var movieImage: UIImageView!
#IBOutlet weak var movieTitle: UILabel!
#IBOutlet weak var movieOverview: UILabel!
var titlemovie = ""
var overview = ""
var imagemovie = UIImage()
override func viewDidLoad() {
super.viewDidLoad()
movieTitle.text = titlemovie
movieOverview.text = overview
movieImage.image = imagemovie
}
}
Get UIImage from data in configureCell(:, : , :) function by UIImage(data:yourdata) and assign to your imageview
let image = UIImage(data:yourdata)
imageview.image = image

Why my table view disappears after scrolling to the bottom?

I don't know why my table view disappears after I reach the bottom of my table view.
here is the gif file of my problem: http://g.recordit.co/4hizPCyctM.gif
here is my code in my view controller
class CheckoutVC: UIViewController {
#IBOutlet weak var orderButton: DesignableButton!
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var floatingView: UIView!
#IBOutlet weak var totalPriceLabel: UILabel!
private let realm = RealmService.shared.realm
private var products = [Product]()
private var userOrder : Order?
private var productSelected : Product?
private var cartIsEmpty = false
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
RealmService.shared.observerRealmErrors() { (error) in
self.showAlert(alertTitle: "Sorry", alertMessage: error?.localizedDescription ?? "", actionTitle: "OK")
}
userOrder = Order.getOrderFromRealmDatabase()
guard let userOrder = userOrder else {return}
products = Array(userOrder.products)
tableView.reloadData()
totalPriceLabel.text = "Total: \(userOrder.getTotalPriceFormattedWithSeparator())"
updateUI()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
RealmService.shared.stopObservingErrors(in: self)
}
private func updateUI() {
guard let userOrder = userOrder else {return}
if userOrder.products.isEmpty {
tableView.isHidden = true
cartIsEmpty = true
orderButton.setTitle("Pilih Barang", for: .normal)
} else {
tableView.isHidden = false
cartIsEmpty = false
orderButton.setTitle("Pesan Barang", for: .normal)
}
}
}
//MARK: - Table View Delegate & Datasource
extension CheckoutVC : UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return userOrder?.products.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: CheckOutStoryboardData.TableViewIdentifiers.checkOutCell.rawValue, for: indexPath) as? CheckOutCell else {return UITableViewCell()}
guard let userOrderInRealm = userOrder else {return UITableViewCell()}
let products = userOrderInRealm.products
cell.productData = products[indexPath.row]
cell.indexPath = indexPath
cell.delegate = self
let stepperValue = Double(products[indexPath.row].quantity)
cell.stepperValue = stepperValue
return cell
}
}
and here is my code in the table view cell
class CheckOutCell: UITableViewCell {
var indexPath: IndexPath?
var delegate: CheckOutCellDelegate?
#IBOutlet weak var stepperGM: GMStepper!
#IBOutlet weak var productImageView: UIImageView!
#IBOutlet weak var productNameLabel: UILabel!
#IBOutlet weak var subCategoryNameLabel: UILabel!
#IBOutlet weak var pricePerUnitLabel: UILabel!
#IBOutlet weak var priceTotalPerItemLabel: UILabel!
var productData : Product? {
didSet {
updateUI()
}
}
var stepperValue : Double? {
didSet {
setStepper()
}
}
#IBAction func deleteButtonDidPressed(_ sender: Any) {
// send data to CheckoutVC
guard let indexPath = self.indexPath else {return}
self.delegate?.deleteButtonDidTapped(at: indexPath)
}
#IBAction func seeProductButtonDidPressed(_ sender: Any) {
// send data to CheckoutVC
guard let indexPath = self.indexPath else {return}
self.delegate?.viewProductButtonDidTapped(at: indexPath)
}
#IBAction func GMStepperDidTapped(_ sender: GMStepper) {
guard let indexPath = self.indexPath else {return}
let stepperValue = Int(sender.value)
self.delegate?.incrementOrDecrementButtonDidTapped(at: indexPath, counterValue: stepperValue)
}
func setStepper() {
guard let stepperValue = stepperValue else {return}
stepperGM.value = stepperValue
}
func updateUI() {
guard let productData = productData else {return}
// update UI
productNameLabel.text = productData.name
pricePerUnitLabel.text = productData.getFormattedUnitPriceWithSeparator()
priceTotalPerItemLabel.text = productData.getFormattedTotalPriceWithSeparator()
//set image
if let imagePath = productData.imagePaths.first {
guard let encodedImagePath = imagePath.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) else {return}
guard let url = URL(string: encodedImagePath) else {return}
productImageView.kf.indicatorType = .activity //loading indicator
productImageView.kf.setImage(with: url, options: [.transition(.fade(0.2))])
}
}
}
and here is the code to get the data from realm database, I get the data from realm database synchronously.
static func getOrderFromRealmDatabase() -> Order {
let userID = "1"
let realmService = RealmService.shared.realm
let allOrder = realmService.objects(Order.self)
let theOrder = allOrder.filter("userID CONTAINS[cd] %#", userID).first
if let userOrder = theOrder {
return userOrder
} else {
// Order never setted up before in Realm database container
// then create Order in realm database
let newOrder = Order()
newOrder.userID = userID
newOrder.products = List<Product>()
RealmService.shared.save(object: newOrder)
return newOrder
}
}
what went wrong in here, I don't understand :(
Remove optional handling in numberOfRowsInSection because products count never 0. and tableview hidden code is never excuted.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return userOrder?.products.count
}

Load/Download image from SDWebimage and display in Custom tableView cell imageView

i already parsed other values but how will i show image to imageView i m already using SdWebImage in Swift.I want to show that in Bottom cell "detail" Below is my code
import UIKit
import SystemConfiguration
import MBProgressHUD
public struct Section {
var arrayDataTop: String
var arrayTerms: String
var qrImage:String
var collapsed: Bool
public init( arrayDataTop: String,qrImage: String ,arrayTerms: String, collapsed: Bool = false) {
self.arrayDataTop = arrayDataTop
self.qrImage = qrImage
self.arrayTerms = arrayTerms
self.collapsed = collapsed
}
}
class CollapsibleViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
#IBOutlet weak var tableViewCollapsible:UITableView!
#IBOutlet weak var listImage:UIImageView!
var nodatastr:String = "No Deal Found."
var dealIDCollapsible : String?
var dealDictCollapsible = [String: AnyObject]()
var parentNavigationController: UINavigationController?
private var loadingView:MBProgressHUD?
var sectionDataObj = [Section]()
override func viewDidLoad() {
super.viewDidLoad()
if (!self.isInternetAvailable()){
self.alertMessageShow(title: "No Internet Connection", message: "Make sure your device is connected to the internet.")
}
else{
if self.loadingView == nil {
self.loadingView = MBProgressHUD.showAdded(to: self.view, animated: true)
}
tableViewCollapsible.estimatedRowHeight = 100.0
tableViewCollapsible.layoutIfNeeded()
tableViewCollapsible.updateConstraintsIfNeeded()
tableViewCollapsible.tableFooterView = UIView()
self.listImageFetch()
dealFetchParticularListing()
}
}
func dealFetchParticularListing(){
let prs = [
"listing_id":dealIDCollapsible,//dealIDCollapsible,
"Deal_fetch_listing": "1" as String
]
Service.CreateDeal(prs as [String : AnyObject]?, onCompletion: { result in
let json = result as? NSDictionary
if let data = json as? [String:Any]{
if let err = data["status"] as? String, err == "success"{
if let data = data["result"] as? [Any]{
//
//fill your data in that local Section obj
//
var sectionDataObj = [Section]()
for sectionObj in data{
if let sectionObjVal = sectionObj as? [String:Any]{
if let qrcode = sectionObjVal["qrcode"] as? String{
if let tnc = sectionObjVal["tnc"] as? String{
if let deal_title = sectionObjVal["deal_title"] as? String{
let sectionValue = Section(arrayDataTop: deal_title, qrImage: qrcode, arrayTerms: tnc)
// access main objects/UIelement on main thread ONLY
sectionDataObj.append(sectionValue)
}
}
}
}
}
DispatchQueue.main.async { () -> Void in
self.sectionDataObj.removeAll()
//
//assign ur data in main sampleData(Section obj) then reload tableView with that data.
//
self.sectionDataObj = sectionDataObj
self.tableViewCollapsible.reloadData()
self.loadingView?.hide(true)
}
}
}
}
})
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Header
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "header") as! MyCellData
cell.lblDealTitle.text = sectionDataObj[indexPath.section].arrayDataTop
return cell
}
// Cell
let cell = tableView.dequeueReusableCell(withIdentifier: "detail") as! MyCellData
cell.lblTerm.text = sectionDataObj[indexPath.section].arrayTerms
// here i want to show image
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension//320.0
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == 0 {
let collapsed = !sectionDataObj[indexPath.section].collapsed
// Toggle collapse
sectionDataObj[indexPath.section].collapsed = collapsed
self.tableViewCollapsible.reloadSections([indexPath.section], with: .automatic)
}
}
}
class MyCellData:UITableViewCell{
#IBOutlet weak var lblDealTitle: UILabel!
#IBOutlet weak var dealimage: UIImageView!
#IBOutlet weak var lblTerm: UILabel!
#IBOutlet weak var qrCodeImage: UIImageView!
}
Plz help me with this.thanks in advance.All things are working properly i am able to see other details.Help will be appreciated.Plz help me i m struggling with this issue.
update ur tableView cellForRowAt like so to show an image or ur cell from ur sectionDataObj
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Header
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "header") as! MyCellData
cell.lblDealTitle.text = sectionDataObj[indexPath.section].arrayDataTop
return cell
}
// Cell
let cell = tableView.dequeueReusableCell(withIdentifier: "detail") as! MyCellData
cell.lblTerm.text = sectionDataObj[indexPath.section].arrayTerms
let imgUrl = sectionDataObj[indexPath.section]. qrImage
cell.qrCodeImage.sd_setImage(with: URL(string:imgUrl), completed: nil)
return cell
}

how to insert data from string to Sqlite in Swift3?

I have a problem that I have tried to insert string data to Sqlite. I want to do is in my Details ViewController if user press Like button, the word and meaning of string pass into Sqlite file that show in Favourite ViewController. Below is my DetailsVC code.
import UIKit
import AVFoundation
class DetailsVC: UIViewController, UITextViewDelegate {
#IBOutlet weak var wordLbl: UILabel!
#IBOutlet weak var meaningLbl: UITextView!
#IBOutlet weak var sysWordLbl: UILabel!
#IBOutlet weak var sysWordsLbl: UILabel!
#IBOutlet weak var anyWordsLbl: UILabel!
#IBOutlet weak var anyWordLbl: UILabel!
#IBOutlet weak var wordImg: UIImageView!
#IBOutlet weak var buSound: UIButton!
#IBOutlet weak var buLike: UIButton!
#IBOutlet weak var menuBtn: UIButton!
//Data from HomeVC
var data:Data?
var fdatas = [FData]()
var favouriteVC = FavouriteVC()
override func viewDidLoad() {
super.viewDidLoad()
meaningLbl.delegate = self
wordLbl.text = "\((data?._word.capitalized)!) \((data?._phonetic)!)"
self.meaningLbl.text = data?._meaning
self.sysWordsLbl.text = data?._meaning
self.anyWordsLbl.text = data?._meaning
self.sysWordLbl.text = "Synonym"
self.anyWordLbl.text = "Antonym"
meaningLbl.font = UIFont(name: FONT_REGULAR, size: 24.0)
}
#IBAction func buMenu(_ sender: Any) {
//menu
dismiss(animated: true, completion: nil)
}
#IBAction func buSound(_ sender: Any) {
//Todo: speak the word
if buSound.isEnabled == true{
buSound.setImage(UIImage(named: "volume-2.png"), for: .normal)
}else{
buSound.setImage(UIImage(named: "volume-un-2.png"), for: .normal)
}
let utTerance = AVSpeechUtterance(string: "\((data?._word)!)")
let synthesize = AVSpeechSynthesizer()
utTerance.voice = AVSpeechSynthesisVoice(language: "en-gb")
synthesize.speak(utTerance)
}
#IBAction func buLike(_ sender: Any) {
//Todo: Click Like
if buLike.isEnabled == true{
buLike.setImage(UIImage(named: "heart.png"), for: .normal)
//Save data to Database
let word = data?._word ?? ""
let meaning = data?._meaning ?? ""
do{
let favData = FData(word: word, meaning: meaning)
self.fdatas.append(favData)
print("\(word), \(meaning)")
}catch{
print(error)
}
}else{
buSound.setImage(UIImage(named: "heart-un.png"), for: .normal)
}
//FavouriteVC.insertRowsAtIndexPaths([NSIndexPath(forRow: fdatas.count-1, inSection: 0)], withRowAnimation: .Fade)
}
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
self.view.endEditing(true);
return false;
}
}
My FavouriteVC
import UIKit
import SwipeCellKit
import SQLite
class FavouriteVC: UIViewController,UITableViewDelegate,UITableViewDataSource, SwipeTableViewCellDelegate{
//TabelView
#IBOutlet weak var fTableView: UITableView!
//Variables
var fdata = [FData]()
override func viewDidLoad() {
super.viewDidLoad()
// FtableView
fTableView.delegate = self
fTableView.dataSource = self
//reload Data
fTableView.reloadData()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return fdata.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: FAVOURITE_CELL, for: indexPath) as? FavouriteCell{
cell.configureCell(fdata: fdata[indexPath.row])
//cell.delegate = self
return cell
}
return FavouriteCell()
}
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> [SwipeAction]? {
guard orientation == .right else { return nil }
let deleteAction = SwipeAction(style: .destructive, title: "Delete") { action, indexPath in
// handle action by updating model with deletion
}
// customize the action appearance
deleteAction.image = UIImage(named: "delete")
return [deleteAction]
}
}
FData.swif
import Foundation
class FData {
//let id: Int64?
var word: String
var meaning: String
//var address: String
init(id: Int64) {
// self.id = id
word = ""
meaning = ""
//address = ""
}
init(word: String, meaning: String) {
// self.id = id
self.word = word
self.meaning = meaning
//self.address = address
}
}
FavouriteData Instance
import UIKit
import SQLite
class FavouriteData{
static let instance = FavouriteData()
private let db: Connection?
private let words = Table("words")
private let id = Expression<Int64>("id")
private let wordL = Expression<String?>("word")
private let meaningL = Expression<String?>("shanword_uni")
//private let address = Expression<String>("address")
private init() {
let path = NSSearchPathForDirectoriesInDomains(
.documentDirectory, .userDomainMask, true
).first!
do {
db = try Connection("\(path)/favourite.sqlite")
} catch {
db = nil
print ("Unable to open database")
}
createTable()
}
func createTable() {
do {
try db!.run(words.create(ifNotExists: true) { table in
table.column(id, primaryKey: true)
table.column(wordL)
//table.column(phone, unique: true)
table.column(meaningL)
})
} catch {
print("Unable to create table")
}
}
func addData(word: String, meaning: String) -> Int64? {
do {
let insert = words.insert(wordL <- word, meaningL <- meaning)
let id = try db!.run(insert)
print("Save: \(id)")
return id
} catch {
print("Insert failed")
return -1
}
}
func getData() -> [FData] {
var contacts = [FData]()
do {
for contact in try db!.prepare(self.words) {
contacts.append(FData(
// id: contact[id],
word: contact[wordL]!,
meaning: contact[meaningL]!))
}
} catch {
print("Select failed")
}
return contacts
}
func deleteData(index: Int64) -> Bool {
do {
let contact = words.filter(id == index)
try db!.run(contact.delete())
return true
} catch {
print("Delete failed")
}
return false
}
}
But, there is not cell of row in the FavouriteVC. How to fix this? Please help me.
Best,
Sai Tawng Pha
I have solved my problem by add one line of code. In my FavouriteVC class, just add it under ViewdidLoad function " fdata = FavouriteData.instance.getData() ".
Here is my complete code.
import UIKit
import SwipeCellKit
import SQLite
class FavouriteVC: UIViewController,UITableViewDelegate,UITableViewDataSource, SwipeTableViewCellDelegate{
//TabelView
#IBOutlet weak var fTableView: UITableView!
//Variables
var fdata = [FData]()
override func viewDidLoad() {
super.viewDidLoad()
// FtableView
fTableView.delegate = self
fTableView.dataSource = self
//reload Data
fTableView.reloadData()
//Get Data
fdata = FavouriteData.instance.getData()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return fdata.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: FAVOURITE_CELL, for: indexPath) as? FavouriteCell{
cell.configureCell(fdata: fdata[indexPath.row])
//cell.delegate = self
return cell
}
return FavouriteCell()
}
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> [SwipeAction]? {
guard orientation == .right else { return nil }
let deleteAction = SwipeAction(style: .destructive, title: "Delete") { action, indexPath in
// handle action by updating model with deletion
}
// customize the action appearance
deleteAction.image = UIImage(named: "delete")
return [deleteAction]
}
}

Resources