मैं एक iPhone ऐप प्रोग्रामिंग कर रहा हूं, और मुझे कुछ उपयोगकर्ता कार्यों के कारण इसे बाहर निकलने के लिए मजबूर करना होगा। ऐप को आवंटित किए गए मेमोरी को साफ करने के बाद, एप्लिकेशन को समाप्त करने के लिए कॉल करने का उपयुक्त तरीका क्या है?
मैं एक iPhone ऐप प्रोग्रामिंग कर रहा हूं, और मुझे कुछ उपयोगकर्ता कार्यों के कारण इसे बाहर निकलने के लिए मजबूर करना होगा। ऐप को आवंटित किए गए मेमोरी को साफ करने के बाद, एप्लिकेशन को समाप्त करने के लिए कॉल करने का उपयुक्त तरीका क्या है?
जवाबों:
क्या आपने कोशिश की है exit(0)
?
वैकल्पिक रूप से [[NSThread mainThread] exit]
, हालांकि मैंने कोशिश नहीं की है कि यह अधिक उपयुक्त समाधान की तरह लगता है।
IPhone पर ऐप छोड़ने की कोई अवधारणा नहीं है। केवल एक एक्शन जिसके कारण किसी ऐप को छोड़ना चाहिए, फोन पर होम बटन को छू रहा है, और यह कुछ डेवलपर्स के लिए उपयोग नहीं है।
Apple के अनुसार, आपके ऐप को अपने आप समाप्त नहीं होना चाहिए। चूंकि उपयोगकर्ता ने होम बटन नहीं मारा था, इसलिए होम स्क्रीन पर कोई भी वापसी उपयोगकर्ता को यह आभास देती है कि आपका ऐप क्रैश हो गया है। यह भ्रामक है, गैर-मानक व्यवहार है और इससे बचना चाहिए।
निकास (0) उपयोगकर्ता को क्रैश के रूप में प्रकट होता है, इसलिए उपयोगकर्ता को एक पुष्टिकरण संदेश दिखाते हैं। पुष्टिकरण के बाद सस्पेंड (होम बटन प्रोग्रामेटिक रूप से) और 2 सेकंड प्रतीक्षा करें, जबकि ऐप एनीमेशन के साथ बैकग्राउंड जा रहा है, तब उपयोगकर्ता के विचार से बाहर निकलें
-(IBAction)doExit
{
//show confirmation message to user
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Confirmation"
message:@"Do you want to exit?"
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"OK", nil];
[alert show];
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex != 0) // 0 == the cancel button
{
//home button press programmatically
UIApplication *app = [UIApplication sharedApplication];
[app performSelector:@selector(suspend)];
//wait 2 seconds while app is going background
[NSThread sleepForTimeInterval:2.0];
//exit app when app is in background
exit(0);
}
}
exit(0)
कोई मायने नहीं रखता। प्वाइंट आपके ऐप में "छोड़ने का व्यवहार" है। कुछ ही ऐप को छोड़कर AppStore में व्यवहार को प्रतिबंधित करना बहुत महत्वपूर्ण है जो कि बहुत ही महत्वपूर्ण 3rd-पार्टियों द्वारा बनाए गए हैं। इसके अलावा, होम बटन व्यवहार की नकल भी अस्वीकार किए जाने के अधीन है।
प्रश्नोत्तर देखें :
प्रश्न: मैं अपने iOS एप्लिकेशन को प्रोग्रामेटिक रूप से कैसे छोड़ सकता हूं?
IOS एप्लिकेशन को शालीनतापूर्वक समाप्त करने के लिए कोई API प्रदान नहीं किया गया है।
IOS में, उपयोगकर्ता होम बटन को एप्लिकेशन को बंद करने के लिए दबाता है। क्या आपके आवेदन में ऐसी स्थितियां हैं, जिसमें वह अपना इच्छित कार्य नहीं दे सकता है, अनुशंसित दृष्टिकोण उपयोगकर्ता के लिए एक चेतावनी प्रदर्शित करने के लिए है जो समस्या की प्रकृति और संभावित क्रियाओं को इंगित करता है जो उपयोगकर्ता ले सकता है - वाईफाई चालू करना, स्थान सेवाएँ सक्षम करना, आदि। उपयोगकर्ता को अपने स्वयं के विवेक पर आवेदन को समाप्त करने की अनुमति दें।
चेतावनी:
exit
फ़ंक्शन को कॉल न करें ।exit
उपयोगकर्ता को दिखाई देने वाली एप्लिकेशन को एक शानदार समाप्ति प्रदर्शन करने और होम स्क्रीन पर वापस एनिमेट करने के बजाय क्रैश हो गया है।इसके अतिरिक्त, डेटा को सहेजा नहीं जा सकता है, क्योंकि यदि आप बाहर निकलें तो
-applicationWillTerminate:
इसी तरह केUIApplicationDelegate
तरीके लागू नहीं होंगे।यदि विकास या परीक्षण के दौरान आपके आवेदन को समाप्त करना आवश्यक है, तो
abort
फ़ंक्शन, याassert
मैक्रो की सिफारिश की जाती है
यह वास्तव में कार्यक्रम छोड़ने का एक तरीका नहीं है, बल्कि लोगों को छोड़ने के लिए मजबूर करने का एक तरीका है।
UIAlertView *anAlert = [[UIAlertView alloc] initWithTitle:@"Hit Home Button to Exit" message:@"Tell em why they're quiting" delegate:self cancelButtonTitle:nil otherButtonTitles:nil];
[anAlert show];
अपनी info.plist पर जाएं और कुंजी की जांच करें "एप्लिकेशन पृष्ठभूमि में नहीं चलता है"। इस बार जब उपयोगकर्ता होम बटन पर क्लिक करता है, तो एप्लिकेशन पूरी तरह से बाहर निकल जाता है।
जोड़ें UIApplicationExitsOnSuspend
पर संपत्ति application-info.plist
के लिए true
।
कुछ परीक्षणों के बाद, मैं निम्नलिखित कह सकता हूं:
[UIApplication sharedApplication]
यह दुर्घटनाग्रस्त होने की तरह दिखने वाले ऐप का कारण होगा, लेकिन ऐसा करने से - (void)applicationWillTerminate:(UIApplication *)application
पहले यह कॉल करेगा ;exit(0);
करने से एप्लिकेशन भी समाप्त हो जाएगा, लेकिन यह "सामान्य" दिखेगा (स्प्रिंगबोर्ड के आइकन उम्मीद की तरह दिखाई देते हैं, ज़ूम आउट प्रभाव के साथ), लेकिन यह - (void)applicationWillTerminate:(UIApplication *)application
प्रतिनिधि पद्धति को कॉल नहीं करेगा ।मेरी सलाह:
- (void)applicationWillTerminate:(UIApplication *)application
प्रतिनिधि को मैन्युअल रूप से बुलाओ ।exit(0);
।आपके ApplicationDelegate को उपयोगकर्ता द्वारा जानबूझकर छोड़ने की सूचना मिलती है:
- (void)applicationWillResignActive:(UIApplication *)application {
जब मुझे यह सूचना मिलती है तो मैं फोन करता हूं
exit(0);
जो सभी काम करता है। और सबसे अच्छी बात यह है कि यह उपयोगकर्ता को छोड़ने का इरादा है, यही कारण है कि इसे वहां कॉल करने में कोई समस्या नहीं होनी चाहिए।
मेरे ऑडियो-ऐप पर लोगों को अपने डिवाइस को सिंक करने के बाद ऐप को छोड़ना आवश्यक था, जबकि संगीत अभी भी खेल रहा था। जैसे ही सिंकिंग पूरी होती है मुझे एक सूचना मिलती है। लेकिन इसके बाद ऐप को छोड़ देना वास्तव में क्रैश जैसा लगेगा।
इसलिए इसके बजाय मैंने एक झंडे को सेट किया, ताकि अगले बैकग्राउंडिंग एक्शन पर ऐप छोड़ दिया जाए। जो सिंक के बाद ऐप को रिफ्रेश करने के लिए ठीक है।
मेरा ऐप अस्वीकृत कर दिया गया है हाल ही में bc मैंने एक अनिर्दिष्ट विधि का उपयोग किया है। वस्तुतः:
"दुर्भाग्य से इसे ऐप स्टोर में नहीं जोड़ा जा सकता है क्योंकि यह एक निजी एपीआई का उपयोग कर रहा है। गैर-सार्वजनिक एपीआई का उपयोग, जिसे iPhone डेवलपर प्रोग्राम लाइसेंस अनुबंध अनुभाग 3.3.1 में उल्लिखित किया गया है:
"3.3.1 अनुप्रयोग केवल Apple द्वारा निर्धारित तरीके से प्रलेखित API का उपयोग कर सकते हैं और किसी भी निजी API का उपयोग या कॉल नहीं करना चाहिए।"
आपके आवेदन में शामिल किया गया गैर-सार्वजनिक एपीआई समाप्त हो गया है "असफल"
Apple का कहना है:
"चेतावनी: एग्जिट फंक्शन को कॉल न करें। एग्जिट कॉलिंग वाले एप्स यूजर को एक शानदार टर्मिनेशन को पूरा करने और होम स्क्रीन पर वापस एनिमेट करने के बजाय क्रैश होते दिखाई देंगे।"
मुझे लगता है कि यह एक बुरी धारणा है। यदि उपयोगकर्ता एक त्यागें बटन पर टैप करता है और एक संदेश प्रकट होता है, जो कुछ कहता है: "एप्लिकेशन अब छोड़ दिया जाएगा।", यह दुर्घटनाग्रस्त नहीं होता है। Apple को एप्लिकेशन छोड़ने का एक वैध तरीका प्रदान करना चाहिए (बाहर नहीं निकलना) (0)।
यह एक अच्छा जवाब मिल गया है लेकिन थोड़ा विस्तार करने का फैसला किया है:
आप Apple के iOS मानव इंटरफ़ेस दिशानिर्देशों को अच्छी तरह से पढ़े बिना अपने आवेदन को AppStore में स्वीकार नहीं कर सकते। (वे आपके खिलाफ कुछ भी करने के लिए आपको अस्वीकार करने का अधिकार बरकरार रखते हैं) खंड "डोंट क्विट प्रोग्रामेटिकली" http://developer.apple.com/library/ios/#DOCUMENTATION/UserExperience/Conceptual/MobileHIG/UEBestPractices/UEBestPractices। html एक सटीक दिशानिर्देश है कि आपको इस मामले में कैसे व्यवहार करना चाहिए।
यदि आपको कभी भी Apple प्लेटफ़ॉर्म के साथ कोई समस्या है, तो आप आसानी से HIG से परामर्श नहीं कर सकते। यह संभव है कि Apple बस आपको ऐसा नहीं करना चाहता है और वे आमतौर पर (मैं Apple नहीं हूं इसलिए मैं हमेशा गारंटी नहीं दे सकता) उनके प्रलेखन में ऐसा कहते हैं।
हम्म, आपको आवेदन छोड़ना पड़ सकता है यदि, कहते हैं, आपके आवेदन को इंटरनेट कनेक्शन की आवश्यकता है। आप एक अलर्ट प्रदर्शित कर सकते हैं और फिर कुछ इस तरह से कर सकते हैं:
if ([[UIApplication sharedApplication] respondsToSelector:@selector(terminate)]) {
[[UIApplication sharedApplication] performSelector:@selector(terminate)];
} else {
kill(getpid(), SIGINT);
}
हम का उपयोग कर एप्लिकेशन से बाहर निकलने नहीं कर सकते हैं exit(0)
, abort()
काम करता है, एप्पल दृढ़ता से इन कार्यों के उपयोग को हतोत्साहित के रूप में। यद्यपि आप इस कार्य को विकास या परीक्षण के उद्देश्य के लिए उपयोग कर सकते हैं।
यदि विकास या परीक्षण के दौरान यह आपके आवेदन को समाप्त करने के लिए आवश्यक है, तो गर्भपात समारोह या मुखर मैक्रो की सिफारिश की जाती है
अधिक जानकारी प्राप्त करने के लिए कृपया इस Apple Q & A थ्रेड को खोजें।
इस फंक्शन के उपयोग से इम्प्रेशन बनता है जैसे एप्लिकेशन क्रैश हो रहा है। इसलिए मुझे कुछ सुझाव मिले जैसे कि हम कुछ कार्यक्षमता की अनुपलब्धता के कारण ऐप को बंद करने के बारे में जागरूक उपयोगकर्ता को समाप्ति संदेश के साथ अलर्ट प्रदर्शित कर सकते हैं।
लेकिन ऐप और स्टार्टिंग को रोकने के लिए iOS मानव इंटरफ़ेस दिशानिर्देश , यह सुझाव देता है कि एप्लिकेशन को समाप्त करने के लिए कभी भी क्विट या क्लोज बटन का उपयोग न करें । बल्कि तब कि वे स्थिति को समझाने के लिए उचित संदेश प्रदर्शित करने का सुझाव दे रहे हैं।
एक iOS ऐप कभी भी क्लोज या क्विट विकल्प प्रदर्शित नहीं करता है। जब लोग किसी अन्य ऐप पर स्विच करते हैं, तो वे होम स्क्रीन पर वापस आते हैं, या अपने डिवाइस को स्लीप मोड में डालते हैं।
प्रोग्राम से iOS ऐप कभी न छोड़ें। लोग इसे एक दुर्घटना के रूप में व्याख्या करते हैं। यदि कुछ आपके ऐप को उद्देश्य से कार्य करने से रोकता है, तो आपको उपयोगकर्ताओं को स्थिति के बारे में बताने और यह समझाने की आवश्यकता है कि वे इसके बारे में क्या कर सकते हैं।
उपरोक्त के अलावा, अच्छा, उत्तर मैं सिर्फ जोड़ना चाहता था, अपनी स्मृति को साफ करने के बारे में सोचें।
आपके आवेदन से बाहर निकलने के बाद, iPhone OS स्वचालित रूप से आपके द्वारा छोड़ी गई किसी भी चीज़ को साफ कर देगा, इसलिए सभी मेमोरी को मैन्युअल रूप से खाली करने से आपके एप्लिकेशन को बाहर निकलने में लगने वाले समय में वृद्धि हो सकती है।
- (IBAction)logOutButton:(id)sender
{
//show confirmation message to user
CustomAlert* alert = [[CustomAlert alloc] initWithTitle:@"Confirmation" message:@"Do you want to exit?" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil];
alert.style = AlertStyleWhite;
[alert setFontName:@"Helvetica" fontColor:[UIColor blackColor] fontShadowColor:[UIColor clearColor]];
[alert show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex != 0) // 0 == the cancel button
{
//home button press programmatically
UIApplication *app = [UIApplication sharedApplication];
[app performSelector:@selector(suspend)];
//wait 2 seconds while app is going background
[NSThread sleepForTimeInterval:2.0];
//exit app when app is in background
NSLog(@"exit(0)");
exit(0);
}
}
मैंने टेल-एग्जिट (0) फ़ंक्शन कॉल किए बिना एप्लिकेशन को बल-छोड़ (क्रैश) करने के लिए ऊपर उल्लिखित [[NSMutableArray new] addObject: nil] दृष्टिकोण का उपयोग किया।
क्यों? क्योंकि मेरा ऐप मैन-इन-द-बीच हमलों को रोकने के लिए सभी नेटवर्क एपीआई कॉल पर सर्टिफिकेट पिनिंग का उपयोग करता है। इनमें स्टार्टअप पर मेरा वित्तीय ऐप कॉल के इनिशियलाइज़ेशन कॉल शामिल हैं।
यदि प्रमाण पत्र प्रमाणीकरण विफल हो जाता है, तो मेरे सभी आरंभीकरण त्रुटि को कॉल करते हैं और मेरे ऐप को अनिश्चित स्थिति में छोड़ देते हैं। उपयोगकर्ता को घर जाने दें और फिर वापस ऐप में मदद करें, क्योंकि जब तक ऐप को ओएस द्वारा शुद्ध नहीं किया जाता है तब तक यह अभी भी बिना लाइसेंस और अविश्वास के है।
इसलिए, इस एक मामले में, हमने उपयोगकर्ता को यह सूचित करने के लिए एक चेतावनी देना सबसे अच्छा समझा कि ऐप असुरक्षित माहौल में चल रहा है और फिर, जब वे "क्लोज़" मारते हैं, तो उपरोक्त विधि का उपयोग करके ऐप को छोड़ दें।
[[UIApplication sharedApplication] terminateWithSuccess];
यह ठीक काम किया और स्वचालित रूप से कॉल करता है
- (void)applicationWillTerminateUIApplication *)application delegate.
संकलन समय चेतावनी निकालने के लिए इस कोड को जोड़ें
@interface UIApplication(MyExtras)
- (void)terminateWithSuccess;
@end
आपको फ़ंक्शन exit(0)
को सीधे कॉल नहीं करना चाहिए क्योंकि यह तुरंत आवेदन छोड़ देगा और ऐसा लगेगा कि आपका ऐप क्रैश हो गया है। यूजर्स को कंफर्म अलर्ट दिखाने के लिए बेहतर है और उन्हें खुद ऐसा करने दें।
func askForQuit(_ completion:@escaping (_ canQuit: Bool) -> Void) {
let alert = UIAlertController(title: "Confirmation!", message: "Do you want to quit the application", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Yes", style: UIAlertAction.Style.default, handler: { (action) in
alert.dismiss(animated: true, completion: nil)
completion(true)
}))
alert.addAction(UIAlertAction(title: "No", style: UIAlertAction.Style.cancel, handler: { (action) in
alert.dismiss(animated: true, completion: nil)
completion(false)
}))
self.present(alert, animated: true, completion: nil)
}
/// Will quit the application with animation
func quit() {
UIApplication.shared.perform(#selector(NSXPCConnection.suspend))
/// Sleep for a while to let the app goes in background
sleep(2)
exit(0)
}
self.askForQuit { (canQuit) in
if canQuit {
self.quit()
}
}
ऐप से बाहर निकलने पर उपयोगकर्ता को यह तय करना चाहिए। मुझे नहीं लगता कि ऐप के क्विट होने पर यह एक अच्छा उपयोगकर्ता इंटरैक्शन है। इसलिए इसके लिए कोई अच्छा एपीआई नहीं है, केवल होम बटन में एक है।
यदि कोई त्रुटि है: इसे बेहतर तरीके से लागू करें या उपयोगकर्ता को सूचित करें। यदि कोई पुनरारंभ करना है: तो इसे उपयोगकर्ता को सूचित करना बेहतर तरीके से लागू करें।
यह गूंगा लगता है, लेकिन उपयोगकर्ता को निर्णय लेने और उसे सूचित किए बिना ऐप से बाहर निकलना बुरा है। और चूंकि उपयोगकर्ता इंटरैक्शन के लिए एक होम बटन है, Apple बताता है, एक ही फ़ंक्शन (किसी ऐप से बाहर निकलने) के लिए 2 चीजें नहीं होनी चाहिए।
होम बटन के अलावा किसी अन्य ऐप से बाहर निकलें वास्तव में गैर-आईओएस-एस्क दृष्टिकोण है।
मैंने यह सहायक किया, हालांकि, कोई निजी सामान का उपयोग नहीं किया:
void crash()
{ [[NSMutableArray new] addObject:NSStringFromClass(nil)]; }
लेकिन अभी भी मेरे मामले में उत्पादन के लिए नहीं है। यह क्रैश रिपोर्टिंग का परीक्षण करने या कोर डेटा रीसेट के बाद तेजी से पुनः आरंभ करने के लिए है। यदि फ़ंक्शन को उत्पादन कोड में छोड़ दिया जाता है तो बस इसे अस्वीकार नहीं किया जाना सुरक्षित है।
IPadOS 13 में अब आप इस तरह से सभी दृश्य सत्र बंद कर सकते हैं:
for session in UIApplication.shared.openSessions {
UIApplication.shared.requestSceneSessionDestruction(session, options: nil, errorHandler: nil)
}
यह applicationWillTerminate(_ application: UIApplication)
आपके ऐप के प्रतिनिधि को कॉल करेगा और अंत में ऐप को समाप्त कर देगा।
लेकिन दो बातों से सावधान रहें:
यह निश्चित रूप से सभी दृश्यों को बंद करने के लिए उपयोग करने के लिए नहीं है । (देखें https://developer.apple.com/design/human-interface-guidelines/ios/system-capabilities/multiple-windows/ )
यह एक iPhone पर iOS 13 पर संकलित करता है और ठीक चलता है, लेकिन कुछ भी नहीं करता है।
IOS / iPadOS 13 के दृश्यों के बारे में अधिक जानकारी: https://developer.apple.com/documentation/uikit/app_and_environment/scenes
किसी ऐप से बाहर निकलना उचित हो सकता है यदि यह लंबे समय तक रहने वाला ऐप है जो पृष्ठभूमि में भी निष्पादित होता है, उदाहरण के लिए स्थान अपडेट प्राप्त करने के लिए (उस के लिए स्थान अपडेट पृष्ठभूमि क्षमता का उपयोग करके )।
उदाहरण के लिए, मान लें कि उपयोगकर्ता आपके स्थान आधारित ऐप से लॉग आउट करता है, और होम बटन का उपयोग करके ऐप को पृष्ठभूमि पर धकेलता है। इस स्थिति में आपका ऐप चालू रह सकता है, लेकिन इसे पूरी तरह से बाहर निकलने के लिए समझ में आ सकता है। यह उपयोगकर्ता के लिए अच्छा होगा (मेमोरी और अन्य संसाधनों को रिलीज़ करता है, जिनका उपयोग करने की आवश्यकता नहीं है), और ऐप स्थिरता के लिए अच्छा है (यानी यह सुनिश्चित करना कि ऐप समय-समय पर पुनरारंभ हो जाता है जब मेमोरी लीक और अन्य कम मेमोरी के खिलाफ एक सुरक्षा जाल होता है मुद्दे)।
यह (हालांकि शायद, नीचे नहीं देखना चाहिए :-) कुछ इस तरह से हासिल किया जा सकता है:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
if (/* logged out */) {
exit(0);
} else {
// normal handling.
}
}
चूंकि ऐप तब पृष्ठभूमि से बाहर निकल जाएगा, यह उपयोगकर्ता के लिए गलत नहीं लगेगा, और क्रैश जैसा नहीं होगा, बशर्ते उपयोगकर्ता इंटरफ़ेस को अगली बार ऐप चलाने पर बहाल किया जाए। दूसरे शब्दों में, उपयोगकर्ता के लिए यह तब अलग नहीं होगा जब एप्लिकेशन बैकग्राउंड में होने पर ऐप को शुरू करने की व्यवस्था हो।
फिर भी, सिस्टम को यह बताने के लिए अधिक मानक दृष्टिकोण का उपयोग करना बेहतर होगा कि ऐप को समाप्त किया जा सकता है। इस मामले में उदाहरण के लिए, यह सुनिश्चित करके कि जीपीएस वर्तमान स्थान को अपडेट करने से रोककर उपयोग में नहीं है, यदि वर्तमान दृश्य पर वर्तमान दृश्य को दिखाने के स्थान को बंद करने सहित। इस तरह से सिस्टम [[UIApplication sharedApplication] backgroundTimeRemaining]
ऐप को बैकग्राउंड में प्रवेश करने के कुछ मिनट बाद (यानी ) समाप्त करने का ध्यान रखेगा । यह एप्लिकेशन को समाप्त करने के लिए कोड का उपयोग किए बिना सभी समान लाभ प्राप्त करेगा।
- (void)applicationDidEnterBackground:(UIApplication *)application
{
if (/* logged out */) {
// stop requesting location updates if not already done so
// tidy up as app will soon be terminated (run a background task using beginBackgroundTaskWithExpirationHandler if needed).
} else {
// normal handling.
}
}
और बेशक, exit(0)
अग्रभूमि में चलने वाले औसत उत्पादन ऐप के लिए उपयुक्त कभी नहीं होगा, जो अन्य उत्तरों के अनुसार है कि संदर्भ http://developer.apple.com/iphone/library/qa/qa2008/qa1561.html