2017-08-23 6 views
1

Je développe une application de chat en utilisant XMPPFramework de Robbiehanson, quand mon application reçoit beaucoup de strophes, l'interface utilisateur de l'application se bloque, c'est comme ça que je crée mon flux.L'interface utilisateur de l'application se bloque lorsque plusieurs strophes sont reçues

L'interface utilisateur de l'application se bloque principalement lorsque l'infrastructure tente d'envoyer des réceptions par rapport à un message reçu ou lorsque le gestionnaire de flux tente d'envoyer des accusés de réception à une section reçue.

Voici comment je configure mon flux.

// Stream Setup

if (!self.xmppStream || ![self.xmppStream isConnected]) { 
    self.xmppStream = [[XMPPStream alloc] init]; 
    [self.xmppStream setHostName:kGetChatServerURLString]; 
    // [self.xmppStream setHostPort:kBPChatServerPort]; 

    [self.xmppStream setHostPort:kBPChatServerPort]; 
    [self.xmppStream setStartTLSPolicy:XMPPStreamStartTLSPolicyAllowed]; 
    self.xmppReconnect = [ [XMPPReconnect alloc] init]; 
    [self.xmppReconnect setAutoReconnect:YES]; 

    self.xmppRosterMemStorage = [[XMPPRosterMemoryStorage alloc] init]; 
    self.xmppRoster = [[XMPPRoster alloc] initWithRosterStorage:self.xmppRosterMemStorage dispatchQueue:dispatch_get_main_queue()]; 

    self.xmppRoster.autoAcceptKnownPresenceSubscriptionRequests = true; 
    self.xmppRoster.autoFetchRoster = true; 
    [self.xmppRoster activate:self.xmppStream]; 

    self.xmppMUC = [[XMPPMUC alloc] initWithDispatchQueue:_backgroundQueue]; 
    [self.xmppMUC activate:self.xmppStream]; 

    // To enable socket in the background. 
    [self.xmppStream setEnableBackgroundingOnSocket:YES]; 

    // Moved the function to here from DidConnect to fix multiple delivery reports sending issue after reconnect. 
    [self setupAutoSendDeliveryReceipts]; 

    XMPPMessageCarbons *xmppMessageCarbon = [[XMPPMessageCarbons alloc] initWithDispatchQueue:_backgroundQueue]; 

    [xmppMessageCarbon activate:self.xmppStream]; 
    [xmppMessageCarbon setAutoEnableMessageCarbons:YES]; 

    //XEP-0191: Blocking Command 
    self.xmppBlocking = [[XMPPBlocking alloc] initWithDispatchQueue:_backgroundQueue]; 
    [self.xmppBlocking activate:self.xmppStream]; 

    [self.xmppStream addDelegate:self delegateQueue:_backgroundQueue]; 
    [self.xmppReconnect addDelegate:self delegateQueue:_backgroundQueue]; 
    [self.xmppRoster addDelegate:self delegateQueue:dispatch_get_main_queue()]; 
    [self.xmppMUC addDelegate:self delegateQueue:_backgroundQueue]; 
    [self.xmppBlocking addDelegate:self delegateQueue:_backgroundQueue]; 

    [[BPCXMPPvCardStorageManager sharedInstance] activateWithStream:self.xmppStream]; 
    [[BPCChatRoomsManager sharedManager] activateWithStream:self.xmppStream]; 
} 

// Stream Setup Gestionnaire

- (void)setupStreamManagement { 

if (kBPCTempEnableStreamManagement) { 

    //Intialize with XMPPStreamManagementMemoryStorage 
    XMPPStreamManagementMemoryStorage *xmppSMMS = [[XMPPStreamManagementMemoryStorage alloc] init]; 
    self.xmppStreamManagement = [[XMPPStreamManagement alloc] initWithStorage:xmppSMMS dispatchQueue:_backgroundQueue]; 

    //Activate with stream 
    [self.xmppStreamManagement activate:self.xmppStream]; 
    self.xmppStreamManagement.autoResume = YES; 
    [self.xmppStreamManagement enableStreamManagementWithResumption:YES maxTimeout:0]; 
    [self.xmppStreamManagement requestAck]; 
    [self.xmppStreamManagement sendAck]; 
    [self.xmppStreamManagement automaticallySendAcksAfterStanzaCount:1 orTimeout:0]; 
} 
} 

// Activer les livraisons automatique de messages

XMPPMessageDeliveryReceipts *xmppMessageDeliveryReceipts = [[XMPPMessageDeliveryReceipts alloc] initWithDispatchQueue:dispatch_queue_create("messageDeliverReceiptsQueue", DISPATCH_QUEUE_CONCURRENT)]; 
xmppMessageDeliveryReceipts.autoSendMessageDeliveryReceipts = YES; 
xmppMessageDeliveryReceipts.autoSendMessageDeliveryRequests = YES; 
[xmppMessageDeliveryReceipts activate:self.xmppStream]; 

La file d'attente d'arrière-plan que j'utilise est:

dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0); 

Comment puis-je résoudre ce problème?

+0

'sendAck' n'est pas nécessaire si' automaticSendAcksAfterStanzaCount' est utilisé. –

Répondre

0

Si l'interface utilisateur gèle, sa signification est clairement votre travail se passe sur le fil principal. Vous devez rechercher votre tâche qui s'exécute dans le thread principal. Et écrivez ce morceau de code dans le thread d'arrière-plan et quand il termine sa tâche, passez au thread principal pour mettre à jour l'interface utilisateur.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){ 
//Background Thread 
dispatch_async(dispatch_get_main_queue(), ^(void){ 
    //Run UI Updates 
}); 
}); 
+0

Rien n'est fait sur la file d'attente principale, lorsque le framework tente d'envoyer des strophes ou de recevoir, il gèle l'interface utilisateur. –

+0

@ZeeshanAnjum Qu'est-ce qui vous fait rejeter si facilement? Habituellement, une interface utilisateur gelée est l'indication d'un travail excessif dans la file d'attente principale. Je ne connais pas le XMPPFramework, mais sûrement à un certain moment vous remettez des données à votre thread principal pour le traitement de l'interface utilisateur, non? Je peux même vous voir définir une file d'attente de délégué comme la file d'attente principale dans votre code ci-dessus. Je ne peux malheureusement pas vous donner une réponse, et je peux voir que celle-ci ne vous aide pas beaucoup, mais simplement nier l'évidence ne vous aidera pas non plus.Expliquez au moins ce que vous pensez que même * peut * geler l'interface utilisateur à côté d'une file principale bloquée ... – Gero

+0

C'est ce que je n'ai pas compris, toutes mes opérations db sont effectuées sur un contexte d'arrière-plan qui ne peut évidemment pas bloquer l'interface utilisateur. Je crois que les ressources sont épuisées, à cause de quoi l'assurance-chômage se fige? –

0

D'abord je vérifierais ce qui se passe sur le fil principal pendant le gel.

  1. Exécutez l'application dans la session de débogage via Xcode.
  2. Lorsque l'interface utilisateur se fige, cliquez sur le bouton "pause" dans la barre d'outils de débogage.
  3. Vérifiez la pile d'appels du thread principal/(thread de file d'attente principal). Vous devriez voir quelle fonction provoque le gel et qui l'a appelé.

Même si vous êtes sûr que votre code s'exécute sur les files d'attente/threads appropriés, il est possible que la bibliothèque que vous utilisez distribue explicitement dans la file d'attente principale. Cela m'est arrivé avant.

0

Lorsque vous êtes rappelé depuis le Framework avec des données qui déclenchent une mise à jour de l'interface utilisateur, dans quel thread travaillez-vous?

Il doit être Thread 1 car UIKit ne peut s'exécuter que sur le thread principal. Si ce n'est pas le thread principal, vous devez envoyer dispatch_async (dispatch_get_main_queue(),^block()); et appelez UIKit (alias tous les appels UI) du bloc. J'ai appris celui-ci à la dure, et oui, l'interface utilisateur devient très lente et se comporte très bizarre.