简体   繁体   中英

Make async request in table view delegate method

So I have a table view with a list of items. Only users with the highest permission levels can delete these items. When the user swipes a table view cell with the intent to delete it editActionsOptionsForRowAt is called. I check the user permission in this delegate method by making a server call (asynchronous). The problem is that I need this info fast, plus this code doesn't compile because I can't return the delete item in a closure. What can I do to fix this?

func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> [SwipeAction]? {
    // ...

    APIContentService.getUserPermission(projectKey: projectKey, stepKey: stepKey, userKey: userKey) { (accessLevel) in
        if let level = accessLevel {
            if level == .admin {
                return [delete] // show delete item – COMPILER ERROR, can't return this in a closure
            } else {
                // 
                return [] // don't show anything
            }
        }
    }

    // ...
}

In short, don't try. The delegate method needs to return immediately with a valid result. You could do tricks with semaphores or dispatch groups to block the delegate method from returning until you get a result from the server but that is a really bad idea.

The proper solution is to get the permission once in viewDidLoad . Save the result in a property. Then reference that property in your delegate method.

The user's permission is not going to change each time the table view wants to know the edit actions for each row while the user is on this screen. So you should only need to get the permission once each time the user views this screen.

Calling API call in table view delegate for delete action is not seems like a good design. What happens if the API request fails or take a long time to process due to some reasons.

It will be great if you can call API in advance and then just compare the values in delete action. It will be more interactive to the user.

If you can't call API in advance then show an Activity Indicator when API calls and hide it in its response. It will help you to handle all scenarios

As you noticed yourself you cannot return something from an asynchronous task.

You have to get the user permission in viewDidLoad and save the state in a property.

Then return the edit action(s) depending on that property.

I would even implement canEditRowAt and return true or false depending on that property.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM