Niestandardowy init dla UIViewController w Swift z dostosowaniem interfejsu użytkownika w scenorysie
Mam problem z napisaniem niestandardowego init do podklasy UIViewController, w zasadzie chcę przekazać zależność przez metodę init do viewController, zamiast ustawiać właściwość bezpośrednio, jak
viewControllerB.property = valueZrobiłem więc niestandardowy init dla mojego viewController i wywołałem lokalizacje super init
init(meme: Meme?) {
self.meme = meme
super.init(nibName: nil, bundle: nil)
}
Interfejs kontrolera widoku znajduje się w scenorysie, zrobiłem również interfejs dla niestandardowej klasy mojego kontrolera widoku. Swift wymaga wywołania tej metody init, nawet jeśli nie robisz nic wewnątrz tej metody. W przeciwnym razie kompilator będzie narzekał ...
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
Problem polega na tym, że kiedy próbuję wywołać mój niestandardowy init za pomocą
MyViewController (meme: meme), w ogóle nie inicjuje on właściwości w moim viewController ...
Próbowałem debugować, znalazłem w moim viewController,
init (koder aDecoder: NSCoder)jest wywoływany jako pierwszy, a następnie mój niestandardowy init jest wywoływany później. Jednak te dwie metody init zwracają różne adresy pamięci
self.
Podejrzewam, że coś jest nie tak z inicjalizacją mojego viewController i zawsze zwróci
selfz
init? (Coder aDecoder: NSCoder), który nie ma implementacji.
Czy ktoś wie, jak poprawnie utworzyć niestandardowy init dla twojego viewController?
Uwaga: interfejs my viewController jest skonfigurowany w scenorysie
oto mój kod viewController:
class MemeDetailVC : UIViewController { var meme : Meme! @IBOutlet weak var editedImage: UIImageView!// TODO: incorrect init
init(meme: Meme?) {
self.meme = meme
super.init(nibName: nil, bundle: nil)
} required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
} override func viewDidLoad() {
/// setup nav title
title = "Detail Meme" super.viewDidLoad()
} override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
editedImage = UIImageView(image: meme.editedImage)
}}
Nie znaleziono powiązanych wyników
Zaproszony:
Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się
12 odpowiedzi
Anonimowy użytkownik
Potwierdzenie od:
Ale nadal możesz użyć metody statycznej, aby utworzyć wystąpienie ViewController z serii ujęć i wykonać dodatkowe dostosowywanie.
Będzie to wyglądać tak:
Pamiętaj, aby dołączyć IdentifierOfYouViewController jako identyfikator kontrolera widoku w serii ujęć.
Może być również konieczna zmiana nazwy serii ujęć w powyższym kodzie.
Anonimowy użytkownik
Potwierdzenie od:
Twój kontroler widoku ma w nazwie , więc zakładam, że dostałeś się tam z innego kontrolera. W takim przypadku możesz użyć metody , aby wysłać dane do części (jest to Swift 3):
Po prostu użyłem właściwości takiej jak zamiast do celów testowych. Upewnij się również, że przekazujesz prawidłowy identyfikator segmentu ( był tylko symbolem zastępczym).
Anonimowy użytkownik
Potwierdzenie od:
Ale możemy rozwiązać ten problem za pomocą metody fabryki/klasy, która tworzy wystąpienie obiektu kontrolera widoku z serii ujęć i zwraca obiekt kontrolera widoku.
Myślę, że to całkiem fajny sposób.
Uwaga:
nie jest to dokładna odpowiedź na pytanie, ale raczej obejście umożliwiające rozwiązanie problemu.
Utwórz metodę klasy w klasie MemeDetailVC w następujący sposób:
Za pomocą:
Anonimowy użytkownik
Potwierdzenie od:
Następnie inicjalizujesz MemeDetailVC za pomocą Dokumentacja firmy Apple dotycząca inicjatorów
https://developer.apple.com/li ... .html
całkiem nieźle, ale moim ulubionym jest seria samouczków
Ray Wenderlich: Initialization In Depth
https://www.raywenderlich.com/ ... art-1
samouczek, który powinien dać ci wiele wyjaśnień/przykładów na temat różnych opcji inicjalizacji i jak „poprawnie” robić rzeczy.
EDIT
: Chociaż możesz użyć wygodnego inicjatora na niestandardowych kontrolerach widoku, wszyscy mają rację argumentując, że nie możesz używać niestandardowych inicjatorów podczas inicjowania z storyboardu lub przez segment storyboardu.
Jeśli twój interfejs jest skonfigurowany w scenorysie i tworzysz kontroler całkowicie programowo, to poręczny inicjator jest prawdopodobnie najłatwiejszym sposobem zrobienia tego, co próbujesz zrobić, ponieważ nie musisz zajmować się wymaganym początkiem w NSCoder ( którego nadal nie bardzo rozumiem).
Jeśli jednak otrzymujesz kontroler widoku przez scenorys, musisz postępować
odpowiedź
https://stackoverflow.com/a/39400793/1478580
@Caleb Kleveter i prześlij kontroler widoku do żądanej podklasy, a następnie ustaw właściwość ręcznie.
Anonimowy użytkownik
Potwierdzenie od:
Podczas pracy z definicją scenorysu wszystkie wystąpienia kontrolera widoku są archiwizowane. Dlatego, aby je zainicjować, musisz użyć . jest miejscem, z którego pochodzą wszystkie ustawienia/informacje o widoku.
Dlatego w tym przypadku nie jest również możliwe wywołanie żadnej innej funkcji init z parametrem niestandardowym. Musi być albo ustawiona jako właściwość podczas przygotowywania płynności, albo można zrezygnować z segue i załadować wystąpienia bezpośrednio z serii ujęć i dostosować je (w zasadzie szablon fabryki wykorzystujący scenorys).
We wszystkich przypadkach należy użyć funkcji init wymaganej przez zestaw SDK, a następnie przekazać dodatkowe parametry.
Anonimowy użytkownik
Potwierdzenie od:
Swift 5
Możesz napisać taki niestandardowy inicjator - & >
Anonimowy użytkownik
Potwierdzenie od:
Zatem ma dwa wyznaczone inicjatory and .
Storyborad wywołuje bezpośrednio w init i , nie ma miejsca na przekazywanie parametrów.
Jednym uciążliwym obejściem jest użycie tymczasowej pamięci podręcznej:
Anonimowy użytkownik
Potwierdzenie od:
Metoda w instancji .
przewodnik:
https://sarunw.com/posts/bette ... ios13
https://sarunw.com/posts/bette ... os13/
/
Anonimowy użytkownik
Potwierdzenie od:
Zastrzeżenie: nie opowiadam się za tym i nie przetestowałem dokładnie jego stabilności, ale tak jest
potencjał
rozwiązanie, które znalazłem podczas gry.
>
Technicznie rzecz biorąc, niestandardową inicjalizację można osiągnąć, zachowując interfejs dostosowany do scenorysu, inicjując dwukrotnie kontroler widoku: pierwszy raz za pomocą niestandardowego , a drugi raz w gdzie bierzesz widok z serii ujęć.
<pre class="lang-swift prettyprint-override">
Teraz w innym miejscu aplikacji możesz wywołać swój niestandardowy inicjator, taki jak , i nadal uzyskać konfigurację widoku z serii ujęć.
Nie sądzę, żeby to było świetne rozwiązanie z kilku powodów:
Być może możesz zaakceptować te kompromisy,
ale używaj na własne ryzyko
.
Anonimowy użytkownik
Potwierdzenie od:
Ta funkcja została dodana w Xcode 11, a poniżej znajduje się fragment z
Uwagi do wydania Xcode 11
https://developer.apple.com/do ... Dobjc
:
Metoda kontrolera widoku z adnotacją z nowym atrybutem może służyć do tworzenia docelowego kontrolera widoku płynnego w kodzie przy użyciu niestandardowego inicjatora z dowolnymi żądanymi wartościami. Pozwala to na używanie kontrolerów widoku z opcjonalnymi wymaganiami inicjalizacyjnymi w scenorysach. Utwórz połączenie z segue do metody na kontrolerze widoku źródła. W nowszych wersjach systemu operacyjnego, które obsługują akcje Segue, ta metoda będzie wywoływana, a jej wartością zwracaną będzie obiektu segue przekazanego do . Wiele metod można zdefiniować na jednym kontrolerze widoku źródła, co może ułatwić sprawdzanie ciągów identyfikatorów segue w . (47091566)
Metoda akceptuje maksymalnie trzy parametry: koder, nadawcę i identyfikator segmentu. Pierwszy parametr jest wymagany, a pozostałe parametry można w razie potrzeby pominąć w sygnaturze metody. Element należy przekazać do inicjatora kontrolera widoku docelowego, aby upewnić się, że jest skonfigurowany z wartościami skonfigurowane w scenorysie. Metoda zwraca kontroler widoku, który pasuje do typu kontrolera docelowego zdefiniowanego w scenorysie lub , aby zainicjować kontroler docelowy za pomocą domyślnej metody . Jeśli wiesz, że nie musisz zwracać , typ zwrotu może być opcjonalny.
W polu Swift dodaj atrybut :
W Objective-C dodaj przed zwracanym typem:
Anonimowy użytkownik
Potwierdzenie od:
Anonimowy użytkownik
Potwierdzenie od:
Klasa B.
Klasa A