В моем проекте есть требование, где пользователь загружает изображение на сервер, а загруженные изображения редактируются в бэкэнде, а пользователь получает новое изображение . Поскольку редактирование изображения занимает много времени, мы используем сокетное соединение, чтобы узнать, когда редактирование завершится.
Итак, мой текущий подход заключается в том, что, как только загрузка изображения завершится, я создаю канал с помощью клиентского кабеля Action и когда я получаю законченное изображение с сервера, я должен получить ответ на метод канала onReceive
.
Но, делая это сейчас, я сталкиваюсь с двумя проблемами, первая главная проблема заключается в том, что обратный вызов onReceive иногда работает, а иногда нет. Второй , я всегда получаю неудачный ответ в обратном вызове. Это не проблема сервера, так как мы делаем то же самое в Android, и она отлично работает там. Любая помощь приветствуется. Ниже мой ActionCableManager
класс.
class ActionCableManager {
var client: ActionCableClient?
var channel: Channel?
let url = "wss://mysite.com/cable"
let ChannelIdentifier = "MyChannel"
init(){
if self.client == nil{
setupActionCableClient()
}
}
func establishConnection() {
guard let client = client else {
return
}
client.connect()
}
func closeConnection() {
self.client?.disconnect()
}
/*===============================================================================*/
// MARK: - Setup connection
/*===============================================================================*/
func setupActionCableClient(){
guard let urlString = URL(string: url) else {return}
let headers = ["Origin":"Mysite address"]
self.client = ActionCableClient(url: urlString, headers:headers)
self.client?.willConnect = {
print("Will Connect")
}
self.client?.onConnected = {
print("Connected to \(String(describing: self.client?.url))")
}
self.client?.onDisconnected = {(error: ConnectionError?) in
print("Disconnected with error: \(String(describing: error))")
}
self.client?.willReconnect = {
print("Reconnecting to \(String(describing: self.client?.url))")
return true
}
}
func createChannel(_ roomId:String){
let room_identifier = ["room_id" : roomId]
self.channel = client?.create(ChannelIdentifier, identifier: room_identifier, autoSubscribe: true, bufferActions: true)
self.channel?.onSubscribed = {
print("Subscribed to \(self.ChannelIdentifier) with room Id=\(roomId)")
}
self.channel?.onReceive = {(data: Any?, error: Error?) in
print("****** channel on receive data = \(String(describing: data))")
if let error = error {
print(error.localizedDescription)
return
}
}
}
}
И вот как я это использую на своем MainViewController
:
let actionCableManager = ActionCableManager()
override func viewDidLoad() {
super.viewDidLoad()
actionCableManager.establishConnection()
}
//To upload image to server and register Action cable channel
func uploadImage(){
//Some code to upload the image
//check for image upload status
if let httpResponse = response as? HTTPURLResponse {
//Image upload was successful
if httpResponse.statusCode == 200{
DispatchQueue.main.async {
self.actionCableManager.createChannel(self.roomId)
}
}
}
}
Ниже приведен фрагмент кода Android, который работает:
// 1. Setup
URI uri = new URI("wss://mysite.com/cable");
Consumer.Options options=new Consumer.Options();
options.headers = new ArrayMap<>();
options.headers.put("Origin","My Site address");
Consumer consumer = ActionCable.createConsumer(uri,options);
// 2. Create subscription
Channel appearanceChannel = new Channel("MyChannel");
appearanceChannel.addParam("room_id",randomString);
Subscription subscription = consumer.getSubscriptions().create(appearanceChannel);
subscription
.onConnected(new Subscription.ConnectedCallback() {
@Override
public void call() {
// Called when the subscription has been successfully completed
}
}).onRejected(new Subscription.RejectedCallback() {
@Override
public void call() {
// Called when the subscription is rejected by the server
}
}).onReceived(new Subscription.ReceivedCallback() {
@Override
public void call(JsonElement data) {
**//Gets a success response here with transformed image URL**
}
}).onDisconnected(new Subscription.DisconnectedCallback() {
@Override
public void call() {
// Called when the subscription has been closed
}
}).onFailed(new Subscription.FailedCallback() {
@Override
public void call(ActionCableException e) {
// Called when the subscription encounters any error
}
});
// 3. Establish connection
consumer.connect();
PS: я использую эту библиотеку github для ActionCableClient