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

Thal And Out Agency railway station See also References External links Navigation menuOfficial Web Site of Pakistan RailwaysArchivedOfficial Web Site of Pakistan Railwayseeexpanding ite

Posting a File and Associated Data to a RESTful WebService preferably as JSON2019 Community Moderator ElectionREST URI convention - Singular or plural name of resource while creating itUploading both data and files in one form using Ajax?How do I upload a file with metadata using a REST web service?REST API - file (ie images) processing - best practicesSpring: JSON data and file in the same requestREST API Put large dataPosting a file and JSON data to Spring rest serviceRESTful Web Service Upload/Download Large Data With JSONREST API Design sending JSON data and a file to the api in same requestPost JSONArray to REST servicePUT vs. POST in RESTParsing values from a JSON file?JavaScript/jQuery to download file via POST with JSON dataHow do I upload a file with metadata using a REST web service?How to POST JSON data with Curl from Terminal/Commandline to Test Spring REST?Separate REST JSON API server and client?what's the correct way to send a file from REST web service to client?How do I write JSON data to a file?What is “406-Not Acceptable Response” in HTTP?REST API - file (ie images) processing - best practices

How can I change the color of pagination dots of UIPageControl?How to change UIPageControl dotsIs there a way to change page indicator dots colorCustomize dot with image of UIPageControl at index 0 of UIPageControlNo visible @interface for 'NSObject<PageControlDelegate>' declares the selector 'pageControlPageDidChange:'How to change the color of pagination dots in UIPageControl with a different color per pagepagecontrol indicator custom image instead of DefaultChanging the colour of UIPageControl dots in MonoTouchpagecontrol selectable page visibility color?Alternative way to load ViewControllers on a UIPageControlHow to set only layer.border-color for UIpage control dots in swiftHow can I develop for iPhone using a Windows development machine?How to change the name of an iOS app?UITableView - change section header coloruipagecontrol indicator(dot)issueCustom UIPageControl dots color not changingchange the interspace between UIPageControl dotsHow to change Status Bar text color in iOSHow can I change image tintColor in iOS and WatchKitUIPageControl dots with larger space in between each dotsHow to change the color of pagination dots in UIPageControl with a different color per page