使用上传状态更新 UI 表格视图单元格 - iOS

发布于 2025-01-06 07:17:14 字数 2720 浏览 0 评论 0原文

不幸的

是,我在 iOS 中使用 UITablewView 控制器的经验非常有限。我的应用程序中需要的是一个 UI 表格视图,其中包含一个自定义单元格,用于当前上传到网络服务器的每个活动上传(视频、音频等)。

这些上传中的每一个都在后台异步运行,并且都应该能够更新诸如各自单元格中的 UILabels 之类的内容,说明有关更新进度的百分比等。

现在我找到了一个有效的解决方案。问题是我不知道它是否真的安全。根据我自己的结论,我真的不认为是这样。我所做的只是从正在创建的单元格中检索 UIView 的引用,然后将这些引用存储在上传对象中,以便它们可以自行更改标签文本等。

我自己的解决方案

-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
 static NSString *CustomCellIdentifier = @"CustomCell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CustomCellIdentifier];

if (cell == nil)
{
    NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"UploadCellView" owner:self options:nil];

    if ([nib count] > 0)
    {
        cell = customCell;
    }
    else
    {
        NSLog(@"Failed to load CustomCell nib file!");
    }
}

NSUInteger row = [indexPath row];
UploadActivity *tempActivity = [[[ApplicationActivities getSharedActivities] getActiveUploads] objectAtIndex:row];

UILabel *cellTitleLabel = (UILabel*)[cell viewWithTag:titleTag];
cellTitleLabel.text = tempActivity.title;

UIProgressView *progressbar = (UIProgressView*)[cell viewWithTag:progressBarTag];
[progressbar setProgress:(tempActivity.percentageDone / 100) animated:YES];

UILabel *cellStatusLabel = (UILabel*)[cell viewWithTag:percentageTag];

[cellStatusLabel setText:[NSString stringWithFormat:@"Uploader - %.f%% (%.01fMB ud af %.01fMB)", tempActivity.percentageDone, tempActivity.totalMBUploaded, tempActivity.totalMBToUpload]];

tempActivity.referencingProgressBar = progressbar;
tempActivity.referencingStatusTextLabel = cellStatusLabel;

return cell;
}

如您所见,我认为我在这方面做的事情还不够好: tempActivity.referencingProgressBar = 进度条; tempActivity.referencingStatusTextLabel = cellStatusLabel;

上传活动获取对此单元中存储的控件的引用,然后可以自行更新它们。问题是我不知道这是否安全。如果他们引用的单元格被重新使用或从内存中删除等等怎么办?

是否有另一种方法可以简单地更新底层模型(我的上传活动),然后强制 UI 表视图重新绘制更改的单元格?您最终能否子类化 UITableViewCell 并让它们不断检查上传,然后让它们自行上传?

编辑

这是上传活动对象调用其引用 UI 控件的方式:

- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten
totalBytesWritten:(NSInteger)totalBytesWritten
totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
{
if (referencingProgressBar != nil)
{
    [referencingProgressBar setProgress:(percentageDone / 100) animated:YES];
}

if (referencingStatusTextLabel != nil)
{
    [referencingStatusTextLabel setText:[NSString stringWithFormat:@"Uploader - %.f%% (%.01fMB ud af %.01fMB)", percentageDone, totalMBUploaded, totalMBToUpload]];
}
}

我唯一关心的是,由于这些对象异步运行,如果在某个给定点 UI 表格视图决定删除或重新使用怎么办?这些上传对象指向的单元格?看起来一点也不安全。

Hell everyone :)

My experience with the UITablewView Controller in iOS is unfortunately quite limited. What I need in my application is a UI table view which contains one custom cell for each active upload currently being uploaded to a webserver (videos, audio, etc).

Each of these uploads run asynchrounously in the background, and should all be able to update things such as UILabels in their respective cells saying something about the update progress in percentage, etc.

Now I have found a solution which works. The problem is I do not know if it is actually secure or not. Based on my own conclusion I don't really think that it is. What I do is simply to retrieve a reference of the UIViews from a cell which is getting created, and then store those references in the upload objects, so they can change label text and so on themselves.

My Own Solution

-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
 static NSString *CustomCellIdentifier = @"CustomCell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CustomCellIdentifier];

if (cell == nil)
{
    NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"UploadCellView" owner:self options:nil];

    if ([nib count] > 0)
    {
        cell = customCell;
    }
    else
    {
        NSLog(@"Failed to load CustomCell nib file!");
    }
}

NSUInteger row = [indexPath row];
UploadActivity *tempActivity = [[[ApplicationActivities getSharedActivities] getActiveUploads] objectAtIndex:row];

UILabel *cellTitleLabel = (UILabel*)[cell viewWithTag:titleTag];
cellTitleLabel.text = tempActivity.title;

UIProgressView *progressbar = (UIProgressView*)[cell viewWithTag:progressBarTag];
[progressbar setProgress:(tempActivity.percentageDone / 100) animated:YES];

UILabel *cellStatusLabel = (UILabel*)[cell viewWithTag:percentageTag];

[cellStatusLabel setText:[NSString stringWithFormat:@"Uploader - %.f%% (%.01fMB ud af %.01fMB)", tempActivity.percentageDone, tempActivity.totalMBUploaded, tempActivity.totalMBToUpload]];

tempActivity.referencingProgressBar = progressbar;
tempActivity.referencingStatusTextLabel = cellStatusLabel;

return cell;
}

As you can see, this is where I think I'm doing something which isn't quite good enough:
tempActivity.referencingProgressBar = progressbar;
tempActivity.referencingStatusTextLabel = cellStatusLabel;

The upload activities get a reference to the controls stored in this cell, and can then update them themselves. The problem is that I do not know whether this is safe or not. What if the cell they are refering to gets re-used or deleted from memory, and so on?

Is there another way in which you can simply update the underlying model (my upload activites) and then force the UI table view to redraw the changed cells? Could you eventually subclass the UITableViewCell and let them continously check up against an upload and then make them upload themselves?

EDIT

This is how the upload activity objects calls their referencing UI controls:

- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten
totalBytesWritten:(NSInteger)totalBytesWritten
totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
{
if (referencingProgressBar != nil)
{
    [referencingProgressBar setProgress:(percentageDone / 100) animated:YES];
}

if (referencingStatusTextLabel != nil)
{
    [referencingStatusTextLabel setText:[NSString stringWithFormat:@"Uploader - %.f%% (%.01fMB ud af %.01fMB)", percentageDone, totalMBUploaded, totalMBToUpload]];
}
}

My only concern is that, since these objects run asynchrounously, what if at some given point the UI table view decides to remove or re-use the cells which these upload objects are pointing to? It doesn't seem very secure at all.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦断已成空 2025-01-13 07:17:14

有两种可能性,假设您有一个正在上传的后台进程:

  1. tableview 是一个委托并实现了一些 uploadProgress
    功能
  2. tableview 监听 uploadProgress NSNotifications

第二个更容易实现,只需将监听器 start/stop 放在 viewdidappear/viewdiddissappear 中即可。然后,在您的上传中,您可以跟踪进度并发出带有附加用户信息的通知,该通知为进度提供整数值。该表有一个函数可以处理收到的通知并重绘单元格。 以下是如何将数据添加到 NSNotification 的 userinfo 部分

如果您想要更高级,您可以拥有一个上传 ID 并将其映射到单元格索引,并且仅重绘该特定单元格。 以下问题和解答解释了如何操作


恶心的伪代码因为我现在无法访问我的 IOS 开发环境

上传函数:

uploadedStuff{
  upload_id = ... // unique i, maps to row in table somehow
  byteswritten = ...
  bytestotal = ....
  userinfo = new dict
  userinfo["rowid] = upload_id
  userinfo["progress"] = (int)byteswritten/bytestotal
  sendNotification("uploadprogress",userinfo)
}

tableview.m:

viewdidappear{
  listenForNotification name:"uploadprogress" handledBy:HandleUploadProgress
}

viewdiddisappear{
  stoplisteningForNotification name:"uploadprogess"
}

HandleUploadProgess:NSNotification notification {
 userinfo = [notification userinfo]
 rowId = [userinfo getkey:"rowId"]
 progress = [userinfo getkey:"rowId"]
 // update row per the link above
}

There are two possibilities, assuming you have a background process that is uploading:

  1. The tableview is a delegate and implements some uploadProgress
    function
  2. The tableview listens for uploadProgress NSNotifications

The second is easier to implement, just put the listeners start/stop in viewdidappear/viewdiddissappear. Then in your upload you can track progress and emit a notification with attached userinfo that gives an integer value to progress. The table has a function that handles this notification being received and redraws the cells. Here is how to add data to the userinfo part of an NSNotification.

If you wanted to be fancier you could have an upload id and map this to a cell index, and only redraw that particular cell. Here's a question and answers that explain how to do this.


Disgusting Pseudocode Since I don't have access to my IOS dev env right now

upload function:

uploadedStuff{
  upload_id = ... // unique i, maps to row in table somehow
  byteswritten = ...
  bytestotal = ....
  userinfo = new dict
  userinfo["rowid] = upload_id
  userinfo["progress"] = (int)byteswritten/bytestotal
  sendNotification("uploadprogress",userinfo)
}

tableview.m:

viewdidappear{
  listenForNotification name:"uploadprogress" handledBy:HandleUploadProgress
}

viewdiddisappear{
  stoplisteningForNotification name:"uploadprogess"
}

HandleUploadProgess:NSNotification notification {
 userinfo = [notification userinfo]
 rowId = [userinfo getkey:"rowId"]
 progress = [userinfo getkey:"rowId"]
 // update row per the link above
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文