Ios 使用dataTask在func上快速显示和隐藏活动指示器
我有一个函数,可以进行调用并等待服务器的响应。我想在请求之前显示活动指示器,并在同一函数的回答之后隐藏它。为什么?避免代码重复。我将在其他操作中调用服务器 它现在的工作方式是:手动调用登录按钮上的开始和停止动画 为了测试指示器,我在服务器上添加了睡眠 问题:如何显示/隐藏每次呼叫服务器的指示灯? 登录视图上的按钮: 内部函数makeRequestPostIos 使用dataTask在func上快速显示和隐藏活动指示器,ios,swift,task,Ios,Swift,Task,我有一个函数,可以进行调用并等待服务器的响应。我想在请求之前显示活动指示器,并在同一函数的回答之后隐藏它。为什么?避免代码重复。我将在其他操作中调用服务器 它现在的工作方式是:手动调用登录按钮上的开始和停止动画 为了测试指示器,我在服务器上添加了睡眠 问题:如何显示/隐藏每次呼叫服务器的指示灯? 登录视图上的按钮: 内部函数makeRequestPost func makeRequestPost<T>(endpoint: String, req
func makeRequestPost<T>(endpoint: String,
requestType: String = "GET",
requestBody: Data,
activityIndicator: CustomActivityIndicator? = nil,
completionHandler: @escaping (ApiContainer<T>?, Error?) -> ()) {
activityIndicator?.start() .......
func makeRequestPost(端点:字符串,
requestType:String=“GET”,
请求主体:数据,
activityIndicator:CustomActivityIndicator?=零,
completionHandler:@正在转义(ApiContainer?,错误?->()){
活动指示灯?.start()。。。。。。。
在操作按钮上:
let loading = CustomActivityIndicator(viewContainer: self.view, startAnimate: true)
makeRequestPost(endpoint: "http://blog.local:4711/api/login",
requestType: "POST",
requestBody: jsonData,
activityIndicator: loading,
completionHandler: { (response : ApiContainer<Login>?, error : Error?) in
let load=CustomActivityIndicator(viewContainer:self.view,startAnimate:true)
makeRequestPost(端点:http://blog.local:4711/api/login",
请求类型:“POST”,
请求主体:jsonData,
活动指示器:加载,
completionHandler:{(响应:ApiContainer?,错误:error?)位于
我假设您的makeRequest函数位于单独的服务类中,因此基本上您可以在onRequestComplete块上添加常规onrequeststart,并在调用postmakeRequest时执行它们
请看一看,也许你会发现它很有用
编辑:
声明全局函数结束并将其暴露给整个模块是一个坏主意。最终可能会有数千个辅助函数,项目的复杂性将成倍增加。尽管fews仍然保护过程性方法(当函数以这种方式声明时),社区在80年代后期从它演变而来。所以我强烈建议您声明类来包装所有与网络相关的函数(NetworkClient/Service/Manager等)
回到您的问题:您可以将活动指示器作为参数:
func makeRequestPost<T>(endpoint: String,
requestType: String = "GET",
requestBody: Data,
activityIndicator: CustomActivityIndicator?,
completionHandler: @escaping (ApiContainer<T>?, Error?) -> ())
func makeRequestPost(端点:字符串,
requestType:String=“GET”,
请求主体:数据,
activityIndicator:CustomActivityIndicator?,
completionHandler:@正在转义(ApiContainer?,错误?->())
因此,您可以在函数中启动并完成它,而不是在任何时候使用函数复制/粘贴代码。在阅读了一些教程后,我最终回答了自己的问题 我做了什么? 1) 我创建了一个类:ViewControllerUtils 2) 在func makeRequestPost上,我添加了一个新的参数(视图),并调用启动和停止加载视图
func makeRequestPost<T>(endpoint: String,
requestType: String = "GET",
requestBody: Data,
view: UIView,
completionHandler: @escaping (ApiContainer<T>?, Error?) -> ()) {
ViewControllerUtils().showActivityIndicator(uiView: view)
guard let url = URL(string: endpoint) else {
print("Error: cannot create URL")
let error = BackendError.urlError(reason: "Could not create URL")
completionHandler(nil, error)
return
}
var urlRequest = URLRequest(url: url)
let session = URLSession.shared
urlRequest.httpMethod = "POST"
urlRequest.httpBody = requestBody
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
urlRequest.addValue("application/json", forHTTPHeaderField: "Accept")
let task = session.dataTask(with: urlRequest, completionHandler: {
(data, response, error) in
ViewControllerUtils().hideActivityIndicator(uiView: view)
guard let responseData = data else {
print("Error: did not receive data")
completionHandler(nil, error)
return
}
guard error == nil else {
completionHandler(nil, error!)
return
}
do {
let response = try JSONDecoder().decode(ApiContainer<T>.self, from: responseData)
completionHandler(response, nil)
}
catch {
print("error trying to convert data to JSON")
print(error)
completionHandler(nil, error)
}
})
task.resume()
}
func makeRequestPost(端点:字符串,
requestType:String=“GET”,
请求主体:数据,
视图:UIView,
completionHandler:@正在转义(ApiContainer?,错误?->()){
ViewControllerUtils().showActivityIndicator(uiView:view)
guard let url=url(字符串:端点)else{
打印(“错误:无法创建URL”)
let error=BackendError.urlError(原因:“无法创建URL”)
completionHandler(无,错误)
返回
}
var urlRequest=urlRequest(url:url)
让session=URLSession.shared
urlRequest.httpMethod=“POST”
urlRequest.httpBody=requestBody
urlRequest.addValue(“应用程序/json”,forHTTPHeaderField:“内容类型”)
URL请求.addValue(“应用程序/json”,用于HttpHeaderField:“接受”)
让task=session.dataTask(带:urlRequest,completionHandler:{
(数据、响应、错误)
ViewControllerUtils().hideActivityIndicator(uiView:view)
guard let responseData=其他数据{
打印(“错误:未收到数据”)
completionHandler(无,错误)
返回
}
保护错误==nil else{
completionHandler(无,错误!)
返回
}
做{
让response=try JSONDecoder().decode(ApiContainer.self,from:responseData)
completionHandler(响应,无)
}
抓住{
打印(“尝试将数据转换为JSON时出错”)
打印(错误)
completionHandler(无,错误)
}
})
task.resume()
}
它还不是一个类。我在我的问题中添加了helper函数。尽量避免将函数保留为全局函数。在这种情况下,您可以创建可以发送请求的NetwrokService,并为其提供requestDidSent/DidComplete块,如果有,您在整个应用程序中使用相同的活动指示器。
func makeRequestPost<T>(endpoint: String,
requestType: String = "GET",
requestBody: Data,
activityIndicator: CustomActivityIndicator? = nil,
completionHandler: @escaping (ApiContainer<T>?, Error?) -> ()) {
activityIndicator?.start() .......
let loading = CustomActivityIndicator(viewContainer: self.view, startAnimate: true)
makeRequestPost(endpoint: "http://blog.local:4711/api/login",
requestType: "POST",
requestBody: jsonData,
activityIndicator: loading,
completionHandler: { (response : ApiContainer<Login>?, error : Error?) in
func makeRequestPost<T>(endpoint: String,
requestType: String = "GET",
requestBody: Data,
activityIndicator: CustomActivityIndicator?,
completionHandler: @escaping (ApiContainer<T>?, Error?) -> ())
class ViewControllerUtils {
var container: UIView = UIView()
var loadingView: UIView = UIView()
var activityIndicator: UIActivityIndicatorView = UIActivityIndicatorView()
/*
Show customized activity indicator,
actually add activity indicator to passing view
@param uiView - add activity indicator to this view
*/
func showActivityIndicator(uiView: UIView) {
self.container.frame = uiView.frame
self.container.center = uiView.center
self.container.backgroundColor = UIColor.white
self.container.alpha = 0.7
self.container.tag = 789456123
loadingView.frame = CGRect(x:0, y:0, width:80, height:80)
loadingView.center = uiView.center
loadingView.backgroundColor = UIColor.black
loadingView.clipsToBounds = true
loadingView.layer.cornerRadius = 10
activityIndicator.frame = CGRect(x:0.0, y:0.0, width:40.0, height:40.0);
activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.whiteLarge
activityIndicator.center = CGPoint(x:loadingView.frame.size.width / 2, y:loadingView.frame.size.height / 2);
DispatchQueue.main.async {
self.loadingView.addSubview(self.activityIndicator)
self.container.addSubview(self.loadingView)
uiView.addSubview(self.container)
self.activityIndicator.startAnimating()
}
}
/*
Hide activity indicator
Actually remove activity indicator from its super view
@param uiView - remove activity indicator from this view
*/
func hideActivityIndicator(uiView: UIView) {
DispatchQueue.main.async {
if let viewWithTag = uiView.viewWithTag(789456123) {
viewWithTag.removeFromSuperview()
}
else {
return
}
}
}
/*
Define UIColor from hex value
@param rgbValue - hex color value
@param alpha - transparency level
*/
func UIColorFromHex(rgbValue:UInt32, alpha:Double=1.0)->UIColor {
let red = CGFloat((rgbValue & 0xFF0000) >> 16)/256.0
let green = CGFloat((rgbValue & 0xFF00) >> 8)/256.0
let blue = CGFloat(rgbValue & 0xFF)/256.0
return UIColor(red:red, green:green, blue:blue, alpha:CGFloat(alpha))
}
}
func makeRequestPost<T>(endpoint: String,
requestType: String = "GET",
requestBody: Data,
view: UIView,
completionHandler: @escaping (ApiContainer<T>?, Error?) -> ()) {
ViewControllerUtils().showActivityIndicator(uiView: view)
guard let url = URL(string: endpoint) else {
print("Error: cannot create URL")
let error = BackendError.urlError(reason: "Could not create URL")
completionHandler(nil, error)
return
}
var urlRequest = URLRequest(url: url)
let session = URLSession.shared
urlRequest.httpMethod = "POST"
urlRequest.httpBody = requestBody
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
urlRequest.addValue("application/json", forHTTPHeaderField: "Accept")
let task = session.dataTask(with: urlRequest, completionHandler: {
(data, response, error) in
ViewControllerUtils().hideActivityIndicator(uiView: view)
guard let responseData = data else {
print("Error: did not receive data")
completionHandler(nil, error)
return
}
guard error == nil else {
completionHandler(nil, error!)
return
}
do {
let response = try JSONDecoder().decode(ApiContainer<T>.self, from: responseData)
completionHandler(response, nil)
}
catch {
print("error trying to convert data to JSON")
print(error)
completionHandler(nil, error)
}
})
task.resume()
}