Get indexPath in button action

How can I find the playlist index and do the same as in func prepare but in addButtonTapped(_ sender: Any)

I mean, there is no indexPath of the created playlist.

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    
    if let cell = sender as? UICollectionViewCell, let indexPath = self.collectionView.indexPath(for: cell) {
        
        let playlist = PlaylistController.shared.playlists[indexPath.item]
        let ChannelVC = segue.destination as? ChannelsViewController
        ChannelVC?.playlist = playlist
    }
}





// MARK: Actions
@IBAction func addButtonTapped(_ sender: Any) {

    let createPlaylist = UIAlertController(title: "", message: "", preferredStyle: .alert)
    
    createPlaylist.addTextField()
    
    createPlaylist.addTextField()
    
    createPlaylist.addAction( UIAlertAction(title: "Save", style: .default) {
        action in
        
        guard let playlistName = createPlaylist.textFields![0].text,
            let playlistURL = createPlaylist.textFields![1].text, !playlistName.isEmpty && !playlistURL.isEmpty else { return }
        
        
        self.networkService.playlist(from: URL (string: playlistURL)!) { result in
            switch result {
            case .value(let Playlist):
                DispatchQueue.main.async {
                    
                    PlaylistController.shared.create(playlistWithName: playlistName, url: URL (string: playlistURL)!, content: Playlist.content)
                    
                    let playlist = PlaylistController.shared.playlists[IndexPath]
                    
                    extractChannelsFromString( Playlist.content, #PLAYLIST ID WHERE TO BE SAVED[indepath] )
                    
                      //  self.collectionView.reloadData()
        
                }
            case .error(let error):
                print(error) //TODO:
            }
        }
                    self.collectionView.reloadData()
    })
    
    createPlaylist.addAction(UIAlertAction(title: "Cancel",  style: .cancel))
    
    present(createPlaylist, animated: true, completion: nil)
}

This is really a UIKit question, not a Swift question, so it would be more appropriate for Stack Overflow.

Anyway, I assume you're using addButtonTapped as the action of a UIButton, and that the button is in a cell in a table view. The sender argument is the button object. You can walk up the view hierarchy to find the containing table view cell and the containing table view. Then you can ask the table view for the cell's index path.

Start with this handy extension:

extension UIView {
    func nearestAncestor<T>(ofType type: T.Type) -> T? {
        if let me = self as? T { return me }
        return superview?.nearestAncestor(ofType: type)
    }
}

Then use it to find the index path like this:

func addButtonTapped(_ sender: Any) {
    guard
        let button = sender as? UIView,
        let cell = button.nearestAncestor(ofType: UITableViewCell.self),
        let tableView = cell.nearestAncestor(ofType: UITableView.self),
        let indexPath = tableView.indexPath(for: cell)
        else { return }

    // Your code here...
}

Note that if you already have a property that references the table view, you can just use that instead of finding the table view with nearestAncestor(ofType:).

3 Likes

I will keep in mind to not post about UIKit in the future.

Thanks for opening my eyes, I found the solution I needed after I saw your post.

@IBAction func BtnClick(_ sender : UIButton) {

     print(sender.tag) //here you will get the IndexPath

}

Super. That solved a problem for me too. Thanks. :)