I'm trying to figure out a way to push images that are loaded via SDWebImage on a TableView, to a view (DetailView) where the image can be viewed in fullscreen.
I have the images loaded from URLs displaying on a table view correctly. But when I tap on one, it segues to another view (DetailView) that is blank when I have a UIImage there. For some reason, the image is not loading.
Thanks!
Here is the TableView code:
import UIKit
class TableViewController: UITableViewController {
var imageURLs = [String]()
override func viewDidLoad() {
super.viewDidLoad()
imageURLs = ["https://i.imgur.com/lssFB4s.jpg","https://i.imgur.com/bSfVe7l.jpg","https://i.imgur.com/vRhhNFj.jpg"]
// 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.
}
override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "DetailView") {
let VC = segue.destinationViewController as! DetailViewController
if let indexpath = self.tableView.indexPathForSelectedRow {
let Imageview = imageURLs[indexpath.row] as String
VC.SentData1 = Imageview
}
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
let cell2: TableViewCell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! TableViewCell
let imagename = UIImage(named: imageURLs[indexPath.row])
cell2.cellImage.image = imagename
let imageView = cell?.viewWithTag(1) as! UIImageView
imageView.sd_setImage(with: URL(string: imageURLs[indexPath.row]))
return cell!
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return imageURLs.count
}
Here is the DetailView code:
import UIKit
class DetailViewController: UIViewController {
#IBOutlet weak var Detailimageview: UIImageView!
var SentData1:String!
override func viewDidLoad() {
super.viewDidLoad()
Detailimageview.image = UIImage(named: SentData1)
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// 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: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
You are using UIImage(named:) in your destination VC. This will try and load the image from your bundle, not from the network. You should use sd_setImage to fetch it from the network (or via cache if it has already been fetched):
Detailimageview.sd_setImage(with: URL(string:self.SentData1))
Note that properties and variables should start with a lower case letter by convention
When you load your detail view, you are passing the web URL for the image you want to load but then trying to load it from the bundle with UIImage(named: SentData1).
Instead you should just be loading it the same way you are doing it in your tableview cells by doing something like Detailimageview.sd_setImage(with: URL(string: SentData1))
Related
currently thumbnails are being shown in UITableViewCell and upon tapping a cell, I want the image to be shown in foreground with a cross/X button on right top to dismiss the image and show tableView. I have the following code in didSelectRow:
let hoverImage = UIImageView()
hoverImage.image = UIImage(named: "splashpt")
hoverImage.contentMode = .scaleAspectFit
self.view.addSubview(hoverImage)
hoverImage.center = self.view.center
hoverImage.layer.zPosition = 5
self.view.bringSubview(toFront: hoverImage)
Still the image doesn't show up. The computation is hitting this section of the code because I'm able to debug and step through this part of the code. But nothing shows up on screen. I'm using the zPosition AND bringSubview(toFront:) and neither of the seem to work for my requirement. Any help would be greatly appreciated. Thank you.
This is a Demo table view.On tapping the table view cells a view is poped up with close button. And on pressing the close button the pop up view is closed.
import UIKit
class ViewController: UITableViewController {
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.
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell")! as UITableViewCell
cell.textLabel?.text = "Happy"
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("Cell\(indexPath.row) is selected")
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let popoverVC = storyBoard.instantiateViewControllerWithIdentifier("PopViewController") as! PopViewController
popoverVC.delegate = parentViewController as? InfoViewDelegate
let nav = UINavigationController(rootViewController: popoverVC)
nav.modalPresentationStyle = UIModalPresentationStyle.Popover
nav.navigationBar.hidden = true
self.presentViewController(nav, animated: true)
{
}
popoverVC.passingViewController = self
}
}
This is a PopUpViewController:
import UIKit
protocol InfoViewDelegate: class
{
func infoViewClicked(tag: Int)
}
class PopViewController :UIViewController
{
#IBOutlet weak var btnClose: UIButton!
var delegate = InfoViewDelegate?()
var passingViewController: UIViewController!
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.
}
override func viewWillAppear(animated: Bool) {
}
override func viewDidDisappear(animated: Bool) {
self.presentingViewController?.dismissViewControllerAnimated(true
, completion: {
})
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
#IBAction func btnClicked(sender: UIButton) {
if(sender == self.btnClose)
{
self.delegate?.infoViewClicked(1)
self.presentingViewController?.dismissViewControllerAnimated(true
, completion: {
})
}
}
}
I want to use a TableView for the detail side of a Master Detail app. I have started with the standard Master Detail project in Xcode, deleted the standard app that comes with it, deleted the standard UIView detail controller, added a TableView controller, added a TextView to the prototype cell for testing, and created a new segue to the new TableView. I subclassed UITableViewCell and created an outlet (detailTextView) from the TextView to the subclass (TableViewCell). Changed the class in DetailViewController.swift from UIViewController to UITableViewController. I am successfully passing a string stringForTextView = "String for TextView" from master to the detail. But I can't figure out how to display that string in the TextView. I tried to reference the TextView text in the detail view through the outlet (detailTextView.text) but got "Use of unresolved identifier detailTextView"
Any help will be greatly appreciated.
Relevant code is shown below.
You can also download the whole project here if that would be helpful:
http://greendept.com/MasterDetailTwoTableViews/
TableViewCell.swift (subclass for prototype cell in detail)
import UIKit
class TableViewCell: UITableViewCell {
#IBOutlet weak var detailTextView: UITextView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
DetailViewController.swift
import UIKit
class DetailViewController: UITableViewController {
var stringForTextView : String?
var detailItem: AnyObject? {
didSet {
// Update the view.
self.configureView()
}
}
func configureView() {
// THE NEXT TWO LINES WORK: PASSED IN STRING PRINTS TO CONSOLE
let printThis = stringForTextView! as String
print("\(printThis)")
// BUT THE REFERENCE TO THE OUTLET BELOW DOES NOT WORK, GIVES
// "Use of unresolved identifier detailTextView"
detailTextView.text = printThis
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.configureView()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
MasterViewController.swift
import UIKit
class MasterViewController: UITableViewController {
var detailViewController: DetailViewController? = nil
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
if let split = self.splitViewController {
let controllers = split.viewControllers
self.detailViewController = (controllers[controllers.count-1] as! UINavigationController).topViewController as? DetailViewController
}
}
override func viewWillAppear(animated: Bool) {
self.clearsSelectionOnViewWillAppear = self.splitViewController!.collapsed
super.viewWillAppear(animated)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Segues
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showDetail" {
if let indexPath = self.tableView.indexPathForSelectedRow {
let controller = (segue.destinationViewController as! UINavigationController).topViewController as! DetailViewController
controller.stringForTextView = "String for TextView"
controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem()
controller.navigationItem.leftItemsSupplementBackButton = true
}
}
}
// MARK: - Table View
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
return cell
}
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
}
DetailViewController is a UITableViewController, and you can't access the detailTextView in the tableView controller. You defined the outlet in the cell, and that is where you can access and configure the detailTextView.
It doesn't make any sense to have the DetailViewController as a UITableViewController, if what you really want is to configure the text view there. Then you should set it back to a UIViewController, and add the text view as a single UITextView to the view controllers view.
This link below shows how you can change text in a cell label even though the outlet to the textview is in the cell subclass. It shows this with a single TableView.
creating custom tableview cells in swift
In adapting the above approach for my test project, I didn't have to change the Master at all. In the Detail view, the configureView() doesn't do the main job of updating the TextView. That happens in cellForRowAtIndexPath -- second to the last function in detail view. Another difference is I could not, and did not need to, implement #IBOutlet var tableView: UITableView! -- because tableView was already available as a stored property. I also had to add overrride in a couple of places. Finally, in the TableViewCell class, I added an outlet linked to the content view of the TextView. The result is that the TextView text is getting updated.
TableViewCell.swift:
import UIKit
class TableViewCell: UITableViewCell {
#IBOutlet weak var detailTextView: UITextView!
#IBOutlet weak var detailContentView: UIView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
print ("awakeFromNib")
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
print("test")
}
}
DetailViewController.swift:
import UIKit
class DetailViewController: UITableViewController {
// #IBOutlet var tableView: UITableView! -- cannot override a stored property
var stringForTextView : String?
// Don't forget to enter this in IB also
let cellReuseIdentifier = "reuseIdentifier"
var detailItem: AnyObject? {
didSet {
// Update the view.
self.configureView()
}
}
func configureView() {
// Update the user interface for the detail item.
// stringForTextView
let printThis = stringForTextView! as String
print("\(printThis)")
// detailTextView.text = printThis
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
self.configureView()
}
// needed "override" here
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
// create a cell for each table view row
// needed "override" here
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:TableViewCell = self.tableView.dequeueReusableCellWithIdentifier(cellReuseIdentifier) as! TableViewCell
cell.detailTextView.text = stringForTextView
print("cell.detailTextView.text: \(cell.detailTextView.text)")
print("row : \(indexPath.row)")
return cell
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I have a UICollectionView in a view controller. When the user clicks one of the images, it goes to a separate page to open the image. I would like instead of going back to the gallery each time to change pictures, to swipe left or right to get the next or previous picture.
I have seen answers to do "pagingEnabled = true" but where do you put this exactly?
I am new to swift.
Below is my code. Thanks for the help in advance.
ViewController.swift
import UIKit
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate
{
#IBOutlet weak var collectionView: UICollectionView!
let appleProducts = ["iPhone", "Apple Watch", "Mac", "iPad"]
let imageArray = [UIImage(named: "pug"), UIImage(named: "pug2"), UIImage(named: "pug3"), UIImage(named: "pug4")]
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 collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return self.appleProducts.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! CollectionViewCell
cell.imageView?.image = self.imageArray[indexPath.row]
cell.titleLabel?.text = self.appleProducts[indexPath.row]
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
{
self.performSegueWithIdentifier("showImage", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if segue.identifier == "showImage"
{
let indexPaths = self.collectionView!.indexPathsForSelectedItems()!
let indexPath = indexPaths[0] as NSIndexPath
let vc = segue.destinationViewController as! NewViewController
vc.image = self.imageArray[indexPath.row]!
vc.title = self.appleProducts[indexPath.row]
}
}
}
CollectionViewCell.swift
import UIKit
class CollectionViewCell: UICollectionViewCell
{
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var titleLabel: UILabel!
}
NewViewController.swift
import UIKit
class NewViewController: UIViewController
{
#IBOutlet weak var imageView: UIImageView!
var image = UIImage()
override func viewDidLoad()
{
super.viewDidLoad()
self.imageView.image = self.image
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
In the view controller that is presented after a tap, you should make a horizontally scrolling UICollectionView. On this collection view, set its pagingEnabled property to true.
The next thing to do is reformat your prepareForSegue method in your parent view controller to pass the entire array of images to the presented view controller as well as the selected index path.
Then, in your presented view controller, you should have the collection view's data source be configured to show all the images but make sure to start at the initial, selected index path that was passed by the parent view controller.
My app is in swift using story board. After launch file my app start the initial view controller the one I have already set the entry point. But suddenly my app doesn't appear the initial viewcontroller after the Launching screen.but if I set the entry point to another view controller its appear. The first viewcontroller viewdidload and all other UITableView delegates and datasource are running when Idebug but the screen doesnt come it just keep staying on my launch file.
What would be the reason for this? Please help me.
Thanks
UPDATE
import UIKit
class SubscriptionViewController: UIViewController,UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tblSettings: UITableView!
#IBOutlet weak var vwTitle: UIView!
var mutableDictionary :[String]=["Business","News","Sports","Entertainment","Crime","Politics"]
var imageView = UIImageView.init(frame: CGRectMake(0, 0, 20, 20))
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
tblSettings.backgroundColor=UIColor.clearColor()
tblSettings.delegate=self
tblSettings.dataSource=self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return mutableDictionary.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("SettingsCell") as! SettingsTableViewCell!
if cell == nil
{
//tableView.registerNib(UINib(nibName: "UICustomTableViewCell", bundle: nil), forCellReuseIdentifier: "UICustomTableViewCell")
tableView.registerClass(SettingsTableViewCell.classForCoder(), forCellReuseIdentifier: "SettingsCell")
cell = SettingsTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "SettingsCell")
}
cell.backgroundColor=UIColor.clearColor()
// Custom view options
let image=UIImage.init(named: "SettingsUnChecked")
imageView.image=image
cell.accessoryType = UITableViewCellAccessoryType.None
cell.accessoryView = imageView//UIButton(frame: CGRectMake(0, 0, 20, 20))
cell.accessoryView!.backgroundColor = UIColor.clearColor()
if let label = cell.lblName{
label.text = mutableDictionary[indexPath.row]
label.textColor=UIColor.whiteColor()
}
return cell
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
I'm learning swift, and i'm having problems trying to fire a segue when a TableViewCell is touched, which is supposed to pass an url to a second view that for the moment just a displays it in a label.
i Dynamically create ( i've seen people use Programmatically, which is probably the right word) every single Cell, so, in the storyboard i don't have any object to link to another view except the view itself... and that's what i did.
So i connected the first view controller to the second, and added the code to perform the segue.
i'm not sure if it's right, my knowledge comes from tutorials that didn't exactly explain what i wanted to do.
down there there's the code of the two views.
first view
import UIKit
protocol sendInfoDelegate{
func userDidEnterInfo( WhichInfo info : String)
}
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var tableData = []
#IBOutlet weak var redditListTableView: UITableView!
var selectedCellURL : String?
var delegate : sendInfoDelegate? = nil
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// change the link to change the json source
getRedditJSON("http://www.reddit.com/.json")
}
//
//Creates a connection via a task (networktask) then parses the json
//
func getRedditJSON(whichReddit : String){
let mySession = NSURLSession.sharedSession()
let url: NSURL = NSURL(string: whichReddit)
let networkTask = mySession.dataTaskWithURL(url, completionHandler : {data, response, error -> Void in
var err: NSError?
var theJSON = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSMutableDictionary
let results : NSArray = theJSON["data"]!["children"] as NSArray
dispatch_async(dispatch_get_main_queue(), {
self.tableData = results
self.redditListTableView.reloadData()
})
})
networkTask.resume()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//needs to be implemented
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableData.count
}
//creates the whole table
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "MyTestCell")
let redditEntry : NSMutableDictionary = self.tableData[indexPath.row] as NSMutableDictionary
cell.textLabel?.text = redditEntry["data"]!["title"] as? String
cell.detailTextLabel?.text = redditEntry["data"]!["author"] as? String
return cell
}
// action to be taken when a cell is selected
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let redditEntry : NSMutableDictionary = self.tableData[indexPath.row] as NSMutableDictionary
self.selectedCellURL = redditEntry["data"]!["url"] as? String
self.performSegueWithIdentifier("passInfo" , sender: indexPath)
println(self.selectedCellURL!)
if delegate != nil {
let information:String = self.selectedCellURL!
println("ciao")
delegate?.userDidEnterInfo(WhichInfo: information)
self.navigationController?.popViewControllerAnimated(true)
}
second view
import UIKit
class WebPageController : UIViewController, sendInfoDelegate {
var infoFromSVC: String?
#IBOutlet weak var labelVC: UILabel!
func userDidEnterInfo(WhichInfo info: String) {
self.infoFromSVC = info
labelVC.text = infoFromSVC
}
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.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "passInfo"{
let firstVController : ViewController = segue.destinationViewController as ViewController
firstVController.delegate = self
}
}
}
Thanks.
To pass any data to second view controller you need to implement prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) method in your first view controller and here pass any data to your second view controller through segue.destinationViewController object.
for example
// this method must be in first view controller
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "passInfo" {
var secondViewController : SecondViewController = segue.destinationViewController as SecondViewController
var indexPath = self.tableview.indexPathForSelectedRow() //get index of data for selected row
secondViewController.data = self.dataArray.objectAtIndex(indexPath.row) // get data by index and pass it to second view controller
}
}
The code for getting data in second view controller
override func viewDidLoad() {
super.viewDidLoad()
self.label.text = self.data
}
The data variable must be defined as a property of your second view controller.