收到大量节时,应用程序的UI会冻结

时间:2017-08-23 05:53:51

标签: ios objective-c sockets xmppframework

我正在使用Robbiehanson的XMPPFramework开发一个聊天应用程序,当我的应用程序收到大量节,应用程序的UI冻结时,这就是我正在制作流的方式。

当框架尝试针对收到的邮件发送收据或者流管理器尝试针对收到的节发送确认时,应用程序的UI大多会冻结。

这就是我设置流的方式。

//流设置

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];
}

//设置流管理器

- (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];
}
}

//启用自动消息传递

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

我使用的后台队列是:

dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);

我该如何解决这个问题?

3 个答案:

答案 0 :(得分:1)

当您从Framework中调用一些触发UI更新的数据时,您正在执行哪个线程?

它需要是线程1,因为UIKit只能在主线程上运行。如果它不是主线程,则必须dispatch_async(dispatch_get_main_queue(),^ block());并从块中调用UIKit(也称为所有UI调用)。我很难学会这一点,是的,UI变得非常缓慢,表现得非常奇怪。

答案 1 :(得分:0)

如果UI冻结了它的明确含义,那么你的一些工作就是主线程。您必须查找在主线程中运行的任务。并在后台线程中编写该块代码,并在完成任务时切换到主线程以更新UI。

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

答案 2 :(得分:0)

首先,我会检查冻结期间主线程上发生了什么。

  1. 通过Xcode在调试会话中运行应用程序。
  2. 当用户界面冻结时,请点击调试工具栏中的“暂停”按钮。
  3. 检查主线程/(主队列线程)的调用堆栈。您应该看到导致冻结的函数以及调用它的人。
  4. 即使您确信您的代码在正确的队列/线程上运行,您正在使用的库可能会显式调度到主队列。这件事发生在我之前。