Sunulan Bir Görünüm Denetleyicisini Kapatma


116

Teorik bir sorum var. Şimdi Apple'ın ViewController kılavuzunu okuyorum .

Yazdılar:

Sunulan bir görüntü denetleyicisini reddetme zamanı geldiğinde, tercih edilen yaklaşım, sunan görünüm denetleyicisinin onu reddetmesine izin vermektir. Başka bir deyişle, mümkün olduğunda, görünüm denetleyicisini sunan aynı görünüm denetleyicisi, onu reddetme sorumluluğunu da almalıdır. Sunulan görünüm denetleyicisine sunulan görünüm denetleyicisinin atılması gerektiğini bildirmek için birkaç teknik olsa da, tercih edilen teknik yetkilendirmedir.

Ancak, sunulan VC'de neden bir protokol oluşturmam ve temsilci değişkenini eklemem, sunulan VC'yi kapatmak için sunulan VC'yi sunmak için temsilci yöntemi oluşturmam gerektiğini açıklayamam, sunulan görünüm denetleyicisi yönteminde basit bir çağrı yerine

[self dismissViewControllerAnimated:NO completion:nil]?

İlk seçim neden daha iyi? Apple neden tavsiye ediyor?

Yanıtlar:


122

Sanırım Apple, potansiyel olarak kludgy bir API parçası için arkalarını biraz koruyor.

  [self dismissViewControllerAnimated:NO completion:nil]

Aslında biraz keman. Bunu - yasal olarak - sunulan görünüm denetleyicisinde çağırabilseniz de, tek yaptığı mesajı sunum görünümü denetleyicisine iletmektir. VC'yi reddetmekle tekrar tekrar bir şey yapmak istiyorsanız, bunu bilmeniz gerekir ve buna bir delege yöntemiyle aynı şekilde davranmanız gerekir - neredeyse olduğu gibi, fırınlanmış bir şekilde biraz esnek değildir. temsilci yöntemi.

Belki de bunun nasıl bir araya getirildiğini tam olarak anlamayan insanlar tarafından çok sayıda kötü kodla karşılaştılar, bu yüzden de dikkatleri.

Ama elbette, tek yapmanız gereken şeyi reddetmekse, devam edin.

Benim yaklaşımım bir uzlaşma, en azından bana neler olduğunu hatırlatıyor:

  [[self presentingViewController] dismissViewControllerAnimated:NO completion:nil]

[Swift]

  self.presentingViewController?.dismiss(animated: false, completion:nil)

26
O kullanılarak belirtilmelidir presentingViewControllero başvurmak gibi çoğunlukla yararsız UINavigationControllerolmadığını selfbirinde gömülür. Bu durumda, hiç elde edemezsiniz presentingViewController. Yine [self dismissViewControllerAnimated:completion]de bu durumda çalışıyor. Benim önerim, Apple düzeltene kadar bunu kullanmaya devam etmek olacaktır.
memmons

4
Bu cevabın 3 yıl sonra hala tamamen geçerli olmasını seviyorum.
user1021430

1
Dikkate alınması gereken başka bir şey, bir görünüm denetleyicisinin nasıl görüntülendiğini bilmemesidir. Sunulmuş olabilir, bir gezinti denetleyicisine itilmiş olabilir, bir sekme çubuğu denetleyicisinin parçası vb. Temsilcinin kullanılması, "sunum yapan" görünüm denetleyicisinin, onu sunmak için kullanılan yöntemin tersini kullanarak görünüm denetleyicisini "kapatmasına" izin verir.
David Smith

51

Swift 3 için güncellendi

Buraya sadece mevcut (sunulan) Görünüm Denetleyicisini reddetmek istedim. Buraya aynı amaçla gelenler için bu cevabı veriyorum.

Navigasyon Denetleyicisi

Bir gezinme denetleyicisi kullanıyorsanız, oldukça kolaydır.

Önceki görünüm denetleyicisine geri dönün:

// Swift
self.navigationController?.popViewController(animated: true)

// Objective-C
[self.navigationController popViewControllerAnimated:YES];

Kök görünüm denetleyicisine geri dönün:

// Swift
self.navigationController?.popToRootViewController(animated: true)

// Objective-C
[self.navigationController popToRootViewControllerAnimated:YES];

( Objective-C için bu cevaba teşekkürler .)

Modal Görünüm Denetleyicisi

Modsal olarak bir Görünüm Kontrolörü sunulduğunda, onu arayarak (ikinci görünüm kontrolöründen) kapatabilirsiniz.

// Swift
self.dismiss(animated: true, completion: nil)

// Objective-C
[self dismissViewControllerAnimated:YES completion:nil];

Dokümantasyon diyor

Sunum görüntüleme denetleyicisi, sunduğu görünüm denetleyicisini görevden almaktan sorumludur. Bu yöntemi sunulan görünüm denetleyicisinin kendisinde çağırırsanız, UIKit sunum görünümü denetleyicisinden kapatmayı ele almasını ister.

Dolayısıyla, sunulan görünüm denetleyicisinin onu kendisi çağırması işe yarar. İşte tam bir örnek.

Delegeler

OP'nin sorusu, bir görüşü reddetmek için delegeleri kullanmanın karmaşıklığıyla ilgiliydi.

Bu noktaya kadar, genellikle bir gezinti denetleyicim veya modal görünüm denetleyicilerim olduğu için delege kullanmaya gerek duymadım, ancak ileride temsilci kalıbını kullanmam gerekirse , bir güncelleme ekleyeceğim.


50

Bu, görünüm denetleyicisinin yeniden kullanılabilirliği içindir.

Görünüm denetleyiciniz, modal olarak sunulması, gezinme denetleyicisine basılması veya herhangi bir şekilde sunulması umrunda olmamalıdır. Görüntü denetleyiciniz kendisini reddederse, mod olarak sunulduğunu varsayarsınız. Bu görünüm denetleyicisini bir gezinme denetleyicisine itemezsiniz.

Bir protokol uygulayarak, üst görünüm denetleyicisinin nasıl sunulması / itilmesi ve atılması / atılması gerektiğine karar vermesine izin verirsiniz.



6

Tecrübelerime göre, onu istediğiniz herhangi bir ViewController'den çıkarmanız ve onu reddeden her bir viewcontroller için farklı görevler gerçekleştirmeniz gerektiğinde kullanışlı oluyor. Protokolü benimseyen herhangi bir viewController, görünümü kendi yöntemleriyle kapatabilir. (ipad vs iphone veya farklı görünümlerden çıkarılırken farklı veriler iletilir, işten çıkarılırken farklı yöntemler çağrılır vb.)

Düzenle:

Dolayısıyla, açıklığa kavuşturmak gerekirse, tek yapmak istediğiniz görünümü reddetmekse, delege protokolünü kurmaya gerek görmüyorum. Farklı sunum görünümü denetleyicilerinden çıkardıktan sonra farklı şeyler yapmanız gerekirse, temsilciyi kullanmak için en iyi yol bu olacaktır.


ancak "farklı görünümlerden çıkarırken farklı verileri iletmeye, işten çıkarırken farklı yöntemleri çağırmaya vb." ihtiyacım yoksa, sunulan görünüm denetleyicisi yönteminde küçük bir çağrı yapabilir miyim - [self dismissViewControllerAnimated: NO complete: nil]?
nikitahils

Sunucunun sunulan görüşü reddetmesine izin vermek, sunum yapan kişinin aslında hazır olduğunu ve ön plana geri dönüşü idare ettiğini açıkça ortaya koyar: yürütme sırasını takip etmek kolaydır ve herhangi bir UI güncellemesinin sorumluluğu dolaylı olarak açıktır.
Johan

2

View Controller Programming Guide , "View Controllers Other View Controllers" dan alıntı .

Sunulan görünüm denetleyicileri zincirindeki her bir görünüm denetleyicisinin, zincirde kendisini çevreleyen diğer nesnelere işaretçileri vardır. Başka bir deyişle, başka bir görünüm denetleyicisini sunan sunulan bir görünüm denetleyicisinin hem sunan GörünümController hem de sunulanViewController özelliklerinde geçerli nesneleri vardır. Bu ilişkileri, gerektiğinde görünüm denetleyicileri zinciri boyunca izlemek için kullanabilirsiniz. Örneğin, kullanıcı mevcut işlemi iptal ederse, sunulan ilk görünüm denetleyicisini kapatarak zincirdeki tüm nesneleri kaldırabilirsiniz. Bir görünüm denetleyicisinin kapatılması, yalnızca o görünüm denetleyicisini değil, aynı zamanda sunduğu tüm görünüm denetleyicilerini de kapatır.

Yani bir yandan güzel dengeli bir tasarım, iyi bir ayırma vb. Sağlar ... Ama diğer yandan çok pratik çünkü navigasyonda belirli bir noktaya hızla geri dönebilirsiniz.

Bununla birlikte, ben şahsen , sunulan görünüm denetleyicileri ağacında geriye doğru ilerlemeye çalışmak yerine çözücü segmentleri kullanmayı tercih ederim , bu da Apple'ın sözünün geldiği bu bölümde bahsettiği şeydir.


2

Bir nokta, bunun iyi bir kodlama yaklaşımı olmasıdır. OOPSRP, Endişelerin ayrılması vb. Gibi birçok ilkeyi karşılar .

Bu nedenle, görünümü sunan görünüm denetleyicisi onu reddeden kişi olmalıdır.

Mesela, kira karşılığı ev veren bir emlak şirketi onu geri alma yetkisi olmalıdır.


2

Swift 3.0 // Hızlı Görünüm Denetleyicisini Kapat

self.navigationController?.popViewController(animated: true)
dismiss(animated: true, completion: nil)

1

Michael Enriquez'in cevabına ek olarak, bunun kendinizi belirsiz bir durumdan korumanın iyi bir yolu olmasının başka bir nedenini düşünebilirim:

Diyelim ki ViewControllerA, ViewControllerB'yi modal olarak sunuyor. Ancak, ViewControllerA kodunu yazmamış olabileceğinizden, ViewControllerA'nın yaşam döngüsünün farkında değilsinizdir. Görünüm denetleyiciniz ViewControllerB'yi sunduktan 5 saniye sonra (diyelim) kapatılabilir.

Bu durumda, dismissViewControllerViewControllerB'den kendisini feshetmek için basitçe kullanıyor olsaydınız, tanımlanmamış bir duruma düşersiniz - belki bir çökme veya siyah ekran değil, ama sizin bakış açınızdan tanımlanmamış bir durum.

Bunun yerine, temsilci modelini kullanıyor olsaydınız, ViewControllerB'nin durumundan haberdar olurdunuz ve anlattığım gibi bir durum için programlayabilirsiniz.


1

hızlı

let rootViewController:UIViewController = (UIApplication.shared.keyWindow?.rootViewController)!

        if (rootViewController.presentedViewController != nil) {
            rootViewController.dismiss(animated: true, completion: {
                //completion block.
            })
        }

0

Modal kullanıyorsanız, görünümü kapatın.

[self dismissViewControllerAnimated:NO completion:nil];

Bu, şu soruyu nasıl yanıtlıyor: "Neden ilk tercih daha iyi? Apple bunu neden tavsiye ediyor?"
jww

0

Bu çok saçma. Yetki gerektiğinde iyidir, ancak kodu daha karmaşık hale getiriyorsa - ve yapıyor - o zaman bunun bir nedeni olması gerekir.

Eminim Apple'ın sebepleri vardır. Ancak, aksini yapmak için gerçek bir neden olmadıkça ve bugün burada kimse görebildiğim bir tanesini sunmadıysa, sunulan VC'nin işten çıkarmayı basitçe yapması daha açık ve daha özlüdür.

Protokoller ihtiyaç duyulduğunda mükemmeldir, ancak nesne yönelimli tasarım hiçbir zaman birbirleriyle gereksiz yere iletişim kuran modüllere sahip olmakla ilgili değildir.

Tom Love (Objective C'nin ortak geliştiricisi) bir keresinde Objective C'nin "zarif", "küçük", "net" ve "iyi tanımlanmış" (C ++ ile karşılaştırıldığında) olduğunu söylemişti. Onun için söylemesi kolay. Yetki verme, "sırf bunun için" aşırı kullanılmış gibi görünen kullanışlı bir özelliktir ve dilde çalışmayı sevsem de, işleri olması gerekenden daha karmaşık hale getirmek için gereksiz sözdizimi kullanmaya mecbur bırakma fikrinden korkuyorum.


Başlangıçta bazı kodlardan tasarruf etmenizi sağlayabilir, ancak yaklaşımınız kod tabanınız büyüdükçe birçok baş ağrısına neden olacaktır. Kaygıların ayrılması gibi nesne yönelimli ilkeleri anlamalısınız, aksi takdirde tüm uygulamanızı tek bir büyük dosyada kodlayabilirsiniz.
Werner Altewischer

-2

Süper görünüm pencerenizi kapatabilirsiniz

self.view.superview?.window?.close()

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.