Restoring CGRect with Transform values from NSDictionary The Next CEO of Stack OverflowCreating a bounding box for a ViewDetecting if a CGAffineTransformed view is out of bounds of a screen/UIViewiOS Persist view transformWrong coordinates after rotating, scaling and moving one image and sending the transform to other ViewControllerMoving a UIImageViews center pointRecreating same transform on UIImageView after pan/resize/rotateHow to find UIView's frame after transform rotatingHow do I calculate the correct CGRect origin on a scaled UIView subview?Rotate image in boundsHow to ensure a UIView with a transform fills a CGRect?

Calculating discount not working

Oldie but Goldie

Why did early computer designers eschew integers?

Car headlights in a world without electricity

My ex-girlfriend uses my Apple ID to login to her iPad, do I have to give her my Apple ID password to reset it?

My boss doesn't want me to have a side project

Calculate the Mean mean of two numbers

How to show a landlord what we have in savings?

How to unfasten electrical subpanel attached with ramset

Do I need to write [sic] when including a quotation with a number less than 10 that isn't written out?

What is a typical Mizrachi Seder like?

How badly should I try to prevent a user from XSSing themselves?

How should I connect my cat5 cable to connectors having an orange-green line?

Is it okay to majorly distort historical facts while writing a fiction story?

Is it "common practice in Fourier transform spectroscopy to multiply the measured interferogram by an apodizing function"? If so, why?

MT "will strike" & LXX "will watch carefully" (Gen 3:15)?

Does int main() need a declaration on C++?

Early programmable calculators with RS-232

Can you teleport closer to a creature you are Frightened of?

Another proof that dividing by 0 does not exist -- is it right?

Finitely generated matrix groups whose eigenvalues are all algebraic

Is it correct to say moon starry nights?

What happens if you break a law in another country outside of that country?

How to pronounce fünf in 45



Restoring CGRect with Transform values from NSDictionary



The Next CEO of Stack OverflowCreating a bounding box for a ViewDetecting if a CGAffineTransformed view is out of bounds of a screen/UIViewiOS Persist view transformWrong coordinates after rotating, scaling and moving one image and sending the transform to other ViewControllerMoving a UIImageViews center pointRecreating same transform on UIImageView after pan/resize/rotateHow to find UIView's frame after transform rotatingHow do I calculate the correct CGRect origin on a scaled UIView subview?Rotate image in boundsHow to ensure a UIView with a transform fills a CGRect?










1















I need to be able to save the frame after transformation of a UIImageView. In the below example, the original frame is when the image is added to the superview. The user then has the ability to rotate, scale and pan the image anywhere in the gray area (superview).



I take these images and save their coordinates to an NSDictionary (which is not the problem). The problem is that if I get the frame after the rotation, the frame is completely off. I need to be able to store the new frame with transform in the dictionary, so that when the user comes back to this view and the images are loaded, the frames and saved transformations are just like they intended.



Panning



CGPoint translation = [gestureRecognizer translationInView:[object superview]];
if (CGRectContainsPoint(self.frame, CGPointMake([object center].x + translation.x, [object center].y + translation.y)))
[object setCenter:CGPointMake([object center].x + translation.x, [object center].y + translation.y)];
[gestureRecognizer setTranslation:CGPointZero inView:[object superview]];



Rotating



self.transformRotation = CGAffineTransformRotate([[gestureRecognizer view] transform], [gestureRecognizer rotation]);

[gestureRecognizer view].transform = self.transformRotation;
if ( [gestureRecognizer rotation] != 0 )
self.rotate = [gestureRecognizer rotation];

[gestureRecognizer setRotation:0];


Scaling



self.transformScale = CGAffineTransformScale([[gestureRecognizer view] transform], [gestureRecognizer scale], [gestureRecognizer scale]);
[gestureRecognizer view].transform = self.transformScale;
if ( [gestureRecognizer scale] != 1 )
self.scale = [gestureRecognizer scale];

[gestureRecognizer setScale:1];


Using the Center point of the view keeps the image closer to the original location when it was saved, the first time it is loaded. Each time it is saved after that the position is the same, because the transform did not change during that session.



- (CGPoint)centerOnCanvas 
CGPoint originalCenter = self.center;
return originalCenter;


- (CGRect)frameOnCanvas
return CGRectMake(
self.preTransformedFrame.origin.x,
self.preTransformedFrame.origin.y,
self.preTransformedFrame.size.width,
self.preTransformedFrame.size.height
);


- (CGRect)preTransformedFrame
CGAffineTransform currentTransform = self.transform;
self.transform = CGAffineTransformIdentity;
CGRect originalFrame = self.bounds;
self.transform = currentTransform;
return originalFrame;



enter image description here



UPDATE: Slightly off and a little larger than the original



enter image description here










share|improve this question



















  • 1





    It's better to save Width, Height and Rotation value into UserDefaults.

    – Sachin Vas
    Mar 10 at 5:37






  • 1





    Could you show the code for rotate, scale and pan the image? If you use CGAffineTransform to make them, I don't think you need to save the frame.

    – trungduc
    Mar 13 at 5:06











  • @trungduc updated.

    – WrightsCS
    Mar 14 at 21:24















1















I need to be able to save the frame after transformation of a UIImageView. In the below example, the original frame is when the image is added to the superview. The user then has the ability to rotate, scale and pan the image anywhere in the gray area (superview).



I take these images and save their coordinates to an NSDictionary (which is not the problem). The problem is that if I get the frame after the rotation, the frame is completely off. I need to be able to store the new frame with transform in the dictionary, so that when the user comes back to this view and the images are loaded, the frames and saved transformations are just like they intended.



Panning



CGPoint translation = [gestureRecognizer translationInView:[object superview]];
if (CGRectContainsPoint(self.frame, CGPointMake([object center].x + translation.x, [object center].y + translation.y)))
[object setCenter:CGPointMake([object center].x + translation.x, [object center].y + translation.y)];
[gestureRecognizer setTranslation:CGPointZero inView:[object superview]];



Rotating



self.transformRotation = CGAffineTransformRotate([[gestureRecognizer view] transform], [gestureRecognizer rotation]);

[gestureRecognizer view].transform = self.transformRotation;
if ( [gestureRecognizer rotation] != 0 )
self.rotate = [gestureRecognizer rotation];

[gestureRecognizer setRotation:0];


Scaling



self.transformScale = CGAffineTransformScale([[gestureRecognizer view] transform], [gestureRecognizer scale], [gestureRecognizer scale]);
[gestureRecognizer view].transform = self.transformScale;
if ( [gestureRecognizer scale] != 1 )
self.scale = [gestureRecognizer scale];

[gestureRecognizer setScale:1];


Using the Center point of the view keeps the image closer to the original location when it was saved, the first time it is loaded. Each time it is saved after that the position is the same, because the transform did not change during that session.



- (CGPoint)centerOnCanvas 
CGPoint originalCenter = self.center;
return originalCenter;


- (CGRect)frameOnCanvas
return CGRectMake(
self.preTransformedFrame.origin.x,
self.preTransformedFrame.origin.y,
self.preTransformedFrame.size.width,
self.preTransformedFrame.size.height
);


- (CGRect)preTransformedFrame
CGAffineTransform currentTransform = self.transform;
self.transform = CGAffineTransformIdentity;
CGRect originalFrame = self.bounds;
self.transform = currentTransform;
return originalFrame;



enter image description here



UPDATE: Slightly off and a little larger than the original



enter image description here










share|improve this question



















  • 1





    It's better to save Width, Height and Rotation value into UserDefaults.

    – Sachin Vas
    Mar 10 at 5:37






  • 1





    Could you show the code for rotate, scale and pan the image? If you use CGAffineTransform to make them, I don't think you need to save the frame.

    – trungduc
    Mar 13 at 5:06











  • @trungduc updated.

    – WrightsCS
    Mar 14 at 21:24













1












1








1








I need to be able to save the frame after transformation of a UIImageView. In the below example, the original frame is when the image is added to the superview. The user then has the ability to rotate, scale and pan the image anywhere in the gray area (superview).



I take these images and save their coordinates to an NSDictionary (which is not the problem). The problem is that if I get the frame after the rotation, the frame is completely off. I need to be able to store the new frame with transform in the dictionary, so that when the user comes back to this view and the images are loaded, the frames and saved transformations are just like they intended.



Panning



CGPoint translation = [gestureRecognizer translationInView:[object superview]];
if (CGRectContainsPoint(self.frame, CGPointMake([object center].x + translation.x, [object center].y + translation.y)))
[object setCenter:CGPointMake([object center].x + translation.x, [object center].y + translation.y)];
[gestureRecognizer setTranslation:CGPointZero inView:[object superview]];



Rotating



self.transformRotation = CGAffineTransformRotate([[gestureRecognizer view] transform], [gestureRecognizer rotation]);

[gestureRecognizer view].transform = self.transformRotation;
if ( [gestureRecognizer rotation] != 0 )
self.rotate = [gestureRecognizer rotation];

[gestureRecognizer setRotation:0];


Scaling



self.transformScale = CGAffineTransformScale([[gestureRecognizer view] transform], [gestureRecognizer scale], [gestureRecognizer scale]);
[gestureRecognizer view].transform = self.transformScale;
if ( [gestureRecognizer scale] != 1 )
self.scale = [gestureRecognizer scale];

[gestureRecognizer setScale:1];


Using the Center point of the view keeps the image closer to the original location when it was saved, the first time it is loaded. Each time it is saved after that the position is the same, because the transform did not change during that session.



- (CGPoint)centerOnCanvas 
CGPoint originalCenter = self.center;
return originalCenter;


- (CGRect)frameOnCanvas
return CGRectMake(
self.preTransformedFrame.origin.x,
self.preTransformedFrame.origin.y,
self.preTransformedFrame.size.width,
self.preTransformedFrame.size.height
);


- (CGRect)preTransformedFrame
CGAffineTransform currentTransform = self.transform;
self.transform = CGAffineTransformIdentity;
CGRect originalFrame = self.bounds;
self.transform = currentTransform;
return originalFrame;



enter image description here



UPDATE: Slightly off and a little larger than the original



enter image description here










share|improve this question
















I need to be able to save the frame after transformation of a UIImageView. In the below example, the original frame is when the image is added to the superview. The user then has the ability to rotate, scale and pan the image anywhere in the gray area (superview).



I take these images and save their coordinates to an NSDictionary (which is not the problem). The problem is that if I get the frame after the rotation, the frame is completely off. I need to be able to store the new frame with transform in the dictionary, so that when the user comes back to this view and the images are loaded, the frames and saved transformations are just like they intended.



Panning



CGPoint translation = [gestureRecognizer translationInView:[object superview]];
if (CGRectContainsPoint(self.frame, CGPointMake([object center].x + translation.x, [object center].y + translation.y)))
[object setCenter:CGPointMake([object center].x + translation.x, [object center].y + translation.y)];
[gestureRecognizer setTranslation:CGPointZero inView:[object superview]];



Rotating



self.transformRotation = CGAffineTransformRotate([[gestureRecognizer view] transform], [gestureRecognizer rotation]);

[gestureRecognizer view].transform = self.transformRotation;
if ( [gestureRecognizer rotation] != 0 )
self.rotate = [gestureRecognizer rotation];

[gestureRecognizer setRotation:0];


Scaling



self.transformScale = CGAffineTransformScale([[gestureRecognizer view] transform], [gestureRecognizer scale], [gestureRecognizer scale]);
[gestureRecognizer view].transform = self.transformScale;
if ( [gestureRecognizer scale] != 1 )
self.scale = [gestureRecognizer scale];

[gestureRecognizer setScale:1];


Using the Center point of the view keeps the image closer to the original location when it was saved, the first time it is loaded. Each time it is saved after that the position is the same, because the transform did not change during that session.



- (CGPoint)centerOnCanvas 
CGPoint originalCenter = self.center;
return originalCenter;


- (CGRect)frameOnCanvas
return CGRectMake(
self.preTransformedFrame.origin.x,
self.preTransformedFrame.origin.y,
self.preTransformedFrame.size.width,
self.preTransformedFrame.size.height
);


- (CGRect)preTransformedFrame
CGAffineTransform currentTransform = self.transform;
self.transform = CGAffineTransformIdentity;
CGRect originalFrame = self.bounds;
self.transform = currentTransform;
return originalFrame;



enter image description here



UPDATE: Slightly off and a little larger than the original



enter image description here







objective-c nsdictionary cgaffinetransform cgrect cgpoint






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 15 at 19:57







WrightsCS

















asked Mar 8 at 19:26









WrightsCSWrightsCS

46k21126173




46k21126173







  • 1





    It's better to save Width, Height and Rotation value into UserDefaults.

    – Sachin Vas
    Mar 10 at 5:37






  • 1





    Could you show the code for rotate, scale and pan the image? If you use CGAffineTransform to make them, I don't think you need to save the frame.

    – trungduc
    Mar 13 at 5:06











  • @trungduc updated.

    – WrightsCS
    Mar 14 at 21:24












  • 1





    It's better to save Width, Height and Rotation value into UserDefaults.

    – Sachin Vas
    Mar 10 at 5:37






  • 1





    Could you show the code for rotate, scale and pan the image? If you use CGAffineTransform to make them, I don't think you need to save the frame.

    – trungduc
    Mar 13 at 5:06











  • @trungduc updated.

    – WrightsCS
    Mar 14 at 21:24







1




1





It's better to save Width, Height and Rotation value into UserDefaults.

– Sachin Vas
Mar 10 at 5:37





It's better to save Width, Height and Rotation value into UserDefaults.

– Sachin Vas
Mar 10 at 5:37




1




1





Could you show the code for rotate, scale and pan the image? If you use CGAffineTransform to make them, I don't think you need to save the frame.

– trungduc
Mar 13 at 5:06





Could you show the code for rotate, scale and pan the image? If you use CGAffineTransform to make them, I don't think you need to save the frame.

– trungduc
Mar 13 at 5:06













@trungduc updated.

– WrightsCS
Mar 14 at 21:24





@trungduc updated.

– WrightsCS
Mar 14 at 21:24












1 Answer
1






active

oldest

votes


















3





+250









According to Apple document for UIView's transform property




When the value of this property is anything other than the identity transform, the value in the frame property is undefined and should be ignored.




That's the reason why you can't get frame after changing transform.



As I understand, after rotating, scaling or panning you want to save current state to restore later. In my opinion, all you need to do it is saving transform and center of UIImageView each time they are changed. You don't need frame in this case.



For example, _transformTarget is your UIImageView, to save its current state you can use below method (Instead of saving in a NSDictionary, I use NSUserDefaults. You can change it to NSDictionary)



- (void)saveCurrentState 
[[NSUserDefaults standardUserDefaults] setObject:NSStringFromCGAffineTransform(_transformTarget.transform) forKey:@"_transformTarget.transform"];
[[NSUserDefaults standardUserDefaults] setObject:NSStringFromCGPoint(_transformTarget.center) forKey:@"_transformTarget.center"];



At the end of each handling gesture method, save current state by using saveCurrentState.



- (void)handlePanGesture:(UIPanGestureRecognizer*)gesture 
CGPoint translation = [gesture translationInView:self.view];
CGPoint newCenter = CGPointMake(_transformTarget.center.x + translation.x, _transformTarget.center.y + translation.y);

if (CGRectContainsPoint(self.view.frame, newCenter))
_transformTarget.center = newCenter;
[gesture setTranslation:CGPointZero inView:self.view];

[self saveCurrentState]; // Save current state when center is changed



- (void)handleRotationGesture:(UIRotationGestureRecognizer*)gesture
_transformTarget.transform = CGAffineTransformRotate(_transformTarget.transform, gesture.rotation);
gesture.rotation = 0;

[self saveCurrentState]; // Save current state when transform is changed


- (void)handlePinchGesture:(UIPinchGestureRecognizer*)gesture
_transformTarget.transform = CGAffineTransformScale(_transformTarget.transform, gesture.scale, gesture.scale);
gesture.scale = 1;

[self saveCurrentState]; // Save current state when transform is changed



Now, the information about UIImageView is saved every time it's changed. At the next time user comes back, get info about center and transform from your dictionary and set them again.



- (void)restoreFromSavedState 
NSString *transformString = [[NSUserDefaults standardUserDefaults] objectForKey:@"_transformTarget.transform"];
CGAffineTransform transform = transformString ? CGAffineTransformFromString(transformString) : CGAffineTransformIdentity;

NSString *centerString = [[NSUserDefaults standardUserDefaults] objectForKey:@"_transformTarget.center"];
CGPoint center = centerString ? CGPointFromString(centerString) : self.view.center;

_transformTarget.center = center;
_transformTarget.transform = transform;



Result





For more detail, you can take a look at my sample repo
https://github.com/trungducc/stackoverflow/tree/restore-view-transform






share|improve this answer























  • This example makes a ton of sense now, seeing that I tried to concat rotation and scale... so applying just the final transformation and saving that looks like it is working for you. I tried to simplify my code down , but I am still having some issues with the coordinates being off. Wondering if that's because the gesture code is in my object (UIImageView in your case) class, and not the superview itself. I am basing it off of the superview frame, so I dont see why that would be an issue.

    – WrightsCS
    Mar 15 at 18:53












  • @WrightsCS I’m not sure what you are talking about. Could you explain a little bit about “the coordinates being off”? I dont think that handle gestures in the object class will lead to any issue. If you want me to handle everything inside object class, I will try to make it

    – trungduc
    Mar 15 at 19:15











  • See the updated image in the original question, slightly larger images and frame is a little off, but I checked the transform and center strings when saved and when retrieved, and they are the same, so not sure why the difference!

    – WrightsCS
    Mar 15 at 19:55






  • 1





    Yes, of course. In my opinion, you shouldnt use autolayout in this case. I think auto layout is the reason for your problem

    – trungduc
    Mar 16 at 16:56






  • 1





    @WrightsCS I think you still can you constraints for canvas view. But try to call layoutIfNeeded before applying center and transform for objects inside to make sure canvas's frame won't be changed after (Which can lead to the problem)

    – trungduc
    Mar 17 at 4:56











Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55069753%2frestoring-cgrect-with-transform-values-from-nsdictionary%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









3





+250









According to Apple document for UIView's transform property




When the value of this property is anything other than the identity transform, the value in the frame property is undefined and should be ignored.




That's the reason why you can't get frame after changing transform.



As I understand, after rotating, scaling or panning you want to save current state to restore later. In my opinion, all you need to do it is saving transform and center of UIImageView each time they are changed. You don't need frame in this case.



For example, _transformTarget is your UIImageView, to save its current state you can use below method (Instead of saving in a NSDictionary, I use NSUserDefaults. You can change it to NSDictionary)



- (void)saveCurrentState 
[[NSUserDefaults standardUserDefaults] setObject:NSStringFromCGAffineTransform(_transformTarget.transform) forKey:@"_transformTarget.transform"];
[[NSUserDefaults standardUserDefaults] setObject:NSStringFromCGPoint(_transformTarget.center) forKey:@"_transformTarget.center"];



At the end of each handling gesture method, save current state by using saveCurrentState.



- (void)handlePanGesture:(UIPanGestureRecognizer*)gesture 
CGPoint translation = [gesture translationInView:self.view];
CGPoint newCenter = CGPointMake(_transformTarget.center.x + translation.x, _transformTarget.center.y + translation.y);

if (CGRectContainsPoint(self.view.frame, newCenter))
_transformTarget.center = newCenter;
[gesture setTranslation:CGPointZero inView:self.view];

[self saveCurrentState]; // Save current state when center is changed



- (void)handleRotationGesture:(UIRotationGestureRecognizer*)gesture
_transformTarget.transform = CGAffineTransformRotate(_transformTarget.transform, gesture.rotation);
gesture.rotation = 0;

[self saveCurrentState]; // Save current state when transform is changed


- (void)handlePinchGesture:(UIPinchGestureRecognizer*)gesture
_transformTarget.transform = CGAffineTransformScale(_transformTarget.transform, gesture.scale, gesture.scale);
gesture.scale = 1;

[self saveCurrentState]; // Save current state when transform is changed



Now, the information about UIImageView is saved every time it's changed. At the next time user comes back, get info about center and transform from your dictionary and set them again.



- (void)restoreFromSavedState 
NSString *transformString = [[NSUserDefaults standardUserDefaults] objectForKey:@"_transformTarget.transform"];
CGAffineTransform transform = transformString ? CGAffineTransformFromString(transformString) : CGAffineTransformIdentity;

NSString *centerString = [[NSUserDefaults standardUserDefaults] objectForKey:@"_transformTarget.center"];
CGPoint center = centerString ? CGPointFromString(centerString) : self.view.center;

_transformTarget.center = center;
_transformTarget.transform = transform;



Result





For more detail, you can take a look at my sample repo
https://github.com/trungducc/stackoverflow/tree/restore-view-transform






share|improve this answer























  • This example makes a ton of sense now, seeing that I tried to concat rotation and scale... so applying just the final transformation and saving that looks like it is working for you. I tried to simplify my code down , but I am still having some issues with the coordinates being off. Wondering if that's because the gesture code is in my object (UIImageView in your case) class, and not the superview itself. I am basing it off of the superview frame, so I dont see why that would be an issue.

    – WrightsCS
    Mar 15 at 18:53












  • @WrightsCS I’m not sure what you are talking about. Could you explain a little bit about “the coordinates being off”? I dont think that handle gestures in the object class will lead to any issue. If you want me to handle everything inside object class, I will try to make it

    – trungduc
    Mar 15 at 19:15











  • See the updated image in the original question, slightly larger images and frame is a little off, but I checked the transform and center strings when saved and when retrieved, and they are the same, so not sure why the difference!

    – WrightsCS
    Mar 15 at 19:55






  • 1





    Yes, of course. In my opinion, you shouldnt use autolayout in this case. I think auto layout is the reason for your problem

    – trungduc
    Mar 16 at 16:56






  • 1





    @WrightsCS I think you still can you constraints for canvas view. But try to call layoutIfNeeded before applying center and transform for objects inside to make sure canvas's frame won't be changed after (Which can lead to the problem)

    – trungduc
    Mar 17 at 4:56















3





+250









According to Apple document for UIView's transform property




When the value of this property is anything other than the identity transform, the value in the frame property is undefined and should be ignored.




That's the reason why you can't get frame after changing transform.



As I understand, after rotating, scaling or panning you want to save current state to restore later. In my opinion, all you need to do it is saving transform and center of UIImageView each time they are changed. You don't need frame in this case.



For example, _transformTarget is your UIImageView, to save its current state you can use below method (Instead of saving in a NSDictionary, I use NSUserDefaults. You can change it to NSDictionary)



- (void)saveCurrentState 
[[NSUserDefaults standardUserDefaults] setObject:NSStringFromCGAffineTransform(_transformTarget.transform) forKey:@"_transformTarget.transform"];
[[NSUserDefaults standardUserDefaults] setObject:NSStringFromCGPoint(_transformTarget.center) forKey:@"_transformTarget.center"];



At the end of each handling gesture method, save current state by using saveCurrentState.



- (void)handlePanGesture:(UIPanGestureRecognizer*)gesture 
CGPoint translation = [gesture translationInView:self.view];
CGPoint newCenter = CGPointMake(_transformTarget.center.x + translation.x, _transformTarget.center.y + translation.y);

if (CGRectContainsPoint(self.view.frame, newCenter))
_transformTarget.center = newCenter;
[gesture setTranslation:CGPointZero inView:self.view];

[self saveCurrentState]; // Save current state when center is changed



- (void)handleRotationGesture:(UIRotationGestureRecognizer*)gesture
_transformTarget.transform = CGAffineTransformRotate(_transformTarget.transform, gesture.rotation);
gesture.rotation = 0;

[self saveCurrentState]; // Save current state when transform is changed


- (void)handlePinchGesture:(UIPinchGestureRecognizer*)gesture
_transformTarget.transform = CGAffineTransformScale(_transformTarget.transform, gesture.scale, gesture.scale);
gesture.scale = 1;

[self saveCurrentState]; // Save current state when transform is changed



Now, the information about UIImageView is saved every time it's changed. At the next time user comes back, get info about center and transform from your dictionary and set them again.



- (void)restoreFromSavedState 
NSString *transformString = [[NSUserDefaults standardUserDefaults] objectForKey:@"_transformTarget.transform"];
CGAffineTransform transform = transformString ? CGAffineTransformFromString(transformString) : CGAffineTransformIdentity;

NSString *centerString = [[NSUserDefaults standardUserDefaults] objectForKey:@"_transformTarget.center"];
CGPoint center = centerString ? CGPointFromString(centerString) : self.view.center;

_transformTarget.center = center;
_transformTarget.transform = transform;



Result





For more detail, you can take a look at my sample repo
https://github.com/trungducc/stackoverflow/tree/restore-view-transform






share|improve this answer























  • This example makes a ton of sense now, seeing that I tried to concat rotation and scale... so applying just the final transformation and saving that looks like it is working for you. I tried to simplify my code down , but I am still having some issues with the coordinates being off. Wondering if that's because the gesture code is in my object (UIImageView in your case) class, and not the superview itself. I am basing it off of the superview frame, so I dont see why that would be an issue.

    – WrightsCS
    Mar 15 at 18:53












  • @WrightsCS I’m not sure what you are talking about. Could you explain a little bit about “the coordinates being off”? I dont think that handle gestures in the object class will lead to any issue. If you want me to handle everything inside object class, I will try to make it

    – trungduc
    Mar 15 at 19:15











  • See the updated image in the original question, slightly larger images and frame is a little off, but I checked the transform and center strings when saved and when retrieved, and they are the same, so not sure why the difference!

    – WrightsCS
    Mar 15 at 19:55






  • 1





    Yes, of course. In my opinion, you shouldnt use autolayout in this case. I think auto layout is the reason for your problem

    – trungduc
    Mar 16 at 16:56






  • 1





    @WrightsCS I think you still can you constraints for canvas view. But try to call layoutIfNeeded before applying center and transform for objects inside to make sure canvas's frame won't be changed after (Which can lead to the problem)

    – trungduc
    Mar 17 at 4:56













3





+250







3





+250



3




+250





According to Apple document for UIView's transform property




When the value of this property is anything other than the identity transform, the value in the frame property is undefined and should be ignored.




That's the reason why you can't get frame after changing transform.



As I understand, after rotating, scaling or panning you want to save current state to restore later. In my opinion, all you need to do it is saving transform and center of UIImageView each time they are changed. You don't need frame in this case.



For example, _transformTarget is your UIImageView, to save its current state you can use below method (Instead of saving in a NSDictionary, I use NSUserDefaults. You can change it to NSDictionary)



- (void)saveCurrentState 
[[NSUserDefaults standardUserDefaults] setObject:NSStringFromCGAffineTransform(_transformTarget.transform) forKey:@"_transformTarget.transform"];
[[NSUserDefaults standardUserDefaults] setObject:NSStringFromCGPoint(_transformTarget.center) forKey:@"_transformTarget.center"];



At the end of each handling gesture method, save current state by using saveCurrentState.



- (void)handlePanGesture:(UIPanGestureRecognizer*)gesture 
CGPoint translation = [gesture translationInView:self.view];
CGPoint newCenter = CGPointMake(_transformTarget.center.x + translation.x, _transformTarget.center.y + translation.y);

if (CGRectContainsPoint(self.view.frame, newCenter))
_transformTarget.center = newCenter;
[gesture setTranslation:CGPointZero inView:self.view];

[self saveCurrentState]; // Save current state when center is changed



- (void)handleRotationGesture:(UIRotationGestureRecognizer*)gesture
_transformTarget.transform = CGAffineTransformRotate(_transformTarget.transform, gesture.rotation);
gesture.rotation = 0;

[self saveCurrentState]; // Save current state when transform is changed


- (void)handlePinchGesture:(UIPinchGestureRecognizer*)gesture
_transformTarget.transform = CGAffineTransformScale(_transformTarget.transform, gesture.scale, gesture.scale);
gesture.scale = 1;

[self saveCurrentState]; // Save current state when transform is changed



Now, the information about UIImageView is saved every time it's changed. At the next time user comes back, get info about center and transform from your dictionary and set them again.



- (void)restoreFromSavedState 
NSString *transformString = [[NSUserDefaults standardUserDefaults] objectForKey:@"_transformTarget.transform"];
CGAffineTransform transform = transformString ? CGAffineTransformFromString(transformString) : CGAffineTransformIdentity;

NSString *centerString = [[NSUserDefaults standardUserDefaults] objectForKey:@"_transformTarget.center"];
CGPoint center = centerString ? CGPointFromString(centerString) : self.view.center;

_transformTarget.center = center;
_transformTarget.transform = transform;



Result





For more detail, you can take a look at my sample repo
https://github.com/trungducc/stackoverflow/tree/restore-view-transform






share|improve this answer













According to Apple document for UIView's transform property




When the value of this property is anything other than the identity transform, the value in the frame property is undefined and should be ignored.




That's the reason why you can't get frame after changing transform.



As I understand, after rotating, scaling or panning you want to save current state to restore later. In my opinion, all you need to do it is saving transform and center of UIImageView each time they are changed. You don't need frame in this case.



For example, _transformTarget is your UIImageView, to save its current state you can use below method (Instead of saving in a NSDictionary, I use NSUserDefaults. You can change it to NSDictionary)



- (void)saveCurrentState 
[[NSUserDefaults standardUserDefaults] setObject:NSStringFromCGAffineTransform(_transformTarget.transform) forKey:@"_transformTarget.transform"];
[[NSUserDefaults standardUserDefaults] setObject:NSStringFromCGPoint(_transformTarget.center) forKey:@"_transformTarget.center"];



At the end of each handling gesture method, save current state by using saveCurrentState.



- (void)handlePanGesture:(UIPanGestureRecognizer*)gesture 
CGPoint translation = [gesture translationInView:self.view];
CGPoint newCenter = CGPointMake(_transformTarget.center.x + translation.x, _transformTarget.center.y + translation.y);

if (CGRectContainsPoint(self.view.frame, newCenter))
_transformTarget.center = newCenter;
[gesture setTranslation:CGPointZero inView:self.view];

[self saveCurrentState]; // Save current state when center is changed



- (void)handleRotationGesture:(UIRotationGestureRecognizer*)gesture
_transformTarget.transform = CGAffineTransformRotate(_transformTarget.transform, gesture.rotation);
gesture.rotation = 0;

[self saveCurrentState]; // Save current state when transform is changed


- (void)handlePinchGesture:(UIPinchGestureRecognizer*)gesture
_transformTarget.transform = CGAffineTransformScale(_transformTarget.transform, gesture.scale, gesture.scale);
gesture.scale = 1;

[self saveCurrentState]; // Save current state when transform is changed



Now, the information about UIImageView is saved every time it's changed. At the next time user comes back, get info about center and transform from your dictionary and set them again.



- (void)restoreFromSavedState 
NSString *transformString = [[NSUserDefaults standardUserDefaults] objectForKey:@"_transformTarget.transform"];
CGAffineTransform transform = transformString ? CGAffineTransformFromString(transformString) : CGAffineTransformIdentity;

NSString *centerString = [[NSUserDefaults standardUserDefaults] objectForKey:@"_transformTarget.center"];
CGPoint center = centerString ? CGPointFromString(centerString) : self.view.center;

_transformTarget.center = center;
_transformTarget.transform = transform;



Result





For more detail, you can take a look at my sample repo
https://github.com/trungducc/stackoverflow/tree/restore-view-transform







share|improve this answer












share|improve this answer



share|improve this answer










answered Mar 15 at 8:23









trungductrungduc

9,04341741




9,04341741












  • This example makes a ton of sense now, seeing that I tried to concat rotation and scale... so applying just the final transformation and saving that looks like it is working for you. I tried to simplify my code down , but I am still having some issues with the coordinates being off. Wondering if that's because the gesture code is in my object (UIImageView in your case) class, and not the superview itself. I am basing it off of the superview frame, so I dont see why that would be an issue.

    – WrightsCS
    Mar 15 at 18:53












  • @WrightsCS I’m not sure what you are talking about. Could you explain a little bit about “the coordinates being off”? I dont think that handle gestures in the object class will lead to any issue. If you want me to handle everything inside object class, I will try to make it

    – trungduc
    Mar 15 at 19:15











  • See the updated image in the original question, slightly larger images and frame is a little off, but I checked the transform and center strings when saved and when retrieved, and they are the same, so not sure why the difference!

    – WrightsCS
    Mar 15 at 19:55






  • 1





    Yes, of course. In my opinion, you shouldnt use autolayout in this case. I think auto layout is the reason for your problem

    – trungduc
    Mar 16 at 16:56






  • 1





    @WrightsCS I think you still can you constraints for canvas view. But try to call layoutIfNeeded before applying center and transform for objects inside to make sure canvas's frame won't be changed after (Which can lead to the problem)

    – trungduc
    Mar 17 at 4:56

















  • This example makes a ton of sense now, seeing that I tried to concat rotation and scale... so applying just the final transformation and saving that looks like it is working for you. I tried to simplify my code down , but I am still having some issues with the coordinates being off. Wondering if that's because the gesture code is in my object (UIImageView in your case) class, and not the superview itself. I am basing it off of the superview frame, so I dont see why that would be an issue.

    – WrightsCS
    Mar 15 at 18:53












  • @WrightsCS I’m not sure what you are talking about. Could you explain a little bit about “the coordinates being off”? I dont think that handle gestures in the object class will lead to any issue. If you want me to handle everything inside object class, I will try to make it

    – trungduc
    Mar 15 at 19:15











  • See the updated image in the original question, slightly larger images and frame is a little off, but I checked the transform and center strings when saved and when retrieved, and they are the same, so not sure why the difference!

    – WrightsCS
    Mar 15 at 19:55






  • 1





    Yes, of course. In my opinion, you shouldnt use autolayout in this case. I think auto layout is the reason for your problem

    – trungduc
    Mar 16 at 16:56






  • 1





    @WrightsCS I think you still can you constraints for canvas view. But try to call layoutIfNeeded before applying center and transform for objects inside to make sure canvas's frame won't be changed after (Which can lead to the problem)

    – trungduc
    Mar 17 at 4:56
















This example makes a ton of sense now, seeing that I tried to concat rotation and scale... so applying just the final transformation and saving that looks like it is working for you. I tried to simplify my code down , but I am still having some issues with the coordinates being off. Wondering if that's because the gesture code is in my object (UIImageView in your case) class, and not the superview itself. I am basing it off of the superview frame, so I dont see why that would be an issue.

– WrightsCS
Mar 15 at 18:53






This example makes a ton of sense now, seeing that I tried to concat rotation and scale... so applying just the final transformation and saving that looks like it is working for you. I tried to simplify my code down , but I am still having some issues with the coordinates being off. Wondering if that's because the gesture code is in my object (UIImageView in your case) class, and not the superview itself. I am basing it off of the superview frame, so I dont see why that would be an issue.

– WrightsCS
Mar 15 at 18:53














@WrightsCS I’m not sure what you are talking about. Could you explain a little bit about “the coordinates being off”? I dont think that handle gestures in the object class will lead to any issue. If you want me to handle everything inside object class, I will try to make it

– trungduc
Mar 15 at 19:15





@WrightsCS I’m not sure what you are talking about. Could you explain a little bit about “the coordinates being off”? I dont think that handle gestures in the object class will lead to any issue. If you want me to handle everything inside object class, I will try to make it

– trungduc
Mar 15 at 19:15













See the updated image in the original question, slightly larger images and frame is a little off, but I checked the transform and center strings when saved and when retrieved, and they are the same, so not sure why the difference!

– WrightsCS
Mar 15 at 19:55





See the updated image in the original question, slightly larger images and frame is a little off, but I checked the transform and center strings when saved and when retrieved, and they are the same, so not sure why the difference!

– WrightsCS
Mar 15 at 19:55




1




1





Yes, of course. In my opinion, you shouldnt use autolayout in this case. I think auto layout is the reason for your problem

– trungduc
Mar 16 at 16:56





Yes, of course. In my opinion, you shouldnt use autolayout in this case. I think auto layout is the reason for your problem

– trungduc
Mar 16 at 16:56




1




1





@WrightsCS I think you still can you constraints for canvas view. But try to call layoutIfNeeded before applying center and transform for objects inside to make sure canvas's frame won't be changed after (Which can lead to the problem)

– trungduc
Mar 17 at 4:56





@WrightsCS I think you still can you constraints for canvas view. But try to call layoutIfNeeded before applying center and transform for objects inside to make sure canvas's frame won't be changed after (Which can lead to the problem)

– trungduc
Mar 17 at 4:56



















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55069753%2frestoring-cgrect-with-transform-values-from-nsdictionary%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Identity Server 4 is not redirecting to Angular app after login2019 Community Moderator ElectionIdentity Server 4 and dockerIdentityserver implicit flow unauthorized_clientIdentityServer Hybrid Flow - Access Token is null after user successful loginIdentity Server to MVC client : Page Redirect After loginLogin with Steam OpenId(oidc-client-js)Identity Server 4+.NET Core 2.0 + IdentityIdentityServer4 post-login redirect not working in Edge browserCall to IdentityServer4 generates System.NullReferenceException: Object reference not set to an instance of an objectIdentityServer4 without HTTPS not workingHow to get Authorization code from identity server without login form

2005 Ahvaz unrest Contents Background Causes Casualties Aftermath See also References Navigation menue"At Least 10 Are Killed by Bombs in Iran""Iran"Archived"Arab-Iranians in Iran to make April 15 'Day of Fury'"State of Mind, State of Order: Reactions to Ethnic Unrest in the Islamic Republic of Iran.10.1111/j.1754-9469.2008.00028.x"Iran hangs Arab separatists"Iran Overview from ArchivedConstitution of the Islamic Republic of Iran"Tehran puzzled by forged 'riots' letter""Iran and its minorities: Down in the second class""Iran: Handling Of Ahvaz Unrest Could End With Televised Confessions""Bombings Rock Iran Ahead of Election""Five die in Iran ethnic clashes""Iran: Need for restraint as anniversary of unrest in Khuzestan approaches"Archived"Iranian Sunni protesters killed in clashes with security forces"Archived

Can't initialize raids on a new ASUS Prime B360M-A motherboard2019 Community Moderator ElectionSimilar to RAID config yet more like mirroring solution?Can't get motherboard serial numberWhy does the BIOS entry point start with a WBINVD instruction?UEFI performance Asus Maximus V Extreme