Question

I am writing an IOS chat app. I have a tableview where each cell contains a textbox, upon loading each cell I subscribe to a chat channel on pubnub.com. I have an observable in the viewdidLoad watching for incoming messages. The object receieved from the observable contains the channel name and the message text and date. I want to display messages to their appropriate cells. I'm not sure where to capture a fully loaded cell when its in view and subscribe to the channel. Then in the observable how do I compare the channel name to the cell currently in view on the screen? I tried the isVisible but I'm getting more than whats visible on the screen. The thing is I want to only show messages to cells that are currenty in view, kind of how vine starts to playa video when the user has stopped on that cell even if they dont click it..

See code below

- (void)viewDidLoad
{
    [super viewDidLoad];

    appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
    self.messages = [NSMutableDictionary dictionary];
    self.configuration = [PNConfiguration defaultConfiguration];

    [self load_DEMO_DATA];
    [self setClient];
    [self connectToServer];

    //Observable
    [[PNObservationCenter defaultCenter] addMessageReceiveObserver:self
                                                         withBlock:^(PNMessage *message) {

        NSDateFormatter *dateFormatter = [NSDateFormatter new];
        dateFormatter.dateFormat = @"HH:mm:ss MM/dd/yy";
        PNChannel *channel = message.channel;

        NSString *messages = [self.messages valueForKey:channel.name];
        if (messages == nil) {messages = @"";}
        messages = [messages stringByAppendingFormat:@"<%@> %@\n",[dateFormatter stringFromDate:message.receiveDate.date],message.message];

        //Get TextBox & Set Caption                                                                                    
        UITextView *caption = (UITextView *)[[(UITableViewCell *)[(UITableView    *)self.tableView cellForRowAtIndexPath:CurrentIndexPath] contentView] viewWithTag:105];

        caption.text = [NSString stringWithFormat:@"%@%@", caption.text, messages];
        [caption scrollRangeToVisible:NSMakeRange([caption.text length], 0)];                         
    }];

}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"TimelinePostCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell==nil)
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];

    // Configure the cell...
    NSDictionary *post = [posts objectAtIndex:indexPath.item];
    NSDictionary *user = [post objectForKey:@"user"];

    //Set Current Channel
    self.currentChannel = [PNChannel channelWithName:[post objectForKey:@"channelName"]      shouldObservePresence:YES];

    //Subscribe to Chat
    [self subscribeToChannel:self.currentChannel.name];
    self.currentPost = post;

    //Get Channel History
    [self ChannelHistory];

    return cell;
}
Was it helpful?

Solution

Well, first of all, -tableView:cellForRowAtIndexPath: shouldn't be used to initiate any time consuming operations. To keep high performance, you should return prepared UITableViewCell from that method less then in 160ms or you will see "lag". This method will be called few times right after table has been shown (as many as you have cells with values).

You should use –scrollViewDidEndDragging:willDecelerate: (with decelerate NO) and –scrollViewDidEndDecelerating: as appropriate place and time when you should initiate subscriptions to the channel and any other manipulation with PubNub client.

You can subscribe on all channels at once - it will be less network overhead than subscribing for every single channel one-by-one. If you want to preserve resources and keep pricing low by keeping client subscribed on few channels, than you should use same methods to unsubscribe from previous channels (same as were suggested to detect current cell and store current channel and so on).

Also just suggestion about how you feed cell with model: move model processing inside custom cell class (there is no reason for controller to know something about structure of cell's views and which data should be shown there).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top