How can I rotate a UIImageView? - cocoa-touch

i'm pretty new to Xcode, and i was wondering how to rotate a uiimage on touch down, this is what i have currently:
#implementation secondViewController
int degrees;
UIImageView *gliderImageView;
bool continueSpinning;
-(void)startSpinning {
degrees = 0;
continueSpinning = true;
[self continueSpinning];
}
-(void)continueSpinning {
degrees = (degrees + 1) %360;
CGAffineTransform rotate = CGAffineTransformMakeRotation( degrees / 180.0 * 3.14);
[gliderImageView setTransform:rotate];
if(!continueSpinning) return;
else [self performSelector:#selector(continueSpinning) withObject:nil afterDelay:0.1f];
}
-(void)stopSpinning {
continueSpinning = false;
}
so does anyone know
how to link the button to the image
how to set a boolean with a button
if this code will work in the first place?

You can find an example of rotating a UIImage here.
So just in your .h write this:
(in the #interface)
IBOutlet UIImage *myImage;
IBOutlet UIButton *myButton;
(after the #interface closing bracket)
#property (nonatomic, retain) IBOutlet UIImage *myImage;
#property (nonatomic, retain) IBOutlet UIButton *myButton
-(IBAction) spinIt:(id)sender;
Then in your .m write:
Under the #implementation:
#synthesize myImage, myButton;
Then below the end of the viewDidLoad write something like this:
-(IBAction)spinIt:(id)sender {
myImage.image = image;
[self addSubview:imageView];
CGAffineTransform rotate = CGAffineTransformMakeRotation( 1.0 / 20.0 * M_PI );
[imageView setTransform:rotate];
}
The above code is from here.
After that add an image and a button to your view in the Storyboard and set up the references by control dragging from the button to the responder and clicking the spinIt method and by control dragging from the outlet names on the far right in the connections tab under the little arrow icon to their respective connections.
The above code rotates 90 degrees so you may want to change it to fit your needs. Also, this is a duplicate question, so in the future please search before posting. Good luck!
EDIT- If you want the image to spin while the button is being pressed I recommend making an array of images of it at different intervals in the spin and playing the images like a stop motion animation. Instructions on that can be found [here]3.

Related

UIImageView not showing up

I have a UIImageView with property, it's connected in the storyboard and in viewDidLoad I have set it's image. I first create an image then assign it to the image of the UIImageView.
-(void)viewDidLoad {
[super viewDidLoad];
UIImage *image = [[UIImage imageNamed:#"image"]resizeableImageWithCapInsets:UIEdgeInsetsMake(28.5, 5, 6.5, 5)];
[self.imageView setImage:image];
}
I've made sure numerous times that the UIImageView is connected in the IB and it's showing up as connected. I have a UICollectionView over it, but it doesn't extend high enough to cover it all and the UICollectionView background color is set to clear. Thanks in advance for the help.
I suppose you added the IBOutlet UIImageView * imageView in your .h and then linked it in the Interface Builder, BUT did you add the property of the imageView? Like this:
#property (nonatomic, retain) IBOutlet UIImageView * imageView;
And then in your .m file, under the #implementation you need to add #synthesize imageView;
and set the image to your imageView using only: [imageView setImage:image]; (without the self.).
(You can also skip the #synthesize and just use [_imageView setImage:image];)
The #property allows you to edit the properties of the object, like backgroundColor, alpha, image, etc.

GPUImage animated gaussian blur filter

I was using the GPUImage gaussian blur filter to blur a still image. I want to tie the blur size to an UI element and as the element is changed by the user I blur the picture. The way I am doing it right now is to change the blurSize when there has been a significant (> 0.25) change, reapply the filter and animate the new image into the imageView.
Is there a more efficient way for me to be doing this?
On the iPhone 5, while performance is not laggy, it is not super smooth either (but perhaps that is because this operation is simply too expensive to be super smooth).
interesting question. Your best bet is to pre-compute and render CGImages at a couple of blur scales in your range, then use two stacked UIImageViews, with the one on top showing the blurrier copy but partially transparent. For example, if you rendered blurred at radiuses 1,2,3,…,10, and you wanted to show 3.7, you'd show image 3 on the bottom and image 4 on the top, at 70% opacity.
// Created in answer to Nikhil Varma's question at http://stackoverflow.com/questions/18804668/gpuimage-animated-gaussian-blur-filter
#import "GPUImage.h"
#define BLUR_STEP 2.
#interface AHViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIImageView *imageView2;
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
#property (nonatomic) CGFloat blurRadius;
#property (nonatomic, strong) UIImage *image;
#property (nonatomic, strong) GPUImageGaussianBlurFilter *blurFilter;
#property (nonatomic, strong) NSCache *blurredImageCache;
#property (nonatomic, strong) dispatch_queue_t blurQueue;
#property (nonatomic, strong) NSMutableSet *blurAmountsBeingRendered;
#end
#implementation AHViewController
-(void)viewDidLoad {
[super viewDidLoad];
self.image = [UIImage imageNamed:#"ph.jpg"];
self.blurFilter = [GPUImageGaussianBlurFilter new];
self.blurredImageCache = [NSCache new];
self.blurQueue = dispatch_queue_create("Image Blur Queue", DISPATCH_QUEUE_SERIAL);
self.blurAmountsBeingRendered = [NSMutableSet set];
self.blurRadius = 1.0;
}
- (IBAction)sliderDidMove:(UISlider *)sender {
self.blurRadius = 10 * sender.value;
}
-(void)setBlurRadius:(CGFloat)blurRadius {
_blurRadius = blurRadius;
CGFloat smaller = self.blurRadius - fmodf(self.blurRadius, BLUR_STEP);
[self asyncGenerateImageWithBlurAmount:smaller];
CGFloat larger = smaller + BLUR_STEP;
[self asyncGenerateImageWithBlurAmount:larger];
}
-(UIImage *)cachedImageWithBlurAmount:(CGFloat)blur {
return [self.blurredImageCache objectForKey:#(blur)];
}
-(void)asyncGenerateImageWithBlurAmount:(CGFloat)blur {
// This image is already available.
if([self.blurredImageCache objectForKey:#(blur)]) {
[self imageIsAvailableWithBlur:blur];
return;
}
// There's already a render going on for this. Just return.
if([self.blurAmountsBeingRendered containsObject:#(blur)])
return;
// Start a render
[self.blurAmountsBeingRendered addObject:#(blur)];
dispatch_async(self.blurQueue, ^{
self.blurFilter.blurSize = blur;
UIImage *result = [self.blurFilter imageByFilteringImage:self.image];
[self.blurredImageCache setObject:result forKey:#(blur)];
[self.blurAmountsBeingRendered removeObject:#(blur)];
dispatch_async(dispatch_get_main_queue(), ^{
[self imageIsAvailableWithBlur:blur];
});
});
}
-(void)imageIsAvailableWithBlur:(CGFloat)blurAmount {
CGFloat smaller = self.blurRadius - fmodf(self.blurRadius, BLUR_STEP);
CGFloat larger = smaller + BLUR_STEP;
UIImage *sharperImage = [self cachedImageWithBlurAmount:smaller];
UIImage *blurrier = [self cachedImageWithBlurAmount:larger];
if(sharperImage && blurrier) {
if(![self.imageView.image isEqual:sharperImage])
self.imageView.image = sharperImage;
if(![self.imageView2.image isEqual:blurrier]) {
self.imageView2.image = blurrier;
}
self.imageView2.alpha = (self.blurRadius - smaller) / BLUR_STEP;
}
}
#end

Can't change the frames of .xib UI objects in code

I am trying to re-write my code to allow me to use xibs to design custom UIViews for re-use throughout my projects. I have created a class called SlidesView which has a .xib of the same name. I have set it up using the following IBOutlets:
#property (nonatomic, retain) IBOutlet UIImageView *ivMain;
#property (nonatomic, retain) IBOutlet UILabel *lHeader;
#property (nonatomic, retain) IBOutlet UITextView *tvMain;
#property (nonatomic, retain) IBOutlet UIImageView *ivIcon;
I have made sure these are all properly connected within the .xib file. I also have a function which I want to use to setup all the initial data for the view:
- (void)setupUsingCenter:(CGPoint)center mainImage:(UIImage *)mainImage mainText:(NSString *)mainText header:(NSString *)header andIconImage:(UIImage *)iconImage
The 'setupUsingCenter:self ...' body looks as follows:
// First check for a main image and image icon
if (mainImage != nil)
{
// Set the image
[self.ivMain setImage:mainImage];
[self.ivMain setFrame:CGRectMake(10, 10, 10, 10)];
// If image icon set that too
if (iconImage != nil)
{
[self.ivIcon setImage:iconImage];
}
}
And finally I load this .xib using the following code:
NSArray* views = [[NSBundle mainBundle] loadNibNamed:#"SlidesView" owner:nil options:nil];
for (UIView *view in views) {
if([view isKindOfClass:[SlidesView class]])
{
SlidesView *slidesView = (SlidesView *)view;
[slidesView setupUsingCenter:self.vPlaceholder.center mainImage:slideImage mainText:slideText header:slideTitle andIconImage:slideIcon];
[slidesView setTextColours:[UIColor colorWithRed:1.0f green:1.0f blue:1.0f alpha:1.0f]];
[self.view addSubview:slidesView];
self.viewPopup = slidesView;
}
}
I have put in the random setFrame parameters for testing purposes but for some reason the frame doesn't change. However, the image on the ivMain does change. Can anyone explain how I can change the frame for my UI objects? Also, why does it allow me to change the image but the frame seems un-editable, doesn't this mean it must be initialised?
Any help is much appreciated,
Thanks.
Are you sure autolayout is disabled on the .xib ? It is my understanding that you cannot edit frames when autolayout is on.
If that's the case, you can either disable autolayout for that particular .xib, or you can work on constraints instead of the frame property
The use of autosizing may cause some unexpected behaviors also the autoresize subviews.
You can try something like this:
[View setAutoresizingMask:UIViewAutoresizingNone];
And:
[View setAutoresizesSubviews:NO];
Where View is the UIView that you want to apply that behavior.

Unable to implement simple view scrolling in iOS

I'm having a hard time implementing a simple scroll on my detail view.
The app is straightforward with a Master and Detail views.
When the user taps an item on Master, the Detail view is pushed with larger photo, blog text and etc.
I would like the entire Detail view to scroll, so if the picture is tall, or the text is long, they can scroll vertically to see/read more. I do not want the user to scroll these items individually. It should feel like webpage scrolling.
Currently my Detail view loads OK but I can't make it scroll.
My DetailViewController.h
#import <UIKit/UIKit.h>
#interface DetailViewController : UIViewController {
IBOutlet UILabel *postTextLabel; // wired to Text Label
IBOutlet UILabel *postAuthorNameLabel; // wired to Author Label
}
#property (strong, nonatomic) id detailItem;
#end
My DetailViewController.m
#import "DetailViewController.h"
#interface DetailViewController ()
- (void)configureView;
#end
#implementation DetailViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self configureView];
}
- (void)configureView
{
if (self.detailItem) {
NSDictionary *post = self.detailItem;
NSString *postText = [post objectForKey:#"post_text"];
NSString *postAuthorName = [post objectForKey:#"post_author_name"];
postTextLabel.text = postText;
postAuthorNameLabel.text = postAuthorName;
}
}
#end
Structure on IB:
Any ideas on what's missing to make this work?
I would do the following:
1)(optional)turn your View into a scrollview by dragging it into the view in the scruture list on the side.
2)link the scrollView into your viewcontroller .h and make an Outlet connection something like this
#property (strong, nonatomic) IBOutlet UIScrollView *scroller;
(make sure you add #synthesize in the .m if you add this manually)
and make sure it is connected in IB!
3)set the contentsize of the scrollview in viewDidLoad method
scroller.contentSize = CGSizeMake(320,550);
NOTE: IBOutlet UILabel *postTextLabel; should actually probably be a UITextView so you can access ContentSize
Which would allow for the following.
CGRect frame = postTextLabel.frame;
frame.size = postTextLabel.contentSize;
postTextLabel.frame = frame;
scroller.contentSize = CGSizeMake(320, frame.size.height+200);//200 or how ever much space is above the textView
and again that only works if you use a UITextView
for ipad replace 320 with 768 or 1024, or whichever depending on orientation
The best way to connect it in IB is like this holding down control and dragging to the .h file
and make sure it is set to automatic like in the picture, and pointing to> the .h of your view.
Adding it like this also automatically adds the #synthesize for you.
Make sure UserInteractionsEnabled are checked here for our scrollview

Disable accelerometer for a period of time then enable it

I have an app where u can move a man with the accelerometer. There is a ready set go sequence and then using pop Animation the guy appears. Although even when the man is not visible and the ready set go words appear the accelerometer is still usable and u can move the guy and accidentally touch the obstacle which then using cgrectintersectsrect changes to An end game screen. So in that ready set go sequence how can I disable the accelerometer then reenable it when the go word appears?
.h:
#interface GameScreen : UIViewController <UIAccelerometerDelegate> {
IBOutlet UIImageView *image1;
IBOutlet UIImageView *image2;
UIImageView *ball;
CGPoint delta;
IBOutlet UIImageView *man;
IBOutlet UIImageView *fang;
IBOutlet UIImageView* hiddenView;
IBOutlet UILabel* ready;
IBOutlet UILabel* set;
IBOutlet UILabel* go;
IBOutlet UILabel* endScreen;
IBOutlet UIImageView* guy;
CAKeyframeAnimation *popAnimation;
}
#property (nonatomic, retain)UIImageView *image1;
#property (nonatomic, retain)UIImageView *image2;
-(void)checkCollision;
#property (nonatomic, retain)IBOutlet UIImageView *ball;
#property CGPoint delta;
#end
.m:
-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
NSLog(#"x : %g", acceleration.x);
NSLog(#"y : %g", acceleration.y);
NSLog(#"z : %g", acceleration.z);
delta.y = acceleration.y * 50;
delta.x = acceleration.x * 50;
ball.center = CGPointMake(ball.center.x + delta.x, ball.center.y + delta.y);
// Right
if(ball.center.x < 0) {
ball.center = CGPointMake(320, ball.center.y);
}
// Left
if(ball.center.x > 320) {
ball.center = CGPointMake(0, ball.center.y);
}
// Top
if(ball.center.y < 0) {
ball.center = CGPointMake(ball.center.x, 460);
}
// Bottom
if(ball.center.y > 460){
ball.center = CGPointMake(ball.center.x, 0);
}
[self checkCollision];
}
You really should be reading a good book on coding and doing some tutorials to get an idea of how to do this, but the concept of a flag is simple.
In the class where your man is moved have a bool called bCanMove or similar, and set that to false when the class is initialised.
Once your "ready, steady, go" sequence finishes you set that to true.
The next step is check this flag in the code where you perform your movement, obviously I can't see your code but I expect you've got a method with a name similar to didAccelerate — in there just check to see if the boolean is true or not, and don't do anything if it isn't, for example:
if(!bCanMove)
{
return;
}
As I can't see your code I don't know whether you're relying on inbuilt mechanisms etc., but as other people have stated (and myself) you shouldn't really be asking these kinds of questions on here — not because you're new to coding but more the way you've phrased the question, nobody can really help without any details and it's something you would't need to ask if you did a little more reading ;)
At a bare minimum you should read this: http://cocoadevcentral.com/d/learn_objectivec/ but that's not going to help you if you don't understand some basic programming concepts (and it would appear you don't) — for that there is no substitute for a good book/tutorial.