Objective c 我有80-90%的时间可以查看的图像,因为它们不';不能总是足够快地填充数据源。我怎样才能解决这个问题?
我有一个详细视图控制器,它由一个充满项目的集合视图控制器显示。这些物品中有些只有一张图片,有些有附加图片(衣服不同角度的图片) 当我切换到细节视图控制器时,我必须快速与外部数据库通信。首先,我检查是否有其他图像,并将它们存储在NSMutableArray中 数组填充图像的速度不够快,因此我必须在ViewDidAspect方法中重新加载数据 这在80-90%的情况下都能正常工作,但有时也会出现这样的情况,我只看到了旋转器,但没有图像。然后,我必须返回一个控制器,并返回到细节视图控制器,以便图像显示。这是我的应用程序中唯一明显的问题。我不认为这是一个好的外观和肯定有一个办法来阻止这一点 我想可能在应用程序第一次打开时加载了所有资源。因此,加载背景中的所有图像。然而,随着客户商店的增长,他们的商店里有数千件衣服,会发生什么呢。可能是个问题。我还考虑过在前一个控制器中加载图像,但我知道在数组中加载和存储哪组图像的唯一方法是点击collection view单元格。如果客户到达页面并直接点击图像,阵列可能还没有准备好 以下是我如何加载图像并将其存储在阵列中。Objective c 我有80-90%的时间可以查看的图像,因为它们不';不能总是足够快地填充数据源。我怎样才能解决这个问题?,objective-c,cocoa-touch,uiviewcontroller,uiimage,nsmutablearray,Objective C,Cocoa Touch,Uiviewcontroller,Uiimage,Nsmutablearray,我有一个详细视图控制器,它由一个充满项目的集合视图控制器显示。这些物品中有些只有一张图片,有些有附加图片(衣服不同角度的图片) 当我切换到细节视图控制器时,我必须快速与外部数据库通信。首先,我检查是否有其他图像,并将它们存储在NSMutableArray中 数组填充图像的速度不够快,因此我必须在ViewDidAspect方法中重新加载数据 这在80-90%的情况下都能正常工作,但有时也会出现这样的情况,我只看到了旋转器,但没有图像。然后,我必须返回一个控制器,并返回到细节视图控制器,以便图像显示
- (void)viewDidLoad
{
[super viewDidLoad];
// Load up additional images
PFQuery *query = [PFQuery queryWithClassName:@"Garments"];
[query whereKey:@"title" equalTo:[self garmentTitle]];
[query getFirstObjectInBackgroundWithBlock:^(PFObject *object, NSError *error) {
[[self carouselSpinner] startAnimating];
if (!error) {
// Set objectID for save to favourite feature
_garmentObject = object;
PFFile *additionalImage1 = [object objectForKey:@"image2"];
PFFile *additionalImage2 = [object objectForKey:@"image3"];
PFFile *additionalImage3 = [object objectForKey:@"image4"];
PFFile *additionalImage4 = [object objectForKey:@"image5"];
PFFile *additionalImage5 = [object objectForKey:@"image6"];
[_additionalGarmentImagesArray addObject:[self garmentImage]];
if (additionalImage1) {
PFImageView *pfImageView1 = [[PFImageView alloc] init];
[pfImageView1 setFile:additionalImage1];
[pfImageView1 loadInBackground:^(UIImage *image, NSError *error) {
if (!error) {
[_additionalGarmentImagesArray addObject:image];
}
}];
}
if (additionalImage2) {
PFImageView *pfImageView2 = [[PFImageView alloc] init];
[pfImageView2 setFile:additionalImage2];
[pfImageView2 loadInBackground:^(UIImage *image, NSError *error) {
if (!error) {
[_additionalGarmentImagesArray addObject:image];
}
}];
}
if (additionalImage3) {
PFImageView *pfImageView3 = [[PFImageView alloc] init];
[pfImageView3 setFile:additionalImage3];
[pfImageView3 loadInBackground:^(UIImage *image, NSError *error) {
if (!error) {
[_additionalGarmentImagesArray addObject:image];
}
}];
}
if (additionalImage4) {
PFImageView *pfImageView4 = [[PFImageView alloc] init];
[pfImageView4 setFile:additionalImage4];
[pfImageView4 loadInBackground:^(UIImage *image, NSError *error) {
if (!error) {
[_additionalGarmentImagesArray addObject:image];
}
}];
}
if (additionalImage5) {
PFImageView *pfImageView5 = [[PFImageView alloc] init];
[pfImageView5 setFile:additionalImage5];
[pfImageView5 loadInBackground:^(UIImage *image, NSError *error) {
if (!error) {
[_additionalGarmentImagesArray addObject:image];
}
}];
}
} else {
NSLog(@"emp array");
}
数组由调用此方法的时间填充:
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[[self carousel] reloadData];
}
- (NSInteger)numberOfItemsInCarousel:(iCarousel *)carousel
{
//return the total number of items in the carousel
return [_additionalGarmentImagesArray count];
}
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSInteger)index reusingView:(UIView *)view
{
PFImageView *imageView = [[PFImageView alloc] initWithFrame:CGRectMake(0, 0, 300.0f, 354)];
view = imageView;
//create new view if no view is available for recycling
if (view == nil)
{
//set image
((PFImageView *)view).image = _additionalGarmentImagesArray[index];
[[self carouselSpinner] stopAnimating];
} else {
//set image
((PFImageView *)view).image = _additionalGarmentImagesArray[index];
[[self carouselSpinner] stopAnimating];
}
return view;
}
最后,我使用我的图像数组:
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[[self carousel] reloadData];
}
- (NSInteger)numberOfItemsInCarousel:(iCarousel *)carousel
{
//return the total number of items in the carousel
return [_additionalGarmentImagesArray count];
}
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSInteger)index reusingView:(UIView *)view
{
PFImageView *imageView = [[PFImageView alloc] initWithFrame:CGRectMake(0, 0, 300.0f, 354)];
view = imageView;
//create new view if no view is available for recycling
if (view == nil)
{
//set image
((PFImageView *)view).image = _additionalGarmentImagesArray[index];
[[self carouselSpinner] stopAnimating];
} else {
//set image
((PFImageView *)view).image = _additionalGarmentImagesArray[index];
[[self carouselSpinner] stopAnimating];
}
return view;
}
这里:
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[[self carousel] reloadData];
}
- (NSInteger)numberOfItemsInCarousel:(iCarousel *)carousel
{
//return the total number of items in the carousel
return [_additionalGarmentImagesArray count];
}
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSInteger)index reusingView:(UIView *)view
{
PFImageView *imageView = [[PFImageView alloc] initWithFrame:CGRectMake(0, 0, 300.0f, 354)];
view = imageView;
//create new view if no view is available for recycling
if (view == nil)
{
//set image
((PFImageView *)view).image = _additionalGarmentImagesArray[index];
[[self carouselSpinner] stopAnimating];
} else {
//set image
((PFImageView *)view).image = _additionalGarmentImagesArray[index];
[[self carouselSpinner] stopAnimating];
}
return view;
}
我突然想到的另一件事是,在我上一个控制器的序列中,我可以在后台从后端获取数据,并使用一个完成块。因此,如果抓取了数据,则转到详图视图控制器;如果没有,则不执行任何操作。在等待过程中,将显示一个微调器
你会如何处理我的问题
现在,每个图像都存储在数据库中自己的列中,例如image2、image3、image4、image5。我又在想也许把它们存储在一个数组里?但我不确定这能为我赢得多少时间,也不确定这是否能解决我在加载失败时遇到的问题。“我的收藏”视图图像是从后端拍摄到的,但它们从来都不会加载失败
如果可能的话,请提供一些可靠的建议或解决方案
感谢您抽出时间我建议您首先从服务器获取要显示的所有图像的URL,以便您知道要在表视图或集合视图中配置多少单元格 然后使用UIImageView属性创建自定义单元格,以显示缩略图等。 另外,另一个属性NSDictionary*imageInfo;您将使用不同的详细信息设置,包括对应单元格图像的URL。 当您从视图控制器类设置imageInfo属性时,cell对象将异步(在后台)下载图像。为此,请重写imageInfo属性的setter 下载图像后,需要在主线程中更新UI(这在自定义单元格中完成): 这样,每当图像下载完成时,UI都会得到更新 如果需要,还可以缓存图像,还可以不时清除缓存
你可以考虑当细胞从屏幕上消失时调用的方法,在这种情况下,你可以取消任何下载,因为显然,如果不可见,你就不再需要它了。
希望它有意义从我的理解来看,您希望确保
[[self carousel]reloadData]在所有5个pfImageViewX loadInBackground:
background方法完成后始终调用code>,是否正确
我会这样做,我不会改变太多:
我会在您的后台提取中添加一个名为numImagesChecked
的计数器,并在检查了5幅图像后将其递增
然后,我将包装[[self carousel]reloadData]
在另一个函数中,仅当numImagesChecked
为5时才会执行重新加载数据(即,检查并完成所有附加图像)
在这里,它在viewDidLoad中被修改:
[query getFirstObjectInBackgroundWithBlock:^(PFObject *object, NSError *error) {
[[self carouselSpinner] startAnimating];
if (!error) {
// Set objectID for save to favourite feature
_garmentObject = object;
PFFile *additionalImage1 = [object objectForKey:@"image2"];
PFFile *additionalImage2 = [object objectForKey:@"image3"];
PFFile *additionalImage3 = [object objectForKey:@"image4"];
PFFile *additionalImage4 = [object objectForKey:@"image5"];
PFFile *additionalImage5 = [object objectForKey:@"image6"];
[_additionalGarmentImagesArray addObject:[self garmentImage]];
int numImagesChecked = 0; //add this
if (additionalImage1) {
PFImageView *pfImageView1 = [[PFImageView alloc] init];
[pfImageView1 setFile:additionalImage1];
[pfImageView1 loadInBackground:^(UIImage *image, NSError *error) {
if (!error) {
[_additionalGarmentImagesArray addObject:image];
}
numImagesChecked++;
[self performSelectorOnMainThread:@selector(reloadDataWithCounter:) withObject:[NSNumber numberWithInt:numImagesChecked] waitUntilDone:NO];
}];
}
else {
numImagesChecked++;
}
if (additionalImage2) {
PFImageView *pfImageView2 = [[PFImageView alloc] init];
[pfImageView2 setFile:additionalImage2];
[pfImageView2 loadInBackground:^(UIImage *image, NSError *error) {
if (!error) {
[_additionalGarmentImagesArray addObject:image];
}
numImagesChecked++;
[self performSelectorOnMainThread:@selector(reloadDataWithCounter:) withObject:[NSNumber numberWithInt:numImagesChecked] waitUntilDone:NO];
}];
}
else {
numImagesChecked++;
}
if (additionalImage3) {
PFImageView *pfImageView3 = [[PFImageView alloc] init];
[pfImageView3 setFile:additionalImage3];
[pfImageView3 loadInBackground:^(UIImage *image, NSError *error) {
if (!error) {
[_additionalGarmentImagesArray addObject:image];
}
numImagesChecked++;
[self performSelectorOnMainThread:@selector(reloadDataWithCounter:) withObject:[NSNumber numberWithInt:numImagesChecked] waitUntilDone:NO];
}];
}
else {
numImagesChecked++;
}
if (additionalImage4) {
PFImageView *pfImageView4 = [[PFImageView alloc] init];
[pfImageView4 setFile:additionalImage4];
[pfImageView4 loadInBackground:^(UIImage *image, NSError *error) {
if (!error) {
[_additionalGarmentImagesArray addObject:image];
}
numImagesChecked++;
[self performSelectorOnMainThread:@selector(reloadDataWithCounter:) withObject:[NSNumber numberWithInt:numImagesChecked] waitUntilDone:NO];
}];
}
else {
numImagesChecked++;
}
if (additionalImage5) {
PFImageView *pfImageView5 = [[PFImageView alloc] init];
[pfImageView5 setFile:additionalImage5];
[pfImageView5 loadInBackground:^(UIImage *image, NSError *error) {
if (!error) {
[_additionalGarmentImagesArray addObject:image];
}
numImagesChecked++;
[self performSelectorOnMainThread:@selector(reloadDataWithCounter:) withObject:[NSNumber numberWithInt:numImagesChecked] waitUntilDone:NO];
}];
}
else {
numImagesChecked++;
}
[self performSelectorOnMainThread:@selector(reloadDataWithCounter:) withObject:[NSNumber numberWithInt:numImagesChecked] waitUntilDone:NO];
} else {
NSLog(@"emp array");
}
以下是新功能:
-(void)reloadDataWithCounter:(NSNumber *)imagesChecked
{
if([imagesChecked intValue]>4){ //only reload data after all 5 images have been checked
[[self carousel] reloadData];
}
}
我同意@Pavlusha-使用PFFile对象中的URL。然后,您可以利用出色的AFUIImageView异步加载图像。为了解决这个问题,我加载了其他图像,并将它们存储在collectionView(显示detailView的控制器)的cellForItemAtIndexPath方法中的数组中
然后,在segue过程中,我将该数组传递给了我的detailView的一个属性,我的图像数组立即可用。但PFImageView视图正是这样做的。它异步加载图像。问题是有时可能有4个图像,有时可能有2个。管理员为那件衣服上传了多少额外的图片,这确实是不一样的。因此,我想知道如何计算返回对象中的额外图像数量,例如if additionlImage1、if additionalImage2等,然后将其与_additionalGarmentImagesArray进行比较,一旦匹配,这意味着加载了所有图像。然后我可以重新加载数据。基本上,我需要一种方法,让你上面提供的代码工作,如果我们不知道有多少图像将返回,因为数量不同。你不总是检查5个图像虽然?即使只有1、2或0,你也总是在检查5,对吗?计数器总是在5点结束。这并不是要计算有多少图像,只是检查了多少图像。这就是为什么每次图像检查时,它也会在“else”上递增。我使用PFImageView来执行上面所述的操作。