The background image is already set in the Xcode project, but when the button gets clicked it changes, so I want to check whether or not the background image 80red.png is the same as the button's background just clicked.
-(IBAction)buttonChange:(id)sender {
redImage = [UIImage imageNamed:#"80red.png”];
UIImage *ButtonColour = [sender backgroundImageForState:UIControlStateNormal];
NSData *ButtonColourData = UIImagePNGRepresentation(ButtonColour);
NSData *redImageData = UIImagePNGRepresentation(redImage);
if ([ButtonColourData isEqual: redImageData]) {
// if images are the same
NSLog(#"Images are the same");
}
}
I don't understand why my code is not working.
Your code doesn't work because you have mistakes in syntax of code.
redImage isn't link to object UIImage class - You had to write UIImage *redImage = [UIImage imageNamed:#"80red.png"];
Next:
When you do a comparison dates of images, you comparing size the images, but different images may be the same size. Better compare the images on their content.
I pretended to your situation and that's what I got:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 2, 2)];
[button setBackgroundImage:[UIImage imageNamed:#"80red.png"] forState:UIControlStateNormal];
[self buttonChange:button];
return YES;
}
-(IBAction)buttonChange:(id)sender {
UIImage *redImage = [UIImage imageNamed:#"80red.png"];
UIImage *ButtonColour = [sender backgroundImageForState:UIControlStateNormal];
//NSData *ButtonColourData = UIImagePNGRepresentation(ButtonColour);
//NSData *redImageData = UIImagePNGRepresentation(redImage);
if ([redImage isEqual: ButtonColour]) {
// if images are the same
NSLog(#"Images are the same");
}
}
I hope my advice will help you.
P.S. Sorry for my english =)
Related
I have the following code in my viewWillAppear in a modal uiviewcontroller.
I am including UIImage+ImageEffects.h to do the blurring of the background image in this example.
-(void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:NO];
// grab an image of our parent view
UIView *parentView = self.presentingViewController.view;
UIImage *parentViewImage = [self takeSnapshotOfView:parentView];
UIImage *blurredImage = nil;
//BLUR THE IMAGE
blurredImage = [self blurWithImageEffects:parentViewImage];
// insert an image view with a picture of the parent view at the back of our view's subview stack...
UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.view.bounds];
imageView.image = blurredImage;
[self.view insertSubview:imageView atIndex:0];
}
[EDIT] Adding Blur Methods
- (UIImage *)takeSnapshotOfView:(UIView *)view
{
CGFloat reductionFactor = 1.5;
UIGraphicsBeginImageContext(CGSizeMake(view.frame.size.width/reductionFactor, view.frame.size.height/reductionFactor));
[view drawViewHierarchyInRect:CGRectMake(0, 0, view.frame.size.width/reductionFactor, view.frame.size.height/reductionFactor) afterScreenUpdates:YES];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
- (UIImage *)blurWithImageEffects:(UIImage *)image
{
return [image applyBlurWithRadius:10 tintColor:[UIColor colorWithWhite:1 alpha:0.2] saturationDeltaFactor:1.5 maskImage:nil];
}
The code works fine and the background shows up blurry but it is really noticeably slow on iPad 3 with iOS 8. When the button to display this viewcontroller is tapped there is a pause before the viewcontroller slides up from the bottom. If I remove the blur the view controller slides up faster.
I tried putting the code in the viewDidAppear but then there is a noticeable white background displayed for a few seconds before the blur appears. But when in viewDidAppear the viewcontroller slides up immediately.
If I reduce the applyWithBlurRadius value this does not seem to reduce the time it takes to apply the blur.
Is there any way I can make it run faster?
GPUImage might solve your issue, Its fast and it doesn't put too much load on processing.
Link To Framework : https://github.com/BradLarson/GPUImage
Link to use GPUImage Blur
http://blog.bubbly.net/tag/gpu-image/
http://www.raywenderlich.com/60968/ios-7-blur-effects-gpuimage
However a reference is shown below which will give you the basic idea:
First prepare your view which is to blurred:
- (NSData *)PhotoForBlurring:(UIView *)view{
UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 1.0);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData * data = UIImagePNGRepresentation(image);
[data writeToFile:#"aName.png" atomically:YES];
return data; }
-(void)sharingScrapPage{
GPUImageiOSBlurFilter *blur = [[GPUImageiOSBlurFilter alloc]init];
blur.blurRadiusInPixels=2.0;
blur.downsampling=6.0;
[blurview removeFromSuperview];
blurview = [[UIImageView alloc]initWithFrame:getRectDisplay(0, 0, 480, 320)]; // Landscape Iphone 4S
UIImage *imageForBlurring=[UIImage imageWithData:[self PhotoForBlurring:self.view]];
NSData* pngdataForBlurring = UIImagePNGRepresentation (imageForBlurring);
UIImage* blurImage = [UIImage imageWithData:pngdataForBlurring];
blurImage=[blur imageByFilteringImage:blurImage];
blurview.image=blurImage;
[self.view addSubview:blurview];
[progressHUD removeFromSuperview];
progressHUD = [[ProgressHUD alloc]initWithFrame:getRectDisplay(190, 110, 100, 90)];
[blurview addSubview:progressHUD]; }
I'm using the code found here http://blog.blackwhale.at/?p=336 to create a custom activityIndicator in the current version of xCode. This code uses a series of .png images in an array and then displays them at the set interval to create an animated loading image that you can then place on the screen (and assuming you can somehow remove it) whenever you want.
In my main ViewController.m file I have the following code in my viewDidLoad section :
/* --- START CUSTOM ACTIVITY INDICATOR */
//Create the first status image and the indicator view
UIImage *statusImage = [UIImage imageNamed:#"activity1.png"];
UIImageView *activityImageView = [[UIImageView alloc]
initWithImage:statusImage];
//Add more images which will be used for the animation
activityImageView.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"activity1.png"],
[UIImage imageNamed:#"activity2.png"],
[UIImage imageNamed:#"activity3.png"],
[UIImage imageNamed:#"activity4.png"],
[UIImage imageNamed:#"activity5.png"],
[UIImage imageNamed:#"activity6.png"],
[UIImage imageNamed:#"activity7.png"],
[UIImage imageNamed:#"activity8.png"],
[UIImage imageNamed:#"activity9.png"],
[UIImage imageNamed:#"activity10.png"],
[UIImage imageNamed:#"activity11.png"],
[UIImage imageNamed:#"activity12.png"],
nil];
//Set the duration of the animation (play with it
//until it looks nice for you)
activityImageView.animationDuration = 0.6;
//Position the activity image view somewhere in
//the middle of your current view
activityImageView.frame = CGRectMake(
self.view.frame.size.width/2
-statusImage.size.width/2,
self.view.frame.size.height/1.2
-statusImage.size.height/1.2,
statusImage.size.width,
statusImage.size.height);
//Start the animation
[activityImageView startAnimating];
//Add your custom activity indicator to your current view
[self.view addSubview:activityImageView];
/* --- END CUSTOM ACTIVITY INDICATOR */
I would like to CLEAR/DELETE/HIDE the activityImageView element, as I only want it to show when the app first launches until the UIWebView finishes loading.
I would like to call this and have the gif appear while webViewDidStartLoad and then clear when webViewDidFinishLoad. Someone help??
You should go like this:
- (void)viewDidLoad {
[super viewDidLoad];
//Create the first status image and the indicator view
UIImage *statusImage = [UIImage imageNamed:#"activity1.png"];
UIImageView *activityImageView = [[UIImageView alloc]
initWithImage:statusImage];
//Add more images which will be used for the animation
activityImageView.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"activity1.png"],
[UIImage imageNamed:#"activity2.png"],
[UIImage imageNamed:#"activity3.png"],
[UIImage imageNamed:#"activity4.png"],
[UIImage imageNamed:#"activity5.png"],
[UIImage imageNamed:#"activity6.png"],
[UIImage imageNamed:#"activity7.png"],
[UIImage imageNamed:#"activity8.png"],
[UIImage imageNamed:#"activity9.png"],
[UIImage imageNamed:#"activity10.png"],
[UIImage imageNamed:#"activity11.png"],
[UIImage imageNamed:#"activity12.png"],
nil];
//Set the duration of the animation (play with it
//until it looks nice for you)
activityImageView.animationDuration = 0.6;
//Position the activity image view somewhere in
//the middle of your current view
activityImageView.frame = CGRectMake(
self.view.frame.size.width/2
-statusImage.size.width/2,
self.view.frame.size.height/1.2
-statusImage.size.height/1.2,
statusImage.size.width,
statusImage.size.height);
//Start the animation
[activityImageView startAnimating];
//Add your custom activity indicator to your current view
[self.view addSubview:activityImageView];
self.timer = [NSTimer scheduledTimerWithTimeInterval:(1.0/2.0)
target:self
selector:#selector(loading)
userInfo:nil
repeats:YES];
}
- (void)loading {
if (!self.webView.loading) {
[activityImageView stopAnimating];
activityImageView.hidden = 1;
} else {
[activityImageView startAnimating];
}
}
Okay, so the reason that you cannot access activityImageView is because its declared in your viewDidLoad function. Add it as a property to your ViewController class and you should be able to do what you want. Make sure that you remove the declaration of activityImageView from viewDidLoad, and just initialize it there.
Also, where is your webview that you want to show the activity indicator? Does it have a separate view controller or is it included in your main view controller? It sounds like your scope for activityImageView is incorrect, though without knowing how you have everything set up its a little hard for me to tell you where to put it.
After you use your activity indicator in these two places, do you plan on using it again during the applications run time, or will it only ever be visible if you reload the application? Depending on the answer to that you will either want to just hide it, or remove it from you main view.
UIImageView.hidden is what controls visibility.
EDIT, Code as requested:
ViewController.h
#interface ViewController : UIViewController
{
UIWebView *_webView;
}
#property(nonatomic, strong) UIWebView *webView;
#property(nonatomic, strong) UIImageView *activityImageView;
ViewController.m
#implementation ViewController
#synthesize activityImageView;
#synthesize webView = _webView;
-(void)viewDidLoad {
//all your previous stuff with the change that you just alloc activityImageView instead of declare it
activityImageView = [[UIImageView alloc] initWithImage:statusImage];
//The above is the initialization, below is where your old code should go
}
Declare your activityImageView as a property in your header file and configure it in your viewDidLoad: method
You should add your activityImageView in UIWebViewDelegate method
- (void)webViewDidStartLoad:(UIWebView *)webView
And then stopAnimating and removeFromSuperview in the UIWebViewDelegate methods
- (void)webViewDidFinishLoad:(UIWebView *)webView
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
You should read UIImageView documentation and the UIWebViewDelegate protocol reference
UPDATE
In your header:
#property(nonatomic, retain) UIImageView *activityImageView;
In your implementation
#synthesize activityImageView;
-(void)viewDidLoad{
activityImageView = [[UIImageView alloc]
initWithImage:statusImage];
//Add more images which will be used for the animation
activityImageView.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"activity1.png"],
[UIImage imageNamed:#"activity2.png"],
[UIImage imageNamed:#"activity3.png"],
[UIImage imageNamed:#"activity4.png"],
[UIImage imageNamed:#"activity5.png"],
[UIImage imageNamed:#"activity6.png"],
[UIImage imageNamed:#"activity7.png"],
[UIImage imageNamed:#"activity8.png"],
[UIImage imageNamed:#"activity9.png"],
[UIImage imageNamed:#"activity10.png"],
[UIImage imageNamed:#"activity11.png"],
[UIImage imageNamed:#"activity12.png"],
nil];
//Set the duration of the animation (play with it
//until it looks nice for you)
activityImageView.animationDuration = 0.6;
//Position the activity image view somewhere in
//the middle of your current view
activityImageView.frame = CGRectMake(
self.view.frame.size.width/2
-statusImage.size.width/2,
self.view.frame.size.height/1.2
-statusImage.size.height/1.2,
statusImage.size.width,
statusImage.size.height);
}
- (void)webViewDidStartLoad:(UIWebView *)webView{
[self.activityImageView startAnimating];
[self.view addSubview:activityImageView];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView{
[activityImageView stopAnimating];
[activityImageView removeFromSuperview];
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{
[activityImageView stopAnimating];
[activityImageView removeFromSuperview];
}
Here is the code that I am using. Keep in mind, this works just fine in the simulator. However, when I run the same code when testing on my iPad device, it doesn't load the image. Why could this be?
SDWebImageManager *manager = [SDWebImageManager sharedManager];
NSURL *url = [NSURL URLWithString:#"http://www.mywebsite.net/folder/Photos/thumbnails/IMG_1780.JPG"];
UIImage *cachedImage = [manager imageWithURL:url];
if (cachedImage)
{
// Use the cached image immediatly
}
else
{
// Start an async download
[manager downloadWithURL:url delegate:self];
}
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(80+196, 5, 192, 192)];
[button setImage:cachedImage forState:UIControlStateNormal];
[button addTarget:self action:#selector(imageSelected:) forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:button];
return cell;
I would appreciate any help! Thank you!
Edit: Altered Code, still works in Sim, but not on device.
- (void)webImageManager:(SDWebImageManager *)imageManager didFinishWithImage:(UIImage *)image
{
// Do something with the downloaded image
//testImage = image;
testButton = [[UIButton alloc] initWithFrame:CGRectMake(80+196, 5, 192, 192)];
[testButton setImage:image forState:UIControlStateNormal];
[testButton addTarget:self action:#selector(imageSelected:) forControlEvents:UIControlEventTouchUpInside];
}
SDWebImageManager *manager = [SDWebImageManager sharedManager];
NSURL *url = [NSURL URLWithString:#"http://www.mywebsite.net/album/Photos/thumbnails/IMG_1780.JPG"];
UIImage *cachedImage = [manager imageWithURL:url];
[self webImageManager:manager didFinishWithImage:cachedImage];
if (cachedImage)
{
// Use the cached image immediatly
//[self webImageManager:manager didFinishWithImage:cachedImage];
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(80+196, 5, 192, 192)];
[button setImage:cachedImage forState:UIControlStateNormal];
[button addTarget:self action:#selector(imageSelected:) forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:testButton];
}
else
{
// Start an async download
[manager downloadWithURL:url delegate:self];
}
Never having used SDWebImageManager but just having a quick look at it, it looks like you're doing everything right! On the other hand, it's not working so...
I had a similar problem to this once, and after much tearing out of hair, I eventually discovered that the filing systems used on the device & the simulator are different - on your iPad I believe it's case sensitive, but not on the simulator. Double-check the case of the file names, it might make a difference.
Edit - also, I was assuming you're trying to use the cached image (which is why it appeared immediately), but if you're downloading one then I expect your button initialising code is premature.
Another Edit - Delegates!
Do you know about using the delegate of the SDWebImageManager? It probably has a method which it calls when the image has downloaded - you need to implement SDWebImageManager delegate protocol in your class where you're setting up the buttons, etc - there will be a method something like -(void)imageDidFinishDownloading:(UIImage *)myImage which you'll have to include, and that's where you need to put the images into the buttons.
May be a little too obvious but, have you checked if your iPad has an internet connection?
The async download may not be finished when you try to create the UIButton. The last piece of code should be called after the download is completed and inside the if statement (as far as i can see from this code).
Easier to write a new answer than edit my last one.
Here's a bit of code which might be useful -
-(void)webImageManager:(SDWebImageManager *)imageManager didFinishWithImage:(UIImage *)image {
// unless you have a way to know which row it's going into, we'll just add it to the end of the array
[downloadedImages addObject:image];
[myTable reloadData];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [downloadedImages count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSInteger row = indexPath.row;
UIImage *theImage = [downloadedImages objectAtIndex:row];
UIButton *testButton = [[[UIButton alloc] initWithFrame:CGRectMake(80+196, 5, 192, 192)] autorelease];
testButton.tag = row; // so we know which row the pressed button is in
[testButton setImage:theImage forState:UIControlStateNormal];
[testButton addTarget:self action:#selector(imageSelected:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:testButton];
return cell;
}
-(void)imageSelected:(UIButton *)pressedButton {
NSInteger row = pressedButton.tag;
// now you know which row was pressed...
}
Change your code here (don't put it in the tableView:cellForRowAtIndexPath: method!) -
SDWebImageManager *manager = [SDWebImageManager sharedManager];
NSURL *url = [NSURL URLWithString:#"http://www.mywebsite.net/folder/Photos/thumbnails/IMG_1780.JPG"];
UIImage *cachedImage = [manager imageWithURL:url];
if (cachedImage) {
// Use the cached image immediately
[downloadedImages addObject:cachedImage];
[myTable reloadData];
} else {
// Start an async download
[manager downloadWithURL:url delegate:self];
}
Obviously it's quite basic - you'll need to add stuff to reset the table, or write the images to files if there are more than a few of them. Hope it helps!
I'm making an animation calling repeatedly this function so I can make an animation:
The method where I have the issue, is a method of a UIImageView's subclass Class
#interface MyCustomImageView : UIImageView {
& it is the following:
- (void) animationShowFrame: (NSInteger) frame {
NSLog(#"frame: %d", frame);
if ((frame >= animationNumFrames) || (frame < 0))
return;
NSData *data = [animationData objectAtIndex:frame];
UIImage *img = [UIImage imageWithData:data];
NSLog(#"%#",img);
NSLog(#"data: %d", [data length]);
[self setImage:img];
}
The problem is that, it seems like the first image is perfectly set, but the rest of them are ignored...
NSLogging them I can see that the images are there & the data is different every time, so, they are loaded ok, even I tried to addSubview to self (the class is UIImageView's child), through a UIImageView & they are showing, but this is not the way cause in that case I'm using too much memory...
Asking for the description in the console, I can see how self.image = nil after setting it...
I don't know what else I can do with this, it's driving me crazy.
Try to subclass to a UIView instead to a UIImageView, and create the UIImageView as a property inside.
#interface CustomView : UIView {
UIImageView *imageView;
Then, in animationShowFrame use that imageView:
- (void) animationShowFrame: (NSInteger) frame {
NSData *data = [animationData objectAtIndex:frame];
UIImage *img = [UIImage imageWithData:data];
[self.imageView setImage:img];
}
Hope it helps!
I am having difficulty in changing the image of my UIButton which is contained within a table view cell. My code as follows:
// In tableview for cell at rowIndex method
self.iconBtn = [[UIButton alloc]initWithFrame:CGRectMake(670,10,80, 80)];
self.iconBtn.tag = kIconValueTag;
[cell.contentView addSubview:self.iconBtn];
//Add icon to cell
UIImage *btnImage = [UIImage imageNamed:#"blank_star.png"];
[self.iconBtn setImage:btnImage forState:UIControlStateNormal];
// I am calling method changeIconState after user clicks on icon.
[self.iconBtn addTarget:self action:#selector(changeIconState) forControlEvents:UIControlEventTouchUpInside];
After the button is pressed, a method outside the table view method is called:
-(void)changeIconState
{
if (self.iconSelectState == kIconNotSelected)
{
self.iconSelectState = kIconSelected;
}
else
{
self.iconSelectState = kIconNotSelected;
}
[self changeIcon];
}
-(void)changeIcon
{
if (self.iconSelectState == kIconSelected)
{
UIImage *btnImageHighlighted = [UIImage imageNamed:#"star.png"];
[self.iconBtn setImage:btnImageHighlighted forState:UIControlStateNormal];
}
else
{
UIImage *btnImageNormal = [UIImage imageNamed:#"blank_star.png"];
[self.iconBtn setImage:btnImageNormal forState:UIControlStateNormal];
}
}
After I run the program, the icon did not change from blank to star as I wanted. It just remained as a blank star. Is there anything I am missing out here?
Why are you managing the image/button state yourself? Why not load the two images for the defined states and let the OS handle it?
//Add icon to cell
UIImage *btnImage = [UIImage imageNamed:#"blank_star.png"];
UIImage *btnImageHighlighted = [UIImage imageNamed:#"star.png"];
[self.iconBtn setImage:btnImage forState:UIControlStateNormal];
[self.iconBtn setImage:btnImageHighlighted forState:(UIControlStateHighlighted && UIControlStateSelected)];
If you need to manage your property (iconSelectedState) you can without worrying about the image. Alternatively, you can query the buttons state property to determine which state it is in.