I have an issue where im loading 3, sometimes 4 of the same images using
[imageFile setImageWithURL:[NSURL URLWithString:friendAvatar] placeholderImage:[UIImage imageNamed:#"defaultProfileImage.png"]];
Im trying to see if theres a way to load this into some kind of NSData and use it later on, kind of like how im doing below, but using AFNetworking.
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^(void)
{
NSURL *url3 = [NSURL URLWithString:friendAvatar];
NSData *data = [NSData dataWithContentsOfURL:url3];
UIImage *img = [[UIImage alloc] initWithData:data];
dispatch_async( dispatch_get_main_queue(), ^(void){
imageFile.image = img;
bgImageFile.image = img;
});
});
Also im not calling the image loads all in the same method, 2 call under the cellForRowAtIndexPath once the users friends list has been populated, then the 3rd gets loaded when i swipe over a cell to show its hidden (under) layer, the 4th repeat image gets called when pressing a button that is showed once the cell has been swiped which leads to a chatroom view between me and that friend.
Hopefully i got to my point on what im trying to acheive. And any help pointing in the right direction is very much appreciated.
Update:
This is my current code, this is what i mean by im pulling the same image several times.
Inside the cellForRowAtIndexPath
[imageFile setImageWithURLRequest:request placeholderImage:[UIImage imageNamed:#"defaultProfileImage.png"]];
[bgImageFile setImageWithURL:[NSURL URLWithString:friendAvatar] placeholderImage:[UIImage imageNamed:#"defaultProfileImage.png"]];
The method bottomDrawerWillAppear that is called contains
UIImageView *drawerBGImg = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,320,75)];
NSString *friendAvatar = [NSString stringWithFormat:#"%#%#%#", #"http://v9a2a7.com/user_photos/", [MyClass friendID], #".jpg"];
[drawerBGImg setImageWithURL:[NSURL URLWithString:friendAvatar]];
And on a seperate class and seperate view viewMessageViewController
NSString *friendAvatar = [NSString stringWithFormat:#"%#%#%#", #"http://v9a2a7.com/user_photos/", email, #".jpg"];
[bgImage setImageWithURL:[NSURL URLWithString:friendAvatar]];
I have not confirmed that the viewMessageViewsController's forces the image to be pulled from the server, but i know for a fact on the cellForRowAtIndexPath makes 3 requests for the same image which results in using 3X the amount of data usage
Hope this clears things up.
It sounds like you want to cache the image so you don't have to keep loading it. Assuming that's what you mean...
The AFNetworking method [UIImageView -setImageWithURL:placeholderImage:] already caches this image for you. The second time you call it, the image will be loaded from the cache.
The only reason it would get reloaded from the server a second time is if your app receives a low memory warning since the last download. (AFImageCache, an NSCache subclass, will automatically invalidate some or all of the cache.)
It uses the URL as the key, so as long as the URL is identical, the image will only get loaded from the server once.
Related
I have a CVPixelBuffer that I'm trying to efficiently draw on screen.
The not-efficient way of turning into an NSImage works but is very slow, dropping about 40% of my frames.
Therefore, I've tried rendering it on-screen using CIContext's drawImage:inRect:fromRect. The CIContext was initialized with a NSOpenGLContext who's view was set to my VC's view. When I have a new image, I call the drawImage method which doesn't spit out any errors... but doesn't display anything on screen either (it did log errors when my contexts were not correctly setup).
I've tried to find an example of how this is done on MacOS, but everything seems to be for iOS nowadays.
EDIT:
Here's some of the code I am using. I've left out irrelevant sections
On viewDidLoad I init the GL and CI contexts
NSOpenGLPixelFormatAttribute pixelFormatAttr[] = {
kCGLPFAAllRenderers, 0
};
NSOpenGLPixelFormat *glPixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes: pixelFormatAttr];
NSOpenGLContext *glContext = [[NSOpenGLContext alloc] initWithFormat:glPixelFormat shareContext:nil];
glContext.view = self.view;
self.ciContext = [CIContext contextWithCGLContext:glContext.CGLContextObj pixelFormat:glPixelFormat.CGLPixelFormatObj colorSpace:nil options:nil];
Then, when a new frame is ready, I do:
dispatch_async(dispatch_get_main_queue(), ^{
[vc.ciContext drawImage:ciImage inRect:vc.view.bounds fromRect:ciImage.extent];
vc.isRendering = NO;
});
I am not sure I'm calling draw in the right place, but I can't seem to find out where is this supposed to go.
If the CVPixelBuffer has the kCVPixelBufferIOSurfaceCoreAnimationCompatibilityKey attribute, the backing IOSurface (retrieved via CVPixelBufferGetIOSurface) can be passed directly to the contents property of a CALayer.
This is probably the most efficient way to display a CVPixelBuffer.
I try to convert data from parse.com into my UIImageView.
for (PFObject *object in objects)
{
PFFile *file = [object objectForKey:#"imageData"];
[file getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
[contentImageArray addObject: [UIImage imageWithData:data]];
}];
}
I load my data in a NSMutableArray, this still works, but then I want my data in an ImageView.
So my code:
cell.contentImage.image = [UIImage imageWithData:[contentImageArray objectAtIndex:(contentImageArray.count - indexPath.row - 1)]];
But it does not work, I just get an error message, please help!
First, you need to check the error and that the data isn't nil because this isn't safe:
[file getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
[contentImageArray addObject: [UIImage imageWithData:data]];
}];
if parse has an issue returning the data your app will crash.
Also, in that code you are already creating the image from the data, so you don't need to do it again:
cell.contentImage.image = [contentImageArray objectAtIndex:(contentImageArray.count - indexPath.row - 1)];
Finally, you're making assumptions about what index each image has in the array and you have very specific indexing logic. That's unlikely to work well / properly in the future, even if it does now. You load images in the background and put them into an array - you have no idea what order the images are going to load in... You should apply logic to deal with that. If you load the table when you don't have any images they you'll be trying to get the (0 - 0 - 1)'th image from the array, and that isn't going to exist.
From your follow on comment:
Populate your contentImageArray with instances of NSNull for each of the objects you have. When you iterate the objects, keep the index and then when the image is ready you can:
[contentImageArray replaceObjectAtIndex:i withObject:[UIImage imageWithData:data]];
and when you try to use the image, check if it's available yet:
id image = [contentImageArray objectAtIndex:indexPath];
cell.contentImage.image = ([image isKindOfClass:[UIImage class]] ? image : nil);
i have some problem. So i have code which update song name and picture from php. Song name work and also updated but picture not work, in php file all work but in my project - no. How make update picture from url after 10 sec for example. Thanks.
-(void)viewWillDraw {
NSURL *artistImageURL = [NSURL URLWithString:#"http://site.ru/ParseDataField/kiss.php?image"];
NSImage *artistImage = [[NSImage alloc] initWithContentsOfURL:artistImageURL];
[dj setImage:artistImage];
dispatch_queue_t queue = dispatch_get_global_queue(0,0);
dispatch_async(queue, ^{
NSError* error = nil;
NSString* text = [NSString stringWithContentsOfURL:[NSURL URLWithString:#"http://site.ru/ParseDataField/kiss.php?artist"]
encoding:NSASCIIStringEncoding
error:&error];
dispatch_async(dispatch_get_main_queue(), ^{
[labelName setStringValue:text];
});
});
}
You should really consider placing this code someplace other than -viewWillDraw. This routine can be called multiple times for the same NSView under some circumstances and, more importantly, you need to call [super viewWillDraw] to make sure that things will actually draw correctly (if anything is drawn in the view itself).
For periodic updates (such as every 10 seconds), you should consider using NSTimer to trigger the retrieval of the next object.
As for the general question of why your image isn't being drawn correctly, you should probably consider putting the image retrieval and drawing code into the same structure as your label retrieval and drawing code. This will get the [dj setImage: artistImage] method call outside of the viewWillDraw chain which is likely causing some difficulty here.
I've a grouped UITableView which has been resized and rounded. I would like to place a view BEHIND this table.I've tried:
[self.tableView addSubview:backgroundView];
[self.tableView sendSubviewToBack:backgroundView];
but it didn't work. This is what I obtain:
I would like to have the background in place of the black space.
Any idea?
How about [self.tableView setBackgroundView:backgroundView];?
Bear with me I'm a beginner. I just ran into this problem and I found two solutions. In my case, I was using a UITableView object.
To begin, add the background image into your app's directory. I put mine in "Supporting Files"
You can add the image as a UIColor object:
...
[resultsTable setBackGroundColor:setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"background.jpg"]]];
...
The problem with this method is that it will repeat your background image because it's treating it as a pattern.
The better way:
// Create a string to store the path location of your image, otherwise you would have to provide an exact path name
NSString *backPath = [[NSBundle mainBundle] pathForResource:#"background"
ofType:#"jpg"];
// Create a UIImage Object to store the image.
UIImage *bgImage = [[UIImage alloc ] initWithContentsOfFile:backPath];
// Create a UIImageView which the TableView
UIImageView *bgView = [[UIImageView alloc]initWithImage:bgImage];
// Set your TableView's background property, it takes a UIView Obj.
[resultsTable setBackgroundView: bgView];
.....
I'm trying to read a reference to an image file out of a plist and make the image display in a detail view. although I can do this for my table view layout, I'm having trouble doing this with my DetailViewController nib file. I'm hoping someone can help me fix the problem and explain to me where I'm going wrong. What follows with the code is my explanation of what I THINK I'm doing. If you could explain to me what I'm doing wrong as much as show me what I should be doing, I'd really appreciate it. I'm trying to learn as much as trying to make things work.
I think the problem resides in two places. The first is my didSelectRowAtIndexPath method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//Get the dictionary of the selected data source.
NSDictionary *dictionary = [[[self.localSites objectAtIndex:indexPath.section]objectForKey:#"rowData"] objectAtIndex:indexPath.row];
TableDetailViewController *controller = [[TableDetailViewController alloc] initWithNibName:#"TableDetailViewController" bundle:[NSBundle mainBundle]];
controller.title = [dictionary objectForKey:#"Location"];
controller.dText = [dictionary objectForKey:#"details"];
// THIS IS WHERE THE PROBLEM IS
NSString *tiny = [dictionary objectForKey:#"thumb"];
controller.mainImage = [UIImage imageNamed:tiny];
[self.navigationController pushViewController:controller animated:YES];
[controller release];
}
In the code above marked //THIS IS WHERE I THINK THE PROBLEM IS, What I'm trying to do is grab the reference to the image contained in string in the plist and use the reference to get the image. This approach works fine in my cellForRowAtIndexPath method where I use it to populate the left hand side of the table with thumbnail images referred to from my plist.
In the above code mainImage refers to a string I've tried to connect to a UIImageView outlet in my TableDetailViewController.xib through my TableDetailViewController.m file as below. This is where I think Problem number two is:
- (void)viewWillAppear:(BOOL)animated
{
[super viewDidLoad];
//This Bit says that the text contained in UITextView blurb is the string dText, which is used in my didSelectRowAtIndex method
blurb.text = dText;
//This is where I try to do the same thing by saying that UIImageView topImage is the NSString mainImage which I use in my didSelectRowAtIndex method
topImage.image = mainImage;
}
My Logic was that topImage is a UIImageView and mainImage is the string containing the image view which in my didSelectRowAtIndex method I pass the value of the key 'thumb' contained in my plist file.
However the above throws up warnings. Can anyone help?
Thanks for taking the time to read.
Ok, I managed to work this out. My mistake was to declare the pointer mainImage as a NSString instead of as a UIImage. I did this because in the .plist I am using the name of the image is contained within a string. I realised though that as I change this string for the .png file of the same name in my didSelectRowAtIndexPath method, by the time I'm passing it to mainImage it is no longer a string I'm passing, it's an image. Sorted! An easy mistake for a newb like me to make. Thought I should post as I'm sure I wont be the only one who makes this mistake.