I have been following VIPER design pattern for my current iOS (Swift) project and i am new on using design pattern on code. I am having trouble to take decision about customizing or configuring a subclass of UITableViewCell. Do i change the cell's on ViewController's ->
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell this delegate method or on my derived UITableViewCell's class instance method's ?? Actually the work is changing cell's IBOutlets like Label, ImageView from Model data
I think you should change your cell inside cell because you're not breaking the encapsulation and can make your IBOutlets private.
Actually you can incapsulate you UITableViewDelegate and UITableViewDataSource realisation in some object. We're creating TableViewAdapter for this. You can find example of TableViewAdapter in my open source VIPER example here.
Related
In an iOS app I have a ViewController that has a ContainerView in which a ViewController (say VC2) resides, using an Embed Segue. This VC2 owns a UITableView and it's datasource and delegate are set to the VC2 and also conforms to the UITableViewDataSource and UITableViewDelegate protocols.
Now the cells are rendered perfectly, so the dataSource seems good. But when I try to select a row, nothing happens, so there seems to be a problem with the delegate.
However, the delegate methods willDisplayCell and shouldHightlightRowAt do get called. And I only implemented these method to check whether the delegate is set up correctly. And no, I did NOT implement the didDeselectRowAt method, which is a common mistake.
In IB the tableview owns two dynamic prototype cells, the Selection property is set to Single Selection and the Style is set to Plain. Both the UITableViewCells have a Style set to Custom and Selection is set to Default.
Why doesn't the didSelectRowAt method get called? I did check the isEditing property, which is set to false; editing is not relevant in my case.
this is my didSelect method:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("didSelectRowAt (indexPath.row)")
}
I use Swift 4.
I'm sorry, but it seems that Xcode has given me a really hard time.
I just deleted the ViewController from the storyboard and built it up from scratch again. Also created a new file for the VC and now everything works just as expected. Sometimes the is the way to go is delete all your work and start over again and in this particular case... it was.
I really cannot say what could be the cause; but it seems that something got messed up in the storyboard file. At least, that is my best guess.
Wasted some time... Thanks anyway for attending...
I'm currently going through a tutorial on UITableView. While learning I'm attempting to understand how the UITableView should be constructed by following Apple's documentation and its programming guides. In the tutorial, the developer places the dequeueReusableCell(withIdentifier:) method inside of the tableView(_:cellForRowAt:) method which belongs to the datasource. As a newcomer after reading Apple's references and guides, I would not have guessed that the dequeueReusableCell(withIdentifier:) method goes inside of the tableView(_:cellForRowAt:) method. As a developer, how do you pick up on subtle things like this? Is it because the tableView(_:cellForRowAt:) method returns a UITableViewCell and may be the best place to do UITableViewCell configurations?
I'd like to gain a better understanding of Apple's references for future projects, thank you in advance for any comments or answers.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ItemCell", for: indexPath)
return cell
}
Something really weird is going on after our Swift 3 migration.
We have two view controllers, both of them implement UITableViewDelegate and both of them implement public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
However only in one of them the actual method is called.
If I change in the one that doesn't work public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) to public func tableView(_ tableView: UITableView, didSelectRowAtIndexPath: IndexPath) (notice the Swift 2.2 signature) then they both work.
Both view controllers are Swift classes, so I am not sure what the heck is going on.
I am pretty sure it might be a Objective-C vs Swift interoperability issue, but our whole project is written in Swift, so that's why it's hard to figure out what is causing this.
Any help is appreciated.
Thank you.
for Swift 3.0, use
override func tableView(_ tableView: UITableView, didSelectRowAt
indexPath: IndexPath){
//your code...
}
I encountered a similar problem. My problem was caused by having a superclass that adopted the UITableViewDelegate and UITableViewDataSource protocols, and then implementing the actual methods in a subclass.
What I gather is that because UITableViewDelegate and UITableViewDataSource are objective-c protocols, they must be adopted directly by the class implementing these functions. Otherwise the Swift function signatures will not be properly mapped to the objective-c function signatures (not sure why this is the case).
In Swift versions prior to 3.0, the underlying objective-c function signatures matched the signatures in the Swift UITableViewDelegate and UITableViewDataSource protocols. Therefore prior to 3.0 it seems to have worked fine to have a superclass adopt these protocols. However as of Swift 3.0 these signatures are no longer a match. It seems that to have the new-style signature properly mapped to the underlying objective-c signature, your class must directly adopt the UITableViewDelegate and UITableViewDataSource protocols.
Therefore in Swift 3.0 and later, if you do not directly adopt the UITableViewDelegate and UITableViewDataSource protocols then your function signatures must match the old-style underlying objective-c signatures in order for your functions to be called correctly.
I have an image inside my tableview cell.
What I want to do is when I click on that cell I want to parse both text & image to detail view.
I can do for text but I can't get the point about image.
So, simply my question is how can I parse image inside tableview cell to detail view in iOS.
Thanks
You can use it as the same way you're using it. Use indexPath to specify the row you wanna manipulate.
Here's how you do it. implement UITableViewDelegate in your ViewController, and implement the following method.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
}
The short answer, you access the image the same way that you set it. In the case of the standard UITableViewCell, it is the imageView property that you used.
For these API type questions though, there is no better place to start, than the documentation
Hi I'm new to coding so basically i've created a tableview app on github
the first one shows what i want to do without code https://github.com/edlen/guideline.git
and the second one is an attempt to recreate it with code
https://github.com/edlen/guidelines-via-code.git
but I'm really stuck about how to create code for going between screens so say for example on the main menu I select helpful info, how do i make the tableview with those options appear? and then if i select PO switch how do I segue to it?
Technically I can do what I want grand without code but I would really like to be able to understand coding of tableviews better and how to go between multiple tableviews and then select a final individualised view controller full of text.
Any advice that you could offer would be great- but please be prepared to speak very slowly and clearly as I'm still learning as i go along!!
At first, designing the app with Interface Builder inside Xcode is both the same for Swift and Objective C.
A UITableViewController should be embedded inside a UINavigationController, if you want to switch between views. Just drag'n'drop a UINavigationController and a UITableViewController into your storyboard - make sure the UITableViewController is the root viewcontroller of the navigation controller (right-click drag the tableview controller on the navigation controller).
After that, create a new Cocoa Touch Class - file (or press CMD-N). Look at this:
Make sure you choose UITableViewController at "Subclass of".
After that, go back to your interface builder and select your UITableViewController. There go to the identity inspector to change the class of your tableview controller. Look here:
After that, you just need to choose a reuse identifier for you tableview cells. You need the reuse identifier, so that your iPhone (or iPad) can reuse a cell and doesn't have to create a new one everytime. I just chose "myCell" as reuse identifier. To do that, click on the cell and go to the attributes inspector:
OK, the part with interface builder is done. Now go to your previously created MyTableViewController.swift.
There you have some methods. You need at least these to methods:
func numberOfSectionsInTableView(tableView: UITableView) -> Int
and
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
You need these methods, because the data source of your tableview is set to self. That means, this class is used to fill your tableview with information.
Let's start simple. To test everything, just use 1 section. So in your numberOfSectionsInTableView return 1.
If you have some data to be displayed, I think you'll store this data inside an array? However, in numberOfRowsInSection you have to return the number of rows that have to be displayed inside that section. So if you want to display 3 rows, just return 3 here. That makes 1 section with 3 rows inside that section.
Now you have to customize your tableview cell with labels and maybe an image view. So you need the function
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("myCell", forIndexPath: indexPath) as UITableViewCell
// Configure the cell...
// add some UILabels or UIImageViews here.
return cell
}
to create your own cells. Here you'll need the reuse identifier you've set in interface builder.
A UITableView also has a delegate, which is responsible for events like (de)selecting a cell. So if you want to show a UIViewController when the user taps on a cell, you have to implement the method
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
Here you can switch between views. Here you need to have the tableview controller embedded inside a navigation controller (except you are presenting your views as modal view controllers, but that's not the point here).
So the user taps on a cell, you have the index of the cell inside indexPath.row - you'll need that to show the user the information inside the new view. After that, create your UIViewController or whatever, and present the viewcontroller with
self.navigationController?.presentViewController(myViewControllerToPresent, animated: true, completion: { () -> Void in
// some code to do after the presentatioin is ready
})
That's it!