Cannot add UITableViewDataSource and SKProductsRequestDelegate protocols - ios

I'm trying to add in-app purchase to my app. But I've no knowledge about how to add in app purchase. That's why I'm following this guide. According to guide I added UITableViewDelegate, UITableViewDataSource, SKProductsRequestDelegate protocols. Unfortunately I got an error shown below. What is the problem and how can I solve it?
import UIKit
import StoreKit
class IAPurchaceViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, SKProductsRequestDelegate {

You must implement the required delegate methods of the delegate's REQUIRED protocols
I'll show you, I just tried this and it works: here's the methods you need to add, at minnimum in fact, here's an example, this is all you need:
import Foundation
import UIKit
import StoreKit
class ANExample: UIViewController, UITableViewDataSource, UITableViewDelegate, SKProductsRequestDelegate {
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
return A_CEll //you must code this
}
func productsRequest(request: SKProductsRequest!, didReceiveResponse response: SKProductsResponse!) {
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return A_NUMBER // you must code this!
}
}
the protocol for the StoreKit stuff is this:
protocol SKProductsRequestDelegate : SKRequestDelegate, NSObjectProtocol {
// Sent immediately before -requestDidFinish:
#availability(iOS, introduced=3.0)
func productsRequest(request: SKProductsRequest!, didReceiveResponse response: SKProductsResponse!)
}
the protocol for table datasource is this:
protocol UITableViewDataSource : NSObjectProtocol {
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
// Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier:
// Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls)
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
optional func numberOfSectionsInTableView(tableView: UITableView) -> Int // Default is 1 if not implemented
optional func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? // fixed font style. use custom view (UILabel) if you want something different
optional func tableView(tableView: UITableView, titleForFooterInSection section: Int) -> String?
// Editing
// Individual rows can opt out of having the -editing property set for them. If not implemented, all rows are assumed to be editable.
optional func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool
// Moving/reordering
// Allows the reorder accessory view to optionally be shown for a particular row. By default, the reorder control will be shown only if the datasource implements -tableView:moveRowAtIndexPath:toIndexPath:
optional func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool
// Index
optional func sectionIndexTitlesForTableView(tableView: UITableView) -> [AnyObject]! // return list of section titles to display in section index view (e.g. "ABCD...Z#")
optional func tableView(tableView: UITableView, sectionForSectionIndexTitle title: String, atIndex index: Int) -> Int // tell table which section corresponds to section title/index (e.g. "B",1))
// Data manipulation - insert and delete support
// After a row has the minus or plus button invoked (based on the UITableViewCellEditingStyle for the cell), the dataSource must commit the change
// Not called for edit actions using UITableViewRowAction - the action's handler will be invoked instead
optional func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath)
// Data manipulation - reorder / moving support
optional func tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath)
}
the protocol for tableview is this:
protocol UITableViewDelegate : NSObjectProtocol, UIScrollViewDelegate {
// Display customization
optional func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath)
#availability(iOS, introduced=6.0)
optional func tableView(tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int)
#availability(iOS, introduced=6.0)
optional func tableView(tableView: UITableView, willDisplayFooterView view: UIView, forSection section: Int)
#availability(iOS, introduced=6.0)
optional func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath)
#availability(iOS, introduced=6.0)
optional func tableView(tableView: UITableView, didEndDisplayingHeaderView view: UIView, forSection section: Int)
#availability(iOS, introduced=6.0)
optional func tableView(tableView: UITableView, didEndDisplayingFooterView view: UIView, forSection section: Int)
// Variable height support
optional func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
optional func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat
optional func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat
// Use the estimatedHeight methods to quickly calcuate guessed values which will allow for fast load times of the table.
// If these methods are implemented, the above -tableView:heightForXXX calls will be deferred until views are ready to be displayed, so more expensive logic can be placed there.
#availability(iOS, introduced=7.0)
optional func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
#availability(iOS, introduced=7.0)
optional func tableView(tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat
#availability(iOS, introduced=7.0)
optional func tableView(tableView: UITableView, estimatedHeightForFooterInSection section: Int) -> CGFloat
// Section header & footer information. Views are preferred over title should you decide to provide both
optional func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? // custom view for header. will be adjusted to default or specified header height
optional func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? // custom view for footer. will be adjusted to default or specified footer height
// Accessories (disclosures).
optional func tableView(tableView: UITableView, accessoryButtonTappedForRowWithIndexPath indexPath: NSIndexPath)
// Selection
// -tableView:shouldHighlightRowAtIndexPath: is called when a touch comes down on a row.
// Returning NO to that message halts the selection process and does not cause the currently selected row to lose its selected look while the touch is down.
#availability(iOS, introduced=6.0)
optional func tableView(tableView: UITableView, shouldHighlightRowAtIndexPath indexPath: NSIndexPath) -> Bool
#availability(iOS, introduced=6.0)
optional func tableView(tableView: UITableView, didHighlightRowAtIndexPath indexPath: NSIndexPath)
#availability(iOS, introduced=6.0)
optional func tableView(tableView: UITableView, didUnhighlightRowAtIndexPath indexPath: NSIndexPath)
// Called before the user changes the selection. Return a new indexPath, or nil, to change the proposed selection.
optional func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath?
#availability(iOS, introduced=3.0)
optional func tableView(tableView: UITableView, willDeselectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath?
// Called after the user changes the selection.
optional func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
#availability(iOS, introduced=3.0)
optional func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath)
// Editing
// Allows customization of the editingStyle for a particular cell located at 'indexPath'. If not implemented, all editable cells will have UITableViewCellEditingStyleDelete set for them when the table has editing property set to YES.
optional func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle
#availability(iOS, introduced=3.0)
optional func tableView(tableView: UITableView, titleForDeleteConfirmationButtonForRowAtIndexPath indexPath: NSIndexPath) -> String!
#availability(iOS, introduced=8.0)
optional func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]? // supercedes -tableView:titleForDeleteConfirmationButtonForRowAtIndexPath: if return value is non-nil
// Controls whether the background is indented while editing. If not implemented, the default is YES. This is unrelated to the indentation level below. This method only applies to grouped style table views.
optional func tableView(tableView: UITableView, shouldIndentWhileEditingRowAtIndexPath indexPath: NSIndexPath) -> Bool
// The willBegin/didEnd methods are called whenever the 'editing' property is automatically changed by the table (allowing insert/delete/move). This is done by a swipe activating a single row
optional func tableView(tableView: UITableView, willBeginEditingRowAtIndexPath indexPath: NSIndexPath)
optional func tableView(tableView: UITableView, didEndEditingRowAtIndexPath indexPath: NSIndexPath)
// Moving/reordering
// Allows customization of the target row for a particular row as it is being moved/reordered
optional func tableView(tableView: UITableView, targetIndexPathForMoveFromRowAtIndexPath sourceIndexPath: NSIndexPath, toProposedIndexPath proposedDestinationIndexPath: NSIndexPath) -> NSIndexPath
// Indentation
optional func tableView(tableView: UITableView, indentationLevelForRowAtIndexPath indexPath: NSIndexPath) -> Int // return 'depth' of row for hierarchies
// Copy/Paste. All three methods must be implemented by the delegate.
#availability(iOS, introduced=5.0)
optional func tableView(tableView: UITableView, shouldShowMenuForRowAtIndexPath indexPath: NSIndexPath) -> Bool
#availability(iOS, introduced=5.0)
optional func tableView(tableView: UITableView, canPerformAction action: Selector, forRowAtIndexPath indexPath: NSIndexPath, withSender sender: AnyObject) -> Bool
#availability(iOS, introduced=5.0)
optional func tableView(tableView: UITableView, performAction action: Selector, forRowAtIndexPath indexPath: NSIndexPath, withSender sender: AnyObject!)
}
You'll notice that in the protocols above, you have methods tagged as OPTIONAL, you don't need to provide these methods if you don't want to ... HOWEVER, you must provide the OTHER methods at the top of each protocol list that ARE NOT optional. You must use the functions that are REQUIRED in order for your UIViewController to conform to these delegates. IN the above example, the methods I've given you are the only 3 that are required, but you can use all of the methods below if you want to, its your choice, but 3 are required.
Here's more information so that you can learn about this stuff, it's only a little complicated the first time, but once you catch on, it's all pretty simple moving forward. Should you have additional questions, feel free to ask.
https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/WorkingwithProtocols/WorkingwithProtocols.html

Related

iOS Allow UITableViewCell swipe deletion and rearrangeable cells simultaneously

In order to enable rearrangeable (moveable) cells in my UITableView, I must set table.isEditing to true and implement the following delegate methods:
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath)
I also implement the following delegate methods to hide the default table-editing UI:
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
return .none
}
func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
return false
}
I would also like to swipe-delete the cells in this table. I've tried using both the tableView(_:editActionsForRowAt:) approach and the new iOS 11 tableView(_:trailingSwipeActionsConfigurationForRowAt:) but neither work while table.isEditing = true. The only other relevant table delegate method I use is:
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool
which returns true for all cells.
Is there a way to enable both of these UITableView features simultaneously? It looks possible as this is exactly how the table queue in the Apple Music app works:

How to customize delete button in UITableView

I tried to customize my delete button in UITableView. I used a function but it didn't work because Xcode found an error. By the way I'm using custom cells in UITableView.
This is my code:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var myTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
}
func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]? {
let deleteButton = UITableViewRowAction(style: .Default, title: "Delete", handler: { (action, indexPath) in
self.myTableView.dataSource?.tableView?(
self.myTableView,
commitEditingStyle: .Delete,
forRowAtIndexPath: indexPath
)
return
})
deleteButton.backgroundColor = UIColor.blackColor()
return [deleteButton]
}
}
And in this line is error:
func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]? {
the erros is: Objective-C method 'tableView:editActionsForRowAtIndexPath:' provided by method 'tableView(:editActionsForRowAtIndexPath:)' conflicts with optional requirement method 'tableView(:editActionsForRowAtIndexPath:)' in protocol 'UITableViewDelegate'
So I want to change the text and background color. If there is any other method, like using icon and not text please show me, thanks.
The error is indicating that the function you defined with the same method signature as the one defined in UITableViewDelegate has different types that are not compatible. Specifically your return type needs to be [UITableViewRowAction]? instead of [AnyObject]?
Change:
func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]? {
To:
func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]?
Your main problem is that the UITableViewDelegate method is
optional public func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]?
and not
func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]?
I hope this helps you

How do I initialize a table view in edit / re-ordering mode?

I want a table view in my view to always be re-orderable. I cannot figure this out. I have rows in my table view but can't get the re-ordering handles to show up.
For the table view prototype cell, I made sure there was a check in Indentation > "Shows Re-order Controls", but this didn't do anything.
This is how my whole class looks like:
class ViewController: UIViewController {
...
#IBOutlet var currentTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
currentTable.editing = true
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return unitCategories.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
cell.textLabel?.text = "\(unitCategories[indexPath.row])"
return cell
}
/*func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle {
return UITableViewCellEditingStyle.None
}*/
}
Can someone help point me in the right direction?
You need to implement these two methods in order to be able to show the reordering control,
func tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath) {
}
func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
As stated in the header file,
func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool
Allows the reorder accessory view to optionally be shown for a
particular row. By default, the reorder control will be shown only if
the datasource implements:
-tableView:moveRowAtIndexPath:toIndexPath:

Swift Trying to link a tap event on a table view cell to a controller method

I am new to swift and havne't programmed in objective C. So i'm new :-)
trying to do something fairly simple. Link a table view cell click to call a method in the controller like so
http://prntscr.com/4m9kf7
Edit:
i have these methods in my MasterController
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
override func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
I have added breakpoints in all 4 of them.
and when clicking on the cell it doesn't stop in either of them.
See Screen shot:
http://prntscr.com/4m9ql0
You need to implement the didSelectRowAtIndexPath delegate method and put your handling code inside it.
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
//CODE TO BE RUN ON CELL TOUCH
}
For Swift 4:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("row selected: \(indexPath.row)")
}

Conform to protocol in ViewController, in Swift

Trying to conform to UITableViewDataSource and UITableViewDelegate inside a Swift UIViewController subclass.
class GameList: UIViewController {
var aTableView:UITableView = UITableView()
override func viewDidLoad() {
super.viewDidLoad()
aTableView.delegate = self
aTableView.dataSource = self
self.view.addSubview(aTableView)
//errors on both lines for not conforming
}
}
Docs say you should conform on the class line after the : but that's usually where the superclass goes. Another : doesn't work. Using a comma separated list after the superclass also doesn't work
EDIT:
Also must adopt all required methods of each protocol, which I wasn't initially doing.
You use a comma:
class GameList: UIViewController, UITableViewDelegate, UITableViewDataSource {
// ...
}
But realize that the super class must be the first item in the comma separated list.
If you do not adopt all of the required methods of the protocol there will be a compiler error. You must get all of the required methods!
As XCode6-Beta7 releases,
I noticed the protocol method of UITableViewDataSource changed a little bit and sounded the same conform to protocol error which worked fine in beta6.
These are the required methods to be implemented according to the UITableViewDataSource protocol:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { // insert code}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { // insert code
}
You might want to re-check the difference or re-implement the delegate method that you thought you just implement.
You must implement two require methods here:
func tableView(tableView:UITableView!, numberOfRowsInSection section:Int) -> Int {
return 10
}
func tableView(tableView:UITableView!, cellForRowAtIndexPath indexPath:NSIndexPath!) -> UITableViewCell! {
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "MyTestCell")
cell.text = "Row #\(indexPath.row)"
cell.detailTextLabel.text = "Subtitle #\(indexPath.row)"
return cell
}
Also, it is important to copy all the non optional functions from the Delegate class. Cmd + Click on the UITableViewDatasource
and copy those two definitions as is.
For me in beta7, the UITableViewDatasource has
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
My implementation:
var items = ["Apple", "Pear", "Banana"]
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "Default")
cell.textLabel?.text = items[indexPath.row]
cell.detailTextLabel?.text = "Test"
return cell
}
Usee These methods:
There is change in Data source methods-
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
protocol UITableViewDataSource : NSObjectProtocol {
****func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
// Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier:
// Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls)
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell****
optional func numberOfSectionsInTableView(tableView: UITableView) -> Int // Default is 1 if not implemented
optional func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? // fixed font style. use custom view (UILabel) if you want something different
optional func tableView(tableView: UITableView, titleForFooterInSection section: Int) -> String?
// Editing
// Individual rows can opt out of having the -editing property set for them. If not implemented, all rows are assumed to be editable.
optional func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool
// Moving/reordering
// Allows the reorder accessory view to optionally be shown for a particular row. By default, the reorder control will be shown only if the datasource implements -tableView:moveRowAtIndexPath:toIndexPath:
optional func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool
// Index
optional func sectionIndexTitlesForTableView(tableView: UITableView) -> [AnyObject]! // return list of section titles to display in section index view (e.g. "ABCD...Z#")
optional func tableView(tableView: UITableView, sectionForSectionIndexTitle title: String, atIndex index: Int) -> Int // tell table which section corresponds to section title/index (e.g. "B",1))
// Data manipulation - insert and delete support
// After a row has the minus or plus button invoked (based on the UITableViewCellEditingStyle for the cell), the dataSource must commit the change
// Not called for edit actions using UITableViewRowAction - the action's handler will be invoked instead
optional func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath)
// Data manipulation - reorder / moving support
optional func tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath)
}
Ur code will works!!
This question is already answered but just want to make things a bit more Swifty.
Instead of writing protocols in UITableViewDelegate, UITableViewDataSource you can divide them using extensions this will help in organising the code. Adding protocol conformance is described in this page
for the above question, this can be confirmed to protocol using extension:
class GameList: UIViewController {
var aTableView:UITableView = UITableView()
override func viewDidLoad() {
super.viewDidLoad()
aTableView.delegate = self
aTableView.dataSource = self
self.view.addSubview(aTableView)
}
}
extension GameList: UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return list.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath)
return cell
}
}
extension GameList: UITableViewDelegate{
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("Row Clicked at \(indexPath.row)")
}
}

Resources