1

I have a a series of UITableViewCells that update every second or so.

First Attempt: In order to perform such an update, I call self.tableView.reloadData() to reload all the cell contents.

Second Attempt: I have tried just refreshing the sections with a UITableViewAnimation.None but that makes the section header disappear and then reappear every second.

In the first attempt, I get a "flickering" effect because the views are constantly being refreshed. I want it so that the flickering effect goes away. In the second attempt, as said above, the section header disappear and then reappear every second.

In my code, I want to constantly update the headerView.headerTimeLeft.text label.

Here are my attempts:

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)
    self.refreshTimer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "refreshView:", userInfo: nil, repeats: true)
}

func refreshView(timer: NSTimer){
    //Attempt 2
    var visibleRows:NSArray = self.tableView.indexPathsForVisibleRows()!
    var sections = NSMutableIndexSet()
    for indexPath in visibleRows{
        sections.addIndex(indexPath.section)
    }

    //Attempt 1 was simply to reload the Data
    //self.tableView.reloadData()
    //Attempt 2 was to reload the sections
    self.tableView.reloadSections(sections, withRowAnimation: UITableViewRowAnimation.None)
}

func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    //Show section header cell with name of event creator
    var cellIdentifier = "SectionHeaderCell"
    var headerView = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as! SectionHeaderCell

    headerView.backgroundColor = UIColor.whiteColor()
    headerView.creator.text = self.events[section].eventCreator()

    var fromDate = self.events[section].fromDate()! + " " + self.events[section].fromTime()!

    var dateFormatter = NSDateFormatter()

    dateFormatter.dateFormat = "MM/dd/yy hh:mm a z"
    var eventStartDate = dateFormatter.dateFromString(fromDate)?.timeIntervalSince1970

    var timeUntilEnd = eventStartDate! - NSDate().timeIntervalSince1970

    //Display the time left
    var seconds = timeUntilEnd % 60
    var minutes = (timeUntilEnd / 60) % 60
    var hours = timeUntilEnd / 3600
    headerView.headerTimeLeft.text = NSString(format: "%dh %dm %ds", Int(hours), Int(minutes), Int(seconds)) as String
    return headerView
}
user1871869
  • 3,317
  • 13
  • 56
  • 106
  • Have you ever heard about difference between constant "let" and variable "var"? – Leo Dabus May 14 '15 at 22:05
  • let timeUntilEnd = eventStartDate!.timeIntervalSinceNow – Leo Dabus May 14 '15 at 22:06
  • NSString(format:) as String ?? why not just String(format:) ? – Leo Dabus May 14 '15 at 22:08
  • 1
    @LeonardoSavioDabus Thank you for letting me know of these fixes. I'll change them accordingly in my code. – user1871869 May 14 '15 at 22:11
  • @LeonardoSavioDabus do you have any suggestions on how to fix the question at hand? – user1871869 May 14 '15 at 22:41
  • If you reproduce the behavior in a sample project and post the link here I can take a look – Leo Dabus May 14 '15 at 22:56
  • @LeonardoSavioDabus I have a sample project. Where can I host the project so I can give u a link to the project? – user1871869 May 14 '15 at 23:23
  • Compress the project's enclosing folder and send me the Dropbox link of the zipped file – Leo Dabus May 14 '15 at 23:30
  • @LeonardoSavioDabus I am almost finished reproducing the issue I need a few minutes. – user1871869 May 14 '15 at 23:40
  • @LeonardoSavioDabus here is the link: For some reason I cannot reproduce the Flickering issue with the labels and it actually works as intended but when I look at my main project's code, it still flickers even though the code is very similar to how this project is built. please let me know if you can find anything wrong.. thanks! https://www.dropbox.com/s/kq2e5eiregxb1wh/Test2.xcodeproj.zip?dl=0 – user1871869 May 15 '15 at 00:20
  • @LeonardoSavioDabus ok so I have nailed down my problem but I'm not sure how to fix it. The issue is, I am pulling an image from Facebook every time `viewForHeaderInSection` is called. Because the timer refreshes every second, so does the getting the photo. Is there anyway to make this function only called once? – user1871869 May 15 '15 at 00:25
  • you need to right click the folder with its contents (including the xcodeproj) and select compress. The zipped file should contain a folder not a file – Leo Dabus May 15 '15 at 00:25
  • You can create a var loadedImage = false and just make it true after loaded, so you can fetch it only once. if !loadedImage { ... } – Leo Dabus May 15 '15 at 00:26
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/77854/discussion-between-user1871869-and-leonardo-savio-dabus). – user1871869 May 15 '15 at 00:26
  • @LeonardoSavioDabus Ah yes I have just tried that but now when I do var `loadedImage = false` my image doesn't show up anymore... I feel like the issue may be because every time I refresh the data, the image loads for one second, then it disappears since I do not load it again since I call `self.tableView.reloadData()` in the `refreshView(timer: NSTimer)` function. Any ideas on how to go around this? – user1871869 May 15 '15 at 00:34
  • just create a sample project I can fix it for you – Leo Dabus May 15 '15 at 00:35
  • @LeonardoSavioDabus here is the sample project with the issue reproduced. Thank you for helping me: https://www.dropbox.com/s/ns7w1wf3gfiw8fc/Test2.zip?dl=0 – user1871869 May 15 '15 at 00:39
  • @LeonardoSavioDabus did the link work? – user1871869 May 15 '15 at 05:56
  • @LeonardoSavioDabus did you find anything? – user1871869 May 16 '15 at 15:44
  • I think you will need to think about another way of doing it try separating the image loading from the timer – Leo Dabus May 16 '15 at 15:46
  • It is an async method I think it will never work like that – Leo Dabus May 16 '15 at 15:47
  • And there is no need to "change" the image every time – Leo Dabus May 16 '15 at 15:48
  • @LeonardoSavioDabus I have tried the boolean method you spoke of where you only load the image once but that did not seem to work even if I put the variable in the async method. Any other possible suggestions to fix this? – user1871869 May 16 '15 at 15:50
  • you need to create an array with the images only once (viewDidLoad) and when reloading the table you fetch the image that was loaded at vied did load – Leo Dabus May 16 '15 at 15:52
  • @LeonardoSavioDabus ah okay I will try that and see what I can do to fix it and will update you when I attempt it. Thanks! – user1871869 May 16 '15 at 15:55
  • @LeonardoSavioDabus Hi, I tried to follow your method but I can't seem to load any images and I am sure I am calling the function right. I have posted my changes in the XCode dropbox link. I get an error saying that I have an `Array index out of range` . Any ideas on how to fix this? The link is: dropbox.com/s/ns7w1wf3gfiw8fc/Test2.zip?dl=0 – user1871869 May 18 '15 at 10:01
  • Check the array count before trying to access it. The async method is the problem. It is probably not finished when you try to get the image. You can also Post a notification when finish and load them. – Leo Dabus May 18 '15 at 11:30
  • @LeonardoSavioDabus can you clarify on what you mean by a notification? Like a local notification? I am a little confused because I thought I solved the async method with the completion handler I made. – user1871869 May 18 '15 at 20:46
  • http://stackoverflow.com/questions/29789243/ios-reloading-a-uitableview-from-a-swift-class-object/29790100#29790100 – Leo Dabus May 18 '15 at 21:47
  • @LeonardoSavioDabus I have included my implementation in my code with the notification center but it doesn't seem to change anything. I still seem to get the same error. Any ideas on what I might be doing wrong? I have updated my dropbox project again. Link is: https://www.dropbox.com/s/ns7w1wf3gfiw8fc/Test2.zip?dl=0 – user1871869 May 19 '15 at 08:41
  • @LeonardoSavioDabus I am a bit confused. I was trying to go off of your example and tried to follow your example. I took out my completion handler that I wrote while getting the profile pictures but that didn't seem to change anything: I still got the same errors as before. Any ideas on how to fix this? I feel like the issue is because I do not know how many images there needs to be loaded beforehand so I somehow need to know how many times to call the `getProfilePicture` function which I'm not sure how to do.. – user1871869 May 19 '15 at 17:46

1 Answers1

0

You're just trying to update the label correct? You shouldn't need to redraw the entire header view. If you just change the label text and possibly call setNeedsDisplay on the label it should take care of itself.

ImpurestClub
  • 193
  • 1
  • 4
  • 15
  • I looked at the `setNeedsDisplay` function and it doesn't seem to take in any parameters. How would you call it on the label? – user1871869 May 14 '15 at 22:36
  • Also I'm not too sure where would you be calling this function on the `headerView.headerTimeLeft.text` label? – user1871869 May 14 '15 at 22:37