I would like to tap on the TableView cell in Swift 3.0 and transition the screen to ViewController on another Storyboard.
The following methods for screen transition
present(viewController, animated:true, completion:nil)
cannot be implemented in TableView class.
In this case, is there no other way but to use the TableView Controller?
I would appreciate it if you could reply.
Use of unresolved identifier 'present'
/*
* FolderTableView.swift
*/
import UIKit
class FolderTableView:NSObject, UITableViewDelegate, UITableViewDataSource{
// half-way omission
functableView(_tableView:UITableView, didSelectRowAtindexPath:IndexPath){
let storyboard:UIStoryboard=UIStoryboard(name: "Task", bundle:nil)
lettaskListViewController=storyboard.instantiateViewController(withIdentifier: "Task")
self.present(taskListViewController, animated:true, completion:nil)
↑ I want to use this method to transition the screen
}
}
/*
* FolderListViewController.swift
*/
import UIKit
import RealmSwift
class FolderListViewController:UIViewController {
@IBOutlet weak var folderTableView: UITableView!
let folderTable=FolderTableView()
override func viewDidLoad(){
super.viewDidLoad()
folderTableView.delegate=folderTable
folderTableView.dataSource=folderTable
}
// omission
}
·Implement the present method within FolderListViewController calling TableView
→The following error occurs in the line folderTableView.delegate=folderTable when tapping the cell
fatal error: unexpectedly found nil while unwrapping an optional value
·Create a ViewController class for the present method and call the method in FolderTableView
→The following error occurs when tapping the cell
Warning: Attempt to present<skillup7.TaskListViewController:0x7f98b423650>on<skillup7.TestViewController:0x7f98b522230>whose view is not in the window hierarchy!
↓↓Prepared ViewController Class ↓↓
/*
* TestViewController.swift
*/
import UIKit
class TestViewController:UIViewController {
override func viewDidLoad(){
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override funcdidReceiveMemoryWarning(){
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func send (viewController: UIViewController) {
self.present(viewController, animated:true, completion:nil)
}
}
languages:Swift 3.0
swift ios swift3
Can't I do screen transition only from ViewController?
→Yes
Is the only way to do this is to use the TableViewController?
(UITableViewController
means) → No
(If you mean ViewController displaying UITableView
) → Yes
Implement the present method in FolderListViewController calling TableView
I can't say anything about the code that is currently presented because there is no part of the FolderListViewController that implements the present method.
Create a ViewController class for the present method and invoke the method in FolderTableView
This is bound to fail; the instance of the ViewController class that invokes the present
method must be 現在the one currently responsible for displaying the screen 表示.Even if you are in the same class, you will fail if you create a different instance than the one that is responsible for displaying the screen.
While I'm not sure what I've tried above, it would be easier to add properties to FolderTableView
because the present
method should be called from the ViewController instance currently responsible for displaying the screen.
Also, as you can see in the comments, it's so disgusting to have a class name ...View
in a class that is not View, so in the following code example, we have renamed it FolderTable
without permission.
/*
* FolderTable.swift
*/
import UIKit
classFolderTable:NSObject, UITableViewDelegate, UITableViewDataSource{
// Properties to keep the ViewController instance currently responsible for displaying the screen
weak var owner —UIViewController?
// half-way omission
functableView(_tableView:UITableView, didSelectRowAtindexPath:IndexPath){
let storyboard:UIStoryboard=UIStoryboard(name: "Task", bundle:nil)
lettaskListViewController=storyboard.instantiateViewController(withIdentifier: "Task")
// Call the `present(_:animated:completion:)` method for the ViewController instance that is currently responsible for displaying the screen
owner?.present(taskListViewController, animated:true, completion:nil)
}
}
/*
* FolderListViewController.swift
*/
import UIKit
import RealmSwift
class FolderListViewController:UIViewController {
@IBOutlet weak var folderTableView: UITableView!
let folderTable=FolderTable()
override func viewDidLoad(){
super.viewDidLoad()
"/ Set ""ViewController Instance currently responsible for displaying the screen"" (===self) in ""folderTable"""
folderTable.owner=self
folderTableView.delegate=folderTable
folderTableView.dataSource=folderTable
}
// omission
}
Personally, implementing UITableViewDelegate
, UITableViewDataSource
in a separate class seems to have far more disadvantages than advantages and disadvantages.In iOS programming, the ViewController tends to get bloated, so you might have wanted to avoid it, but in Swift, extensions are much easier to use, so I think the code will be much cleaner.
class FolderListViewController:UIViewController {
@IBOutlet weak var folderTableView: UITableView!
override func viewDidLoad(){
super.viewDidLoad()
folderTableView.delegate=self
folderTableView.dataSource=self
}
// omission
}
extensionFolderListViewController:UITableViewDelegate,UITableViewDataSource{
// half-way omission
functableView(_tableView:UITableView, didSelectRowAtindexPath:IndexPath){
let storyboard:UIStoryboard=UIStoryboard(name: "Task", bundle:nil)
lettaskListViewController=storyboard.instantiateViewController(withIdentifier: "Task")
self.present(taskListViewController, animated:true, completion:nil)
}
}
You cannot declare properties for extension, but I don't think it will be a big problem if you design a model class that is easy to implement UITableViewDelegate
, UITableViewDataSource
and make it a different class.
Because the present(_:animated:completion:) function is the UIViewController, only classes inheriting the UIViewController
can be invoked.The error message UUse of unresolved identifier 'present' 」 means that a method named にpresent されて is not implemented in the FolderTableView class.This is an error because you are calling something that does not exist.
If you want to run the present function after processing within a class that cannot use the present(_:animated:completion:) function, you can create a custom delegate.For example, create a new protocol like this
.import UIKit
protocolFolderTableViewTransitionDelegate{
funcgoToTaskListScene()
}
Then, create the above delegate properties in the class that triggers the transition execution, and call the delegate method within the method that actually triggers the transition execution.
class FolderTableView: NSObject, UITableViewDelegate, UITableViewDataSource{
// Properties referencing the delegate protocol (optional, no value here)
vardelegate —FolderTableViewTransitionDelegate?
// UITableViewDelegate method called when selecting cells in a table view
functableView(_tableView:UITableView, didSelectRowAtindexPath:IndexPath){
// call a custom delivery method
delete?goToTaskListScene()
}
// Abbreviated below
}
Then, the controller class responsible for the transition process will conform to the protocol that you just created.Then set itself to the delegate property.In addition, it implements a method that actually performs transition processing.
// Add a protocol name to make this class compliant
class FolderListViewController:UIViewController, FolderTableViewTransitionDelegate{
@IBOutlet weak var folderTableView: UITableView!
privatelet folderTable=FolderTableView()
// MARK:-UIViewController method
override func viewDidLoad(){
super.viewDidLoad()
// Configure this Class for the Deligate Properties
folderTable.delegate=self
folderTableView.delegate=folderTable
folderTableView.dataSource=folderTable
}
// MARK:- FolderTableViewTransitionDelegate method
// method for performing a transition
funcgoToTaskListScene(){
let storyboard:UIStoryboard=UIStoryboard(name: "Task", bundle:nil)
lettaskListViewController=storyboard.instantiateViewController(withIdentifier: "Task")
self.present(taskListViewController, animated:true, completion:nil)
}
}
By implementing the delegate function using the protocol as described above, the present(_:animated:completion:) method can be used to achieve a modal transition, even from non-classes that inherit the UIViewController or UIViewController.
You do not need to create a new UIViewController subclass just to use the present function.In this case, wouldn't it be more efficient to use an existing class?
However, as you pointed out in the other answers and comments, there is a fundamental problem with this code.Apple recommends a MVC (Model-View-Controller) design pattern to program application development.This code appears to be out of the recommended naming convention because some sections are not organized in the form of MVC.Understanding MVC and Swift naming conventions and writing code should reduce errors.You should also be able to create more efficient and appropriate subclasses.
The "fatal error: unexpected found nil while unwrapping an optional value" error appears to be due to the outlet not being linked properly. We recommend that you first check the outlet's connection status with Connections Inspector, and then try a new code.
© 2024 OneMinuteCode. All rights reserved.