2012-06-13 11 views
5

मैं पैन, चुटकी, और यूआईजीएस्टर रिकॉग्नाइज़र को घुमाता हूं ताकि उपयोगकर्ता को कुछ यूआई तत्वों को ठीक से रखा जा सके जहां वे चाहते हैं। http://www.raywenderlich.com/6567/uigesturerecognizer-tutorial-in-ios-5-pinches-pans-and-more से कोड का उपयोग करना (या http://mobile.tutsplus.com/tutorials/iphone/uigesturerecognizer/ से इसी तरह का कोड) दोनों मुझे यह बताते हैं कि उपयोगकर्ता को इन UI तत्वों को अपनी इच्छानुसार रखने के लिए क्या चाहिए।लोडिंग UIView ट्रांसफॉर्म और सेटिंग्स से केंद्र अलग-अलग स्थिति

उपयोगकर्ता बाहर निकलता है "यूआई लेआउट" मोड, मैं सहेजते हैं UIView के बदलने और इतने की तरह केंद्र:

NSString *transformString = NSStringFromCGAffineTransform(self.transform); 
[[NSUserDefaults standardUserDefaults] setObject:transformString forKey:@"UItransform", suffix]]; 

NSString *centerString = NSStringFromCGPoint(self.center); 
[[NSUserDefaults standardUserDefaults] setObject:centerString forKey:@"UIcenter"]; 

मैं एप्लिकेशन को फिर से लोड करते हैं, मैंने पढ़ा UIView के बदलने और इतने की तरह केंद्र:

NSString *centerString = [[NSUserDefaults standardUserDefaults] objectForKey:@"UIcenter"]; 
if(centerString != nil) 
    self.center = CGPointFromString(centerString); 

NSString *transformString = [[NSUserDefaults standardUserDefaults] objectForKey:@"UItransform"]; 

if(transformString != nil) 
    self.transform = CGAffineTransformFromString(transformString); 

और UIView घूमता है और सही ढंग से स्केल किया जाता है, लेकिन गलत जगह पर। इसके अलावा, फिर से "यूआई लेआउट" मोड दर्ज करने पर, मैं हमेशा विभिन्न संकेतों के साथ दृश्य को नहीं पकड़ सकता (जैसा कि प्रदर्शित किया गया दृश्य इशारा पहचानकर्ता द्वारा समझा गया दृश्य नहीं है?)

मेरे पास भी है रीसेट बटन जो पहचान के लिए UIView के transform और उसके center को एनआईबी से लोड होने पर जो भी हो, सेट करता है। लेकिन परिवर्तित UIView केंद्र लोड करने और बदलने के बाद, रीसेट भी काम नहीं करता है। UIView की स्थिति गलत है।

मेरा पहला विचार यह था कि चूंकि उन इशारा कोड उदाहरण center बदलते हैं, इसलिए यह घूर्णन विभिन्न केंद्रों के आसपास हो रहा है (चाल, घूर्णन और तराजू के कुछ अप्रत्याशित अनुक्रम को मानते हुए)। चूंकि मैं संपादन के पूरे अनुक्रम को सहेजना नहीं चाहता (हालांकि यह आसान हो सकता है अगर मैं लेआउट मोड में कुछ पूर्ववत फीचर रखना चाहता हूं), मैंने इसे स्थानांतरित करने के लिए ट्रांसफॉर्म का उपयोग करने के लिए यूआईपीएनजेस्टर रिकॉग्नाइज़र हैंडलर को बदल दिया। एक बार जब मैं काम कर रहा हूं, तो मुझे लगता है कि ट्रांसफॉर्म को बचाने से मुझे वर्तमान स्थान और अभिविन्यास मिलेगा, भले ही आदेश क्या हुआ। लेकिन ऐसी कोई किस्मत नहीं है। मुझे अभी भी इस तरह एक निराशाजनक स्थिति मिलती है।

तो मुझे नुकसान हुआ है। यदि कोई UIView स्थानांतरित हो गया है और एक नई स्थिति में घुमाया गया है, तो मैं उस स्थान और अभिविन्यास को इस तरीके से कैसे सहेज सकता हूं कि मैं इसे बाद में लोड कर सकूं और UIView को वापस कहां से प्राप्त कर सकूं?

अगर मैंने इस अधिकार को टैग नहीं किया है या इसे सही तरीके से नहीं रखा है या कुछ अन्य स्टैक ओवरफ्लो पाप नहीं किया है, तो पहले से क्षमा करें। यह पहली बार है जब मैंने यहां पोस्ट किया है।

EDIT

मैं अब तक दो सुझावों का प्रयास कर रहा हूं। मुझे लगता है कि वे प्रभावी रूप से एक ही चीज हैं (एक फ्रेम को बचाने का सुझाव देता है और दूसरा मूल को बचाने का सुझाव देता है, जो मुझे लगता है कि फ्रेम.ऑरिगिन है)।

तो अब प्रीफ़्स कोड से सेव/लोड में निम्नलिखित शामिल हैं।

सहेजें:

NSString *originString = NSStringFromCGPoint(self.frame.origin); 
[[NSUserDefaults standardUserDefaults] setObject:originString forKey:@"UIorigin"]; 

लोड ( बदलने लोड करने से पहले):

NSString *originString = [[NSUserDefaults standardUserDefaults] objectForKey:@"UIorigin"]; 
if(originString) { 
    CGPoint origin = CGPointFromString(originString); 
    self.frame = CGRectMake(origin.x, origin.y, self.frame.size.width, self.frame.size.height); 
} 

मैं एक ही मिलता है (या इसी तरह - यह बताने के लिए मुश्किल है) परिणाम। वास्तव में, मैंने केवल prefs को पुनः लोड करने के लिए एक बटन जोड़ा, और एक बार दृश्य घुमाए जाने के बाद, "रीलोड" बटन बार-बार ऑफसेट द्वारा UIView को स्थानांतरित कर देगा (हालांकि फ्रेम या ट्रांसफॉर्म स्वयं के सापेक्ष हैं - जो मुझे यकीन है एक सुराग है, लेकिन मुझे यकीन नहीं है कि यह क्या इंगित कर रहा है)।

संपादित करें # 2

यह मैं दृश्य के frame पर निर्भर करता है के बारे में चिंता करता है। एप्पल http://developer.apple.com/library/ios/#documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/WindowsandViews/WindowsandViews.html#//apple_ref/doc/uid/TP40009503-CH2-SW6 (जोर मेरा) से:

केंद्र संपत्ति में मूल्य हमेशा वैध है, भले ही स्केलिंग या रोटेशन कारकों को देखने के बदलने के लिए जोड़ा गया है। फ्रेम प्रॉपर्टी में मान के लिए भी यह सच नहीं है, जिसे अमान्य माना जाता है यदि दृश्य का रूपांतरण पहचान परिवर्तन के बराबर नहीं है।

संपादित # 3

ठीक है, तो जब मैं में वरीयता लोड हो रहा हूँ, सब कुछ ठीक लग रहा है। यूआई पैनल का bounds रेक्ट {{0, 0}, {506, 254}} है। मेरे वीसी के दृश्य के अंत में डिडलोड विधि, अभी भी ठीक लगता है। लेकिन जब तक चीजें वास्तव में प्रदर्शित होती हैं, bounds कुछ और है। उदाहरण के लिए: {{0, 0}, {488.321, 435.981}} (ऐसा लगता है कि एक बार घुमाए जाने और स्केल किए जाने पर इसके पर्यवेक्षण में कितना बड़ा है)। यदि मैं सीमाओं को रीसेट करता हूं जो इसे माना जाता है, तो यह वापस स्थानांतरित हो जाता है।

सीमाओं को रीसेट करने के लिए पर्याप्त है जो उन्हें प्रोग्रामेटिक रूप से माना जाता है, लेकिन मुझे वास्तव में यह सुनिश्चित नहीं है कि यह कब करना है! मैंने इसेडिडलोड के अंत में ऐसा करने के लिए सोचा होगा, लेकिन उस बिंदु पर bounds अभी भी सही है।

संपादित करें # 4

मैं layoutSubviews में initWithCoder में self.bounds पर कब्जा (के रूप में यह एक निब से आ रहा है) की कोशिश की, और फिर, कि कब्जा कर लिया CGRect को self.bounds को रीसेट। और वह काम करता है।

लेकिन यह खतरनाक हैकी और खतरे से भरा हुआ लगता है। यह वास्तव में ऐसा करने का सही तरीका नहीं हो सकता है। (क्या यह हो सकता है?) नीचे स्क्रैम का उत्तर इतना सरल लगता है, लेकिन ऐप फिर से लोड होने पर मेरे लिए काम नहीं करता है।

+0

ग्रेट पहला सवाल! एसओ में आपका स्वागत है! – jrturton

+0

धन्यवाद, jrturton :) तो वास्तव में कुछ और है। तथ्य यह है कि मुझे मिनटों के भीतर दो जवाब मिल गए (भले ही मैं अभी तक सफल नहीं हुआ हूं) बस शानदार है! – sbkp

+0

संभवतः आप घूर्णन/ज़ूम के लिए स्केल और रोटेशन ट्रांसफॉर्म के संयोजन का उपयोग कर रहे हैं, और बस पैन के लिए केंद्र को ले जा रहे हैं? – jrturton

उत्तर

0

उत्तर देने वाले सभी लोगों के लिए धन्यवाद! उन सभी के योग ने मुझे निम्नलिखित का नेतृत्व किया:

समस्या यह है कि bounds सीजीआरईटी को स्टार्टअप पर वरीयताओं से परिवर्तन लोड करने के बाद रीसेट किया जा रहा था, लेकिन वास्तविक समय में संशोधित करते समय वरीयताओं को अद्यतन करते समय नहीं।

मुझे लगता है कि दो समाधान हैं। सबसे पहले viewDidLoad के बजाय layoutSubviews से वरीयताओं को लोड करना होगा। layoutSubviews के बाद bounds पर कुछ भी नहीं लगता है।

मेरे ऐप के अन्य कारणों के लिए, हालांकि, व्यू कंट्रोलर के viewDidLoad से वरीयताओं को लोड करना अधिक सुविधाजनक है। तो मैं जिस समाधान का उपयोग कर रहा हूं वह यह है:

// UserTransformableView.h 
@interface UserTransformableView : UIView { 
    CGRect defaultBounds; 
} 

// UserTransformableView.m 
- (id)initWithCoder:(NSCoder *)aDecoder { 
    self = [super initWithCoder:aDecoder]; 
    if(self) { 
     defaultBounds = self.bounds; 
    } 
    return self; 
} 

- (void)layoutSubviews { 
    self.bounds = defaultBounds; 
} 
2

आप frame संपत्ति को भी सहेज लेंगे। आप NSStringFromCGRect() और CGRectFromString() का उपयोग कर सकते हैं।

लोड करते समय, फ्रेम सेट करें और फिर अपना परिवर्तन लागू करें। इस तरह मैं इसे अपने ऐप्स में से एक में करता हूं।

उम्मीद है कि इससे मदद मिलती है।

अद्यतन: मेरे मामले में, मुझे खींचने योग्य UIViews घूर्णन और आकार बदलने के लिए आवेदन किया जा सकता है। मैं अपनी वस्तुओं को सहेजने और लोड करने के लिए NSCoding का उपयोग करता हूं, उदाहरण नीचे।

//encoding 
.... 
[coder encodeCGRect:self.frame forKey:@"rect"]; 
// you can save with NSStringFromCGRect(self.frame); 
[coder encodeObject:NSStringFromCGAffineTransform(self.transform) forKey:@"savedTransform"]; 

//init-coder 
CGRect frame = [coder decodeCGRectForKey:@"rect"]; 
// you can use frame = CGRectFromString(/*load string*/); 
[self setFrame:frame]; 
self.transform = CGAffineTransformFromString([coder decodeObjectForKey:@"savedTransform"]); 

यह मेरे फ्रेम को बदलने और बदलने के लिए क्या करता है, और आवश्यकता होने पर उन्हें लोड करता है। उसी विधि को NSStringFromCGRect() और CGRectFromString() के साथ लागू किया जा सकता है।

अद्यतन 2: आपके मामले में। आप कुछ इस तरह करना होगा ..

[self setFrame:CGRectFromString([[NSUserDefaults standardUserDefaults] valueForKey:@"UIFrame"])]; 
self.transform = CGAffineTransformFromString([[NSUserDefaults standardUserDefaults] valueForKey:@"transform"]); 

मान लिया जाये कि आप transform कुंजी UIFrame साथ NSUserDefaults लिए बचत कर रहे हैं, और।

+0

धन्यवाद, स्कैम। मुझे लगता है कि आपका सुझाव अनिवार्य रूप से डियानज़ जैसा ही है, है ना? उन्होंने दृश्य (संभवतः फ्रेम) मूल को बचाने का सुझाव दिया। चाहे उसके सुझाव या तुम्हारा (जैसा कि मैंने इसे समझा) के साथ, मुझे अभी भी एक भयानक परिणाम मिल गया है। यदि यह पूछने के लिए बहुत कुछ नहीं है, तो क्या आप मुझे सही दिशा में धक्का देने के लिए एक कोड स्निपेट पोस्ट करने में सक्षम होंगे? – sbkp

+0

ने एक उदाहरण जोड़ा है कि मैं एक ही दृष्टिकोण का उपयोग कैसे करता हूं। – skram

+0

धन्यवाद! मुझे अभी भी एक ही परिणाम मिल रहा है। लेकिन मुझे यहां कुछ जांचने दो। मैं इसके लिए एनएससीओडी के बिना एनएसयूसर डीफॉल्ट का उपयोग कर रहा हूं। तो मेरा सेव कोड (उदाहरण के लिए) आपके से अलग है, जैसे: '[[NSUserDefaults standardUserDefaults] NSStringFromCGRect (self.frame) के लिए: @" UIframe "]; [[NSUserDefaults standardUserDefaults] NSStringFromCGAffineTransform (self.transform) के लिए: @ "UItransform"]; ' ऐसा लगता है कि आप जो कर रहे हैं (है ना?) – sbkp

1

तुम भी UIView के स्थान को बचाने चाहिए,

CGPoint position = CGPointMake(self.view.origin.x, self.view.origin.y) 

NSString _position = NSStringFromCGPoint(position); 

// Do the saving 
+0

धन्यवाद, डियानज़। दुर्भाग्य से, मुझे इसे काम करने के लिए नहीं मिला है। मैंने अपनी पोस्ट में जो कुछ भी लिखा था उसकी व्याख्या ("EDIT" के बाद)। क्या आप यह देखने के लिए बहुत दयालु होंगे कि क्या मैंने आपको सही ढंग से समझा है? (Self.frame.origin को सहेजना) या यदि यह पूछने के लिए बहुत कुछ नहीं है, तो क्या आप मुझे सही दिशा में धक्का देने के लिए एक कोड स्निपेट पोस्ट करने में सक्षम होंगे? – sbkp

+0

यह संकलित भी नहीं करता है, और वैसे भी केंद्र संपत्ति के लिए अलग नहीं है। – jrturton

0

मैं सब कुछ है कि क्या हो रहा है के बारे में सुनिश्चित नहीं हूँ, लेकिन यहाँ कुछ विचार सहायता कर सकती हैं।

1- स्क्राम का समाधान व्यावहारिक लगता है, लेकिन यह bounds है जिसे आप frame नहीं सहेजना चाहते हैं।

महत्वपूर्ण हैं एक: (।। कि नोट, अगर वहाँ कोई रोटेशन हो गया है, केंद्र गुना फ्रेम को परिभाषित तो, दो की स्थापना फ्रेम करने के समान ही है) से, View Programming Guide for IOS आप से जुड़ा हुआ व्यू की ट्रांसफॉर्म प्रॉपर्टी पहचान रूपांतरण नहीं है, उस दृश्य की फ्रेम प्रॉपर्टी का मान अपरिभाषित है और को अनदेखा किया जाना चाहिए। एक दृश्य में परिवर्तन लागू करते समय, दृश्य का आकार और स्थिति प्राप्त करने के लिए आपको दृश्य की सीमाएं और केंद्र गुणों का उपयोग करना होगा। किसी भी सबव्यूव के फ्रेम आयत अभी भी वैध हैं क्योंकि वे दृश्य की सीमाओं के सापेक्ष हैं।

2- एक और विचार। जब आप ऐप को पुनः लोड करते हैं, तो आप निम्न कोशिश कर सकते हैं:

  • सबसे पहले, दृश्य परिवर्तन को पहचान परिवर्तन में सेट करें।
  • फिर, दृश्य की सीमाओं और केंद्र को सहेजे गए मानों पर सेट करें।
  • अंत में, दृश्य के परिवर्तन को सहेजे गए परिवर्तन में सेट करें।

आपके ऐप को पुनरारंभ करने के आधार पर, यह कुछ पुरानी ज्यामिति के साथ बैक अप शुरू हो सकता है। मुझे सच में नहीं लगता कि यह कुछ भी बदलेगा, लेकिन कोशिश करने में काफी आसान है।
अद्यतन: कुछ परीक्षण के बाद, ऐसा लगता है कि ऐसा लगता है कि इसका कोई असर नहीं होगा। बदलने को बदलने सीमा या केंद्र बदलने के लिए प्रतीत नहीं होता है (हालांकि यह फ्रेम बदलने करता है।)

3 अंत में, आप चुटकी इशारा पहचानकर्ता पुनर्लेखन bounds बजाय transform पर संचालित करने के लिए से कुछ परेशानी को बचाने कर सकते हैं। (दोबारा, bounds का उपयोग करें, frame नहीं, क्योंकि पहले की रोटेशन frame अमान्य हो सकती थी।) इस तरह, ट्रांसफॉर्म केवल रोटेशन के लिए उपयोग किया जाता है, जो मुझे लगता है, बिना किसी अन्य तरीके से किया जा सकता है।

एक ही गाइड से, एप्पल की सिफारिश है:

आप आमतौर पर एक दृश्य की संपत्ति को बदलने, संशोधित करने के लिए जब आप एनिमेशन लागू करना चाहते हैं। उदाहरण के लिए, आप इस संपत्ति का उपयोग पर अपने केंद्र बिंदु के चारों ओर घूमते हुए अपने दृश्य की एनीमेशन बना सकते हैं। आप इस दृश्य का उपयोग अपने दृश्य में स्थायी परिवर्तन करने के लिए नहीं करेंगे, जैसे इसकी स्थिति को संशोधित करना या इसके पर्यवेक्षण के समन्वय स्थान के भीतर एक दृश्य को आकार देना। उस प्रकार के परिवर्तन के लिए, आपको इसके बजाय अपने दृश्य के फ्रेम आयत को संशोधित करना चाहिए।

2

मुझे आपकी समस्या को पुन: उत्पन्न करने में समस्या हो रही है।

  • चालें यह एक को बदलने
  • दूसरे के साथ यह घुमाता के साथ केंद्र
  • तराजू इसे बदलने बदलने, पर concatenated द्वारा एक दृश्य में जोड़ता है: मैं निम्नलिखित कोड है, जो निम्नलिखित करता है का इस्तेमाल किया है पहले
  • बचाता को बदलने और केंद्र तार
  • अन्य दृश्य जोड़ता है और केन्द्र लागू होता है और स्ट्रिंग से बदलने के लिए

यह ठीक उसी जगह और स्थिति में दो दृश्य में परिणाम:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; 
    view1.layer.borderWidth = 5.0; 
    view1.layer.borderColor = [UIColor blackColor].CGColor; 
    [self.view addSubview:view1]; 
    view1.center = CGPointMake(150,150); 
    view1.transform = CGAffineTransformMakeScale(1.3, 1.3); 
    view1.transform = CGAffineTransformRotate(view1.transform, 0.5); 

    NSString *savedCentre = NSStringFromCGPoint(view1.center); 
    NSString *savedTransform = NSStringFromCGAffineTransform(view1.transform); 

    UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; 
    view2.layer.borderWidth = 2.0; 
    view2.layer.borderColor = [UIColor greenColor].CGColor; 
    [self.view addSubview:view2]; 
    view2.center = CGPointFromString(savedCentre); 
    view2.transform = CGAffineTransformFromString(savedTransform); 

} 

देता है:

enter image description here

यह मैं क्या प्रलेखन से उम्मीद होती है के साथ बांध, कि सभी रूपांतरण में केंद्र बिंदु के आसपास होता है और इसलिए कभी प्रभावित नहीं होता है। एकमात्र तरीका मैं कल्पना कर सकता हूं कि आप आइटम को अपने पिछले राज्य में पुनर्स्थापित करने में सक्षम नहीं हैं अगर किसी भी तरह पर्यवेक्षण भिन्न था, या तो अपने स्वयं के परिवर्तन या एक अलग फ्रेम, या एक अलग दृश्य के साथ अलग था। लेकिन मैं आपके प्रश्न से यह नहीं बता सकता।

संक्षेप में, आपके प्रश्न में मूल कोड काम करना चाहिए, इसलिए कुछ और चल रहा है! उम्मीद है कि यह जवाब आपको इसे कम करने में मदद करेगा।

+0

मैं कुछ ऐसा करने की कोशिश करता हूं: दृश्य का परिवर्तन और केंद्र बंद करें और उन्हें पुनः लोड करें। बात नहीं बढ़ती है (आपके परिणाम पुन: उत्पन्न)। लेकिन जब मैं ऐप को पुनरारंभ करता हूं, तो यह कहीं और है। तो पर्यवेक्षण के बारे में आपकी सोच के बाद समस्या, शायद जब मैं स्टार्टअप पर वरीयताओं को पढ़ रहा हूं, पर्यवेक्षण में कुछ राज्य अभी तक सेट नहीं है। मैं उसमें खुदाई करूंगा और वापस रिपोर्ट करूंगा। बहुत बहुत धन्यवाद! – sbkp

+0

ठीक है, इसलिए जब मैं prefs लोड कर रहा हूं, तो सबकुछ ठीक दिखता है। यूआई पैनल का 'सीमा' आय {{0, 0}, {506, 254}} है। मेरे वीसी के दृश्य के अंत में डिडलोड विधि, अभी भी ठीक लगता है। लेकिन जब तक चीजें वास्तव में प्रदर्शित होती हैं, तब तक 'सीमा' आय कुछ और होती है। उदाहरण के लिए: {{0, 0}, {488.321, 435.981}}। यदि मैं सीमाओं को रीसेट करता हूं जो इसे माना जाता है, तो यह वापस स्थानांतरित हो जाता है। तो प्रोग्रामिंग के लिए इतना आसान है, लेकिन मुझे वास्तव में यकीन नहीं है कि यह कब करना है! मैंने इसेडिडलोड के अंत में ऐसा करने के लिए सोचा होगा, लेकिन उस बिंदु पर 'सीमाएं' अभी भी सही है। – sbkp

+2

ज्यामिति (फ्रेम, सीमाएं, इत्यादि) पूरी तरह से सेट नहीं है जब viewDidLoad कहा जाता है, लेकिन यह _is_ viewWillAppear से पहले सेट है। तो, यह ज्यामिति की जांच करने और किसी भी समायोजन करने के लिए जगह होगी। (फिर भी, बिना किसी बदलाव के सीमाओं को रीसेट करना, इसके परिणामस्वरूप अन्य परिणाम हो सकते हैं।) एक ऑटोरेसाइजिंग मास्क दृश्य प्रकट होने से पहले फ्रेम/सीमा/केंद्र बदल सकता है। –

संबंधित मुद्दे