Kipróbáltam, és valóban a settings app jól néz ki. Viszont kiváncsiságból meg akartam nézni, hogy mi lehet az a “dupla távolság”, és a “Debug view hierarchy” nézetben jól néz ki az app! (legalábbis a színek). Szerintem ha a kód rossz lenne, akkor it is hibásan kéne megjelennie, viszont itt jó!
A kód nem volt változtatva, annyi történt, hogy gépet cseréltem, nyilván az Xcode és Simulator verzió frissült, és leszedtem githubról a projektet és lebuildeltem. Az előző gépen meg jó volt, ezért gyanakszok a Simulatorra. (mert amúgy semmi hibaüzenet vagy warning nem jelenik meg)
Közben sikerült közelebb jutni a megoldáshoz! A probléma forrása, hogy a telefonomon még 14.5.1 van, míg az iOS 15-ben úgy látszik rengeteg változtatás történt.
Letöltöttem egy 14.5-ös simulatort, és “érdekes módon” abban működik minden.
A “hézag” oka a cellek között az az, hogy az iOS 15ben default van egy section header padding, és mivel nekem az összes cellám egy új section és nem row, ezért ott megjelent.
Ha támogatni kell még régebbi rendszereket is akkor ez megoldja:
if #available(iOS 15.0, *) {
tableView.sectionHeaderTopPadding = 0
}
A navbar esetében a konkrét megoldásra még nem jöttem rá, de ott is az iOS 15ben bevezetett valami okozza ez 99%.
Mondjuk nem értem miért kell így módosítani pl a cellek esetében: ha valakinek kell akkor bekapcsolja. De default-tá miért kell tenni?
Még arra tudok gondolni, hogy vagy NavigationControlleren vagy magán az UIVIewControlleren Interface Builderben a Top Bar legördülő listában valami deprecated van kiválasztva, amit mondjuk most a 15-nél alakítottak át default valami mássá. A másik ami még okozhat ilyet, hogy ha ugyanitt be van pipálva az Extend Edgesnél az Under bottom Bars.
Valamint még magát a projektet, ha kiválasztod, az első Inspetorban lehet állítani, hogy melyik Xcode-dal kompatibilis dolgokat mutasson, és minden egyes storyboard és xibnél is lehet állítani szintén az első Inspectorban, hogy milyen iOS kompatibilitással buildelje le. Lehet még támogatsz régebbi iOS verziókat, amiért bizonyos beállítási lehetőségek nem jelennek meg, és ezért nem jössz rá.
Megmondom őszintén, hogy most nem vagyok teljesen kibékülve az Apple fejlesztési irányával. Ugyanis elérhető a “régi” (persze még bőven supportált) Storyboard/Xib alapú megjelenés valamint a SwiftUI. Nos ennyi UI hibát macos és iOS-en egyaránt már régen láttam, főleg meg így ebben. Szinte minden héten felfedezek valami új dizájn hibát (ma is felfedeztem egyet). Valószínű ez azért lehet, mert egyszerre kell támogatni minden újdonságot mindkét verzióban ráadásul több rendszeren is. Persze nyilvánvalóan jobb, hogy nem egyik pillanatról a másikra áll át, de így meg kétszer annyi hibát csinálnak mint eddig.
Mindenesetre mostanában döntöttem úgy, hogy bármennyire is fájdalmas, de elkezdek átállni SwiftUI-ra. Szó szerint mindent újraírok alapjairól inkább. Egyébként már az előző WWDC-n a megjelenő újdonságokat már SwiftUI-on mutatták be. Könnyebb lesz később a példákat megértenem és beépítenem. Ugyanakkor már egy projektben használok kezdetek óta SwiftUI-t és a napokban is találkoztam olyannal, hogy tvOS-en két gombot egymás mellé téve plusz a végére egy Spacer-t, az első gombon az ikon elcsúszott. Ha kivettem a Spacert és középen jelent meg a két gomb, akkor tökéletes volt. Szóval akad itt is olyan, hogy a hajamat tépem, mire sikerül úgy meghekkelnem, hogy elfogadható legyen.
Én kb másfél évig pihentettem az iOS fejlesztést, más területen mozogtam, most próbálok “visszatérni”, de sok az újdonság így mindig van valami ami kihívást okoz, persze azért nem felejtettem el mindent
Viszont én még egyelőre maradok a UIKitnél 100%ban, jelenleg még jobban használhatónak gondolom, és rengeteg cég is még egyáltalán nem állt át a SwiftUI-ra.
Nekem is megvan ez az érzés, hogy mintha kezdenének szétcsúszni a dolgok az Apple háza táján. Alapvetően az az érzésem (ez nem csak programozási szempontból, hanem pl ha csak be akarok állítani vmit a rendszerben), hogy ha valamire van megoldás/beállítás az általában teljesen egyértelmű, működik. Na de ha nincsen akkor az valami elképesztő szívás tud lenni, hogy mégis meg legyen valahogyan oldva. Egy példa: feljebb itt a screenshoton amit feltöltöttem, a navbaron van egy gomb a bal oldalt és egy kép középen, viszont semmi sincs a jobb oldalon. Alapból, ha ezt így meg akarom csinálni, akkor vmiért bugos a megjelenités és a középen lévő kép kicsit jobbra csúszik, ami nyilván nem néz ki jól. Ha berakok egy gombot a jobb oldalra akkor jó. Emiatt meg kellett “hackelni” és most job oldalon van egy átlátszó gomb ami nem csinál semmi, az interakció le van tiltva.
Szóval erre gondolok, hogy ha nem működik akkor totális szívás. Dokumentáció szerint felrakom a bal oldalra a gombot, meg a képet és nem úgy néz ki, mint kéne. Innentől meg lehet gondolkodni, hogy mégis hogyan lehetne megoldani a problémát…
Igen, egyébként alapvetően én is így érzem. Ugyanakkor a SwiftUI-nak van két hatalmas előnye:
Ami nyilvánvaló, hogy az UI dizájnerek és programozók egy azon fájlon dolgoznak. Azaz nem kérdés, hogy “most ezt kódban írtam át vagy a storyboardon módosította a dizjner?”.
Dizájn (talán) pattern alapú fejlesztés. Azaz, ha van egy alap UIView(Controller), aminek van egy megjelenése, pl.: háttér, fejléc, lábléc, amely nagyon sok másik UIViewnál ismétlődik, akkor azt, ha Storyboardozni akarsz, akkor azt másolni kell. Ha módosítasz valamit akkor minden egyes UIView esetén meg kell csinálnod a módosítást. Vagy nyilvánvalóan mindent programozással oldasz meg, de akkor meg minek egyáltalán a szerkesztő?
Jártam úgy, hogy nagyon sokat módosítottam egy Storyboardon, majd később vettem észre, hogy véletlen egy elemet áthúztam egy másik view alá, így elvesztette a többi elemmel a viszonyát. Mire mindent újra sikeresen visszaállítottam, az több óra volt, mert meg kellett néznem több eszközön, alló-fekvő nézetben egyaránt. És azért megnézem, hogy sok módosítás esetén bárki hogyan állít vissza bármit “verziókövetésből” …
Na, ilyenekről beszéltem: van a safeArea, amely az a terület, amelybe nem lóg bele pl. a notch, azaz minden elem ezen a területen belül látható. Lekérdezhető, hogy hány pixelre van a képernyő tetejétől, ez a “top” érték. Ezt SwiftUI-ban GeometryReaderrel lehet lekérdezni. De itt jön az, hogy hogy a büdös életben nem tesztelték ezt úgy, hogy elrejtik a statusbart felül? Ugyanis, ha elrejted (azaz ne látszódjon felül az óra és hálózat), akkor ez az érték 0 lesz, azaz a tartalom szépen becsúszik notch alá.
Új sima iOS app projekt az Xcodeban, nyilván SwiftUI megjelenítéssel, a projektben a ContentView.swift fájlban preview kódja ez legyen:
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
GeometryReader { geometry in
VStack {
Text("safeAreaTop: \(geometry.safeAreaInsets.top)")
.padding(.top, 40)
}
.statusBar(hidden: true)
}
}
}
Ezt az értéket egyébként iPhone 13 Pro Max készüléken kaptam, nyilván más készüléknél más lehet az érték. A probléma egyébként nem csak az, hogy nem tudom mennyi a safeArea top és bottom értéke, hanem a terület méreteit sem tudom pontosan így. Természetesen ez is “meghekkelhető”, de megint vissza kell nyúlni az UIKit-hez, azaz a SwiftUI-t magában használni még mindig lehetetlen!!!
Itt valamit nagyon osszekeversz. A “Safe Area”-nak SEMMI koze nincs a notchhoz se a lekerekiteshez. Ahogy a doksi is irja, “reflects the portion of the view that is not covered by navigation bars, tab bars, toolbars, and other ancestor views”. iOS7-iOS11 kozott kulon volt szedve top es bottomLayoutGuide-ra, es iOS11-tol nevezzuk “Safe Area”-nak. Ha van egy “view”-d es azon van statusbar, akkor a statusbar alatti terulet a “Safe Area”. Ha ugyonerre a viewre feldobsz egy navigaton bart akkor a navigation bar alatti terulet lesz a “Safe Area”.
Igazad lehet, ugyanakkor fura, hogy UIKit-en, amikor van egy top és bottombar mentes ablakom, a constraint-ot be lehet állítani, hogy a SafeAreaoz igazodjon. Ott viszont szépen kihagyja a notchot, akkor ott ez miért van?
Ez pontosan hol van? Mert, ha pl az Interface Designerben allitgatod a constrainteket, ott “relative to margin” eseten a notcon es kerekitesen belul marad a dolog.
Erről beszélek, a Second Item a Safe Area tophoz igazodik, ami maga az UIViewController view-ja. Bár a képen nem látszik, de a “Top Bar: None” értéke van, azaz nincs navigationbar felül. És ezért gondoltam, hogy a SwiftUI-ban is a SafeArea az mindig “notchnélküli SafeArea” akkor is, ha nincs semmilyen topbar.
Es azt mondod, hogy statusbar sincs? Mert ugye a statusbar is resze a safe areanak. Bar erdekes, mert nekem az a tapasztalatom, hogy siman a notch ala megy a content. Lehet van valami mas opcio, ami ezt okozza.
Még azt vettem érdekességként észre, hogy az egész navigationcontroller alá van szervezve és ott van kikapcsolva a topbar. Ugyanakkor direkt emiatt kipróbáltam, hogy magán az UIViewControlleren kapcsoltam ki a topbart, ne Inferred legyen, de nem változott semmit sem.
Viszont kipróbálom, hogy beteszem navigationcontoller alá SwiftUI-ban is és kikapcsolom a navigationbart és meglátjuk mi lesz.
Újabb dolog, ami nem működik egyáltalán SwiftUI-ban: az NSParagraphStyle. iOS 15-től elérhető az új AttributedString, amelynek van paragraphStyle értéke, amely NSParagraphStyle-t vár és egyszerűen nem foglalkozik vele a rendszer. Ugyanaz a paragraphStyle megadva UILabelnél szépen működik.
(Aztán majd jól kiderül, hogy megint benézek valamit vagy nem jól használom és működik az… remélem így lesz :D)
Így utólag tudom, hogy nincs más opció a statusbar és safearea beállításokkal kapcsolatban. Csak nem mindegy, hogy hol definiáljuk a statusbar elrejtést. Persze a koncepció nyilván az, hogy öröklődnek a beállítások a beágyazott tartalomra. És emiatt egy kicsit furcsa is a működése, de tegnap megtaláltam a “natív” megoldást véletlenül…
Szóval a hiba csak annyi volt, hogy a korábbi példámban nem a VStack-re kellett volna alkalmaznom a statusbar elrejtést, hanem a külső GeometryReaderre, és akkor a tartalmon belül megmaradnak a safearea értékek.
Pontosabban: valamiért nem egészen úgy jelenik meg a Previewban a tartalom, mint elindítva simulatorban. Azaz alapból nem látszik a statusBar, viszont ha alkalmazom rá a statusBar elrejtését (mint ahogy a main App-ban is van), akkor történik az, mint amit korábban írtam.
Szóval még mindig nem értem teljesen a koncepciót, hogy miért volt hibás az, hogy a tartalomban rejtettem el a statusbart. A képen látszik, hogy kijelöltem a VStacket, és az előnézeti képen bejelölte a rendszer zöld kerettel. Ebből látszik, hogy valójában felveszi a safearea méretet. Bár a background color túlnyúlik rajta, valószínű annak más oka van (ennek szemléltetésére tettem oda az “akarmi” szöveget).
A képen látható preview teljesen megegyezik a simulatorban megjelenő alkalmazással: