Zdaję sobie sprawę, że to pytanie zostało już zadane, ale odpowiedzi są sprzeczne i jestem zdezorientowany, więc proszę, nie pal mnie.
Chcę mieć UIView
podklasę wielokrotnego użytku w całej mojej aplikacji. Chcę opisać interfejs za pomocą pliku nib.
Teraz powiedzmy, że jest to widok wskaźnika ładowania ze wskaźnikiem aktywności. Chciałbym na jakimś zdarzeniu utworzyć wystąpienie tego widoku i animować go do widoku kontrolera widoku. Mógłbym opisać interfejs widoku bez problemu programowo, tworząc elementy programowo i ustawiając ich ramkę wewnątrz metody init itp.
Jak mogę to zrobić za pomocą stalówki? Utrzymanie rozmiaru podanego w konstruktorze interfejsu bez konieczności ustawiania ramki.
Udało mi się to zrobić w ten sposób, ale jestem pewien, że jest źle (to tylko widok z selektorem):
- (id)initWithDataSource:(NSDictionary *)dataSource {
self = [super init];
if (self){
self = [[[NSBundle mainBundle] loadNibNamed:[NSString stringWithFormat:@"%@", [self class]] owner:self options:nil] objectAtIndex:0];
self.pickerViewData = dataSource;
[self configurePickerView];
}
return self;
}
Ale nadpisuję siebie, a kiedy go utworzę:
FSASelectView *selectView = [[FSASelectView alloc] initWithDataSource:selectViewDictionary];
selectView.delegate = self;
selectView.frame = CGRectMake(0, self.view.bottom + 50, [FSASelectView width], [FSASelectView height]);
Muszę ręcznie ustawić ramę, zamiast odbierać ją od IB.
EDYCJA: Chcę utworzyć ten niestandardowy widok w kontrolerze widoku i mieć dostęp do sterowania elementami widoku. Nie chcę nowego kontrolera widoku.
Dzięki
EDYCJA: Nie wiem, czy to najlepsza praktyka, na pewno nie, ale tak to zrobiłem:
FSASelectView *selectView = [[[NSBundle mainBundle] loadNibNamed:[NSString stringWithFormat:@"%@",[FSASelectView class]] owner:self options:nil] objectAtIndex:0];
selectView.delegate = self;
[selectView configurePickerViewWithData:ds];
selectView.frame = CGRectMake(0, self.view.bottom + 50, selectView.width, selectView.height);
selectView.alpha = 0.9;
[self.view addSubview:selectView];
[UIView animateWithDuration: 0.25 delay: 0 options:UIViewAnimationOptionAllowUserInteraction |UIViewAnimationOptionCurveEaseInOut animations:^{
selectView.frame = CGRectMake(0, self.view.bottom - selectView.height, selectView.width, selectView.height);
selectView.alpha = 1;
} completion:^(BOOL finished) {
}];
Nadal potrzebna jest właściwa praktyka
Czy powinno to być zrobione przy użyciu kontrolera widoku i inicjalizacji z nazwą końcówki? Czy powinienem ustawić końcówkę w jakiejś metodzie inicjalizacji UIView w kodzie? A może to, co zrobiłem, jest w porządku?
initWithDataSource
? W każdym razie to zadziała, nawet jeśli podasz właściciela jako „Zero”.Odpowiedzi:
Używam tego do inicjalizacji widoków niestandardowych wielokrotnego użytku, które mam.
Zauważ, że możesz użyć "firstObject" na końcu, jest trochę czystszy. „firstObject” to poręczna metoda dla NSArray i NSMutableArray.
Oto typowy przykład ładowania xib do użycia jako nagłówek tabeli. W Twoim pliku YourClass.m
Zwykle w programie
TopArea.xib
należy kliknąć opcję Właściciel pliku i ustawić właściciela pliku na YourClass . Wtedy faktycznie w YourClass.h miałbyś właściwości IBOutlet. W programieTopArea.xib
możesz przeciągać kontrolki do tych gniazd.Nie zapominaj, że w programie
TopArea.xib
może być konieczne kliknięcie samego widoku i przeciągnięcie go do jakiegoś gniazdka, aby w razie potrzeby mieć nad nim kontrolę. (Bardzo cenną wskazówką jest to, że robiąc to dla wierszy komórek tabeli, absolutnie musisz to zrobić - musisz połączyć sam widok z odpowiednią właściwością w kodzie.)źródło
Jeśli chcesz zachować swoją
CustomView
i jegoxib
niezależnośćFile's Owner
, wykonaj następujące krokiFile's Owner
pole puste.xib
plikuCustomView
i ustaw goCustom Class
jakoCustomView
(nazwa własnej klasy widoku niestandardowego)IBOutlet
w.h
pliku swojego widoku niestandardowego..xib
pliku widoku niestandardowego kliknij widok i wejdźConnection Inspector
. Tutaj znajdziesz wszystkie swoje IBOutlety, które zdefiniujesz w.h
plikuw
.m
pliku swojejCustomView
klasy nadpiszinit
metodę w następujący sposóbTeraz, gdy chcesz załadować swój
CustomView
, użyj następującego wiersza kodu[[CustomView alloc] init];
źródło
-init
. Zamiast tego zadzwoniinitWithFrame:
i-awakeFromNib
. Jeśli napiszesz ten sam kod, aby załadować swój widok, jak w-init
metodzie, wejdziesz w nieskończoną pętlę.Wykonaj następujące kroki
UIView
.MyView.xib
.UIViewController
fromNSObject
in xib. Zobacz obrazek poniżejPołącz widok właściciela pliku ze swoim widokiem. Zobacz obrazek poniżej
Zmień klasę swojego widoku na
MyView
. Tak samo jak 3.Oto kod do załadowania widoku:
Mam nadzieję, że to pomoże.
Wyjaśnienie :
UIViewController
służy do ładowania twojego xib i widoku, któryUIViewController
ma, jest faktycznieMyView
przypisany w MyView xib ..Demo Zrobiłem chwycić demo tutaj
źródło
Odpowiadając na moje własne pytanie o 2 lub coś później tutaj, ale ...
Używa rozszerzenia protokołu, więc możesz to zrobić bez dodatkowego kodu dla wszystkich klas.
źródło
W Swift:
Na przykład nazwa Twojej klasy niestandardowej to
InfoView
Najpierw tworzysz pliki
InfoView.xib
iInfoView.swift
tak:Następnie ustaw
File's Owner
sięUIViewController
podoba:Zmień nazwę
View
naInfoView
:Kliknij prawym przyciskiem myszy
File's Owner
i połącz swojeview
pole zInfoView
:Upewnij się, że nazwa zajęć to
InfoView
:Po tym możesz bez problemu dodać akcję do przycisku w swojej niestandardowej klasie:
I użycie tej niestandardowej klasy w
MainViewController
:źródło
Cóż, możesz albo zainicjować xib używając kontrolera widoku i użyć viewController.view. lub zrób to tak, jak to zrobiłeś. Jedynie tworzenie
UIView
podklasy jako kontroleraUIView
jest złym pomysłem.Jeśli nie masz żadnych gniazd z widoku niestandardowego, możesz bezpośrednio użyć
UIViewController
klasy, aby ją zainicjować.Aktualizacja: W twoim przypadku:
W przeciwnym razie musisz zrobić niestandardowy
UIViewController
(aby uczynić go właścicielem pliku, aby gniazda były odpowiednio podłączone).Gdziekolwiek chcesz dodać widok, możesz użyć.
Jednak przekazanie innego kontrolera widoku (już używanego dla innego widoku) jako właściciela podczas ładowania xib nie jest dobrym pomysłem, ponieważ właściwość widoku kontrolera zostanie zmieniona, a gdy chcesz uzyskać dostęp do oryginalnego widoku, nie mieć do niej odniesienie.
EDYCJA: Napotkasz ten problem, jeśli ustawiłeś swój nowy xib z właścicielem pliku jako tę samą główną
UIViewController
klasę i powiązałeś właściwość widoku z nowym widokiem xib.to znaczy;
Poniższy kod spowoduje później zamieszanie, jeśli napiszesz go w środku, widok został załadowany
YourMainViewController
.self.view
Dzieje się tak, ponieważ od tego momentu będzie odnosić się do Twojego widoku niestandardowegoźródło