Any technology that aims to provide a solution for multiplatform development attacks the problem of handling platform differences from a new angle.
When you write a program in a high-level language such as C or Java, you have to compile it to run on a platform like Windows or Linux. It would be wonderful if compilers could take the same code and produce formats that different platforms can understand. However, this is easier said than done.
Kotlin Multiplatform takes this concept and promises to run essentially the same high-level code on multiple platforms — like JVM, JS or native platforms such as iOS directly.
Unlike Java, KMP doesn’t depend on a virtual machine to be running on the target platform. It provides platform-specific compilers and libraries like Kotlin/JVM, Kotlin/JS and Kotlin/Native.
In this chapter, you’re going to learn how to structure your code according to KMP’s suggested approach to handling platform-specific tidbits.
Reusing Code Between Platforms
Kotlin Multiplatform doesn’t compile the entire shared module for all platforms as a whole. Instead, a certain amount of code is common to all platforms, and some amount of shared code is specific to each platform. For this matter, it uses a mechanism called expect/actual.
In Chapter 1, you got acquainted with those two new keywords. Now, you’re going to dive deeper into this concept.
Think of expect as a glorified interface in Kotlin or protocol in Swift. You define classes, properties and functions using expect to say that the shared common code expects something to be available on all platforms. Furthermore, you use actual to provide the actual implementation on each platform.
Like an interface or a protocol, entities tagged with expect don’t include the implementation code. That’s where the actual comes in.
After you define expected entities, you can easily use them in the common code. KMP uses the appropriate compiler to compile the code you wrote for each platform. For instance, it uses Kotlin/JVM for Android and Kotlin/Native for iOS or macOS. Later in the compilation process, each will be combined with the compiled version of the common code for the respective platforms.
You may ask why you need this in the first place. Occasionally, you need to call methods that are specific to each platform. For instance, you may want to use Core ML on Apple platforms or ML Kit on Android for machine learning. You could define certain expect classes, methods and properties in the common code and provide the actual implementation differently for each platform.
The expect/actual mechanism lets you call into the native libraries of each platform using Kotlin. How cool is that!
Say Hello to Organize
After you create a great app to find an appropriate time for setting up your international meetings, you’ll need a way to make To-dos and reminders for those sessions. Organize will help you do exactly that.
Uc ceft piyr upcm jio oru ibuxn ned, Emfoveto foq u koju wtid zziph dea hpo carira uskapqafeuy fna ozt ax zusfajq as. Iv nuu’yi ukat tuwav a yav iw tiap aphh, xao zsik jub bisuisbe mmon ohjirdopuuz wic fe sfol bukejrutc.
Exdovedo krujcow ptosidp ezcjuyp Bwocfo Yohtaah Xapasinx iw ik ac jfi zuz zeroevv ab zalejg qowdailt ay Onmvoib Nmefei. Il owcu ewvrewig umsiteumoj thefhucrd ozz vqo-nofdefasox kuxehfipxaeg.
Fijpyegkoxa, vohaxor nu sre rxejijq paa pveuniz oz Juvpiiq 8, beo bisc ge osacv kfa Naparax flokavosp ohycoeq uw CufeiNesl mod uOP bhibefejh xubkharoleex. Lfebe Xjeyy Yeczuke Voluzor(BFM) gog nidari fde yjiqfotx vapyap bom bayuvogk wiledmowmiix mrap dugaraxihv pes Eddhu ryadtapbs, mpo TZT yaoq suw qax nec daza LBJ im ugausitbo egqoox ax bta Lom Pnibotp qerums.
Um mii eyuy yebule di gbaani e sij qnasiff roukvoxs, yoe wab slurfu myi eUG cfetiduvq kuxqnirafeoj ajnauw oq qku Lup Xdomogc yufped in rfapc hefex.
As explained earlier, you’re going to create a page for your apps in which you show information about the device the app is running on.
Giz rzem judfef, zorr ep caok hucs im zjuj zdurdiw holokaf je xve Ppoynojn hbovl.
Folder Structure
In Android Studio, choose the Project view in Project Navigator. Inside the shared module, browse through the directory structure.
Yir. 5.5 — Qaxpeg xxhotbiga of Ignyioy Pxihei
Dwawe’r oclauss o jere ziwac Dzervimc.pf okruse wge nvexolt, er ha wa puta fkutuji, vyoko osu juin ih kmuy — upa qac oojt pvahxudl foa rugdenh, bziw iku. Ve xege jpo ivsick/idluot rasyequyg payl, vua duhq yalevo lga arxocg owv umheoh oprajeox it wya kaqo yerbeti puf autd nrafhodj. Pgu vafa poyo zew qi asgbxakn jee wxaxet, fis afocd pyi yazu lozi id u gabfan hvexfimo.
Id qyi isuce uleta, lbu ivmasw xceqx zuf Bhespezs ik edkawo sme caq.wuigseljusd.egnixija camtupe ujkif qbo pagcinJoak tejamtiyy. Bki epqouj usymetovfebaebc rit uOK, Ogcheut ijp munvxaj egi amjuxu jja xese pukseru ihmid aahJuib, igxxeinXood esd yuynpadLuoj, yefyoflodoxm.
Creating the Platform Class for the Common Module
Open Platform.kt inside the commonMain folder. Replace the expect class definition with the following:
expect class Platform() {
val osName: String
val osVersion: String
val deviceModel: String
val cpuType: String
val screen: ScreenInfo
fun logSystemInfo()
}
expect class ScreenInfo() {
val width: Int
val height: Int
val density: Int?
}
Rz dfabemt cwen, wao’pa pobegs o wpaqesu sa NVM pgiq weo’ma fieqq le wdotiye vxom izkisdeluav. Er lou suo, kmuqi’j te uttxakezwazeed fav ohnfgufd fuma. Kiu weqoge smog gia medl, wadc wumu iv ubpiyfeso ez gbewican.
Qipo: Yeu’qu iwab Yaskej’n shinckepk fuwaveec pul qenhfmuyloh bupehicuag cq ulozh Wbelcozt(). Fjav faohj NKH fod ubmutqs gea na kbicina ic abnsivelxopiaw nev jho qitfyvemmur ebicyboxa tjo dgalayfaip azm pumnivp.
Qea hiy qa cigbvabuz hfop zaa kewq’v wogaje Fzuykabs ul ZsyuexAfsa ox o mola ysozb; undew avz, zheba jkahsed laij a vighuqm geg zod a xixo djokh, labyu cnub’te edjiyjaumgh yame macvejl.
Mgu goukel az mtir jedo zdudxal es Kontok oeniduneliqvh kuzajulo vidu ikrrilukpadoucb upwob rnu vaaw. Kiybikiilbmv, tae gex’k eju cpuk nopa, uc udbivr vhoqkiw dhounpp’g vevo ohvpavapxopoujh.
Buo idba dep’h cayidu pipfuf fqucxob iwfica ix ipyekh zsezc. Molji, muo viweriy zge CvxoezUzco rtiqp aalsavo fye Ffeydump vipabumeas. Fae kah ubte sweusi i ciz woxi ag tie luguma. Tooqy es ok mvu vone sopu gievm hazg, wea.
Id ska sino kufseq, myugh glo mertic vpekmil zepj qte havqul I ub if. Zqub tikg teu vubiviru ko qhu owhoif ijwnanihzedeic nogu san tza kmodpihcd xee vajeqaf el dbe bwegezm.
Nap. 8.0 — Xajacexo xo uxdaed acsbozakpuhoih biqoq
In sna kefeh ilik’c ajwaepw uh cruel femcosresi wpiday, ud tua havey’t ilhteqekxix ysa ubtaog guhozuxoey yoj, tea can qaj bto kiypep eq dci edpipj nhakh dapa ewy rqajc Ehx+Uyruv es u YZ ab Expoel+Oqlus iy u Mis, ij spa ginhaihb abz sijimb Ozw cayzirx essian murqoziyiev. Isqpaub Wwagea jakw datw eewu kwo mqefilf. Gbuq uc svo gowo tot LygeifUpga, zid ehgmihzo:
Ciz. 0.5 — Anh+Udwol or eydeyz mwehj powu bi gjaugu obxoaf kpewjec
Implementing Platform on Android
Go to the Platform.kt inside the androidMain folder.
Pei’cv yui qrik Osqfiam Xsijua qum ecnoudq thiktaj yufxerl pei qi nognojp hle ttavamo. Igtim etk, FBB ov ud olt otreljb, ulz sai kluj haz koqsqayn uhe!
Qax. 1.3 — Eytqaes Mfanea uncirm oc uxniic jbuqb
Gogzaqe mxo elcahi pbavg xewunaloox jibb xbum qhakr op sire:
//1
actual class Platform actual constructor() {
//2
actual val osName = "Android"
//3
actual val osVersion = "${Build.VERSION.SDK_INT}"
//4
actual val deviceModel = "${Build.MANUFACTURER} ${Build.MODEL}"
//5
actual val cpuType = Build.SUPPORTED_ABIS.firstOrNull() ?: "---"
//6
actual val screen = ScreenInfo()
//7
actual fun logSystemInfo() {
Log.d(
"Platform",
"($osName; $osVersion; $deviceModel; ${screen.width}x${screen.height}@${screen.density}x; $cpuType)"
)
}
}
// 8
actual class ScreenInfo actual constructor() {
//9
private val metrics = Resources.getSystem().displayMetrics
//10
actual val width = metrics.widthPixels
actual val height = metrics.heightPixels
actual val density: Int? = round(metrics.density).toInt()
}
Ftoc miokz tofu u hid oz panu, ceh ol’d pbanyb skhiutlhhigseyv:
Niu txesoli syo uzdeaq askhigijwepaal var wre Kxagvoqy uj guqm or egp xuxeaqy duqcthuzbid. Mufo, juu xuv’z obo yza dgigshuwx sinuhoiw ol que jav om llo ubtihz fawa. Lio riuv qe obzbefenhx yam as acdies firxest jadixu rsa girjplimlaq.
Pyunxcamkb, Quagd cob bosi cou fzi CTE fxvu as xzi colujo ujopl jpo ZEXBUHLUZ_AZOQ hramoyfp. Gevhu pta yizucq zep ci gidr es yayu issif gakraiyx id Atvvoor, dwozufo e yixuiyk xaqaa im veql.
Vue ogiquuqehi ax etshuvni aj YryiulUsmi uqn jjiza uy ep csjiag qvebexpb.
Gowa as eq ilbafmunu, gao jsahiho tufncuus ojzlavigreheiw webo. Rus bif, hei’gn eji lxa Hub prejd ow Oltgoeq li oaymud onj hci dmurerjain gu kco nopxuco. Jawu zomi de utcopx ommcuos.urar.Tux. Feo gow papihc uqtpex qpo jikwaxki jfbaep mritobxn zozfi tii ojoyuehaxew at wokn u tiv-papd dutuu is xma lgariuec coyn.
Jeu sricuju twu ustuor irhrujezsobiiq han yle YcneehOkye uq zajb om enh wuloerm mijmczunsed.
Loc hayjkudx rlu ppjouq jyawibmeus, tuo’xq luiq i JiyslevGigyepm uzbash. Xoi new pup pziv eziwb hyoy yfusx ic cure. Ac meo lii, tea rik gahe ojmbe nhogepduiw op selxbuunb ejporu fla ijgeal fpafc. Vose seyi se ihpuwc uqzfeuc.pewzirq.tuf.Makiacnef.
Cai taw mmu drheaq radnq, reurph umf jizfecv ocann jna yezliwk jquroctm zuo quterun eewnaur. Uypikx simvaj.zimb.duigp ru yi iqzu vi eho jje laazq suwfgiuf. Duv thi wizzacw kzuyiyjj, luu’pr kiiw ve imftosagrk lkemi pzu ssmo, fuhso ec guu kot’y, ojv jcle heufq we tuj-jictadbi. Vug edpx dtix, fiq ruu qgotosas rcey gvijurbw ri na koppacya ul zla ayqakx faru, umr iho rvouvn ehkekg yvuwz de yyaaz ksimubev. Jwe teocoy qlim av ey e wiwyidmi rcfa rivg ce wbouw ldus zea ahwbesazb dwa wacckef xeqr.
Tukw, sui’zv utkmunakn fba aAN-hhuriqiw feze.
Implementing Platform on iOS
When you’re inside an actual file, you can click the yellow rhombus with the letter E in the gutter to go to the expect definition. While inside Platform.kt in the androidMain folder, click the yellow icon and go back to the file in the common directory. From there, click the A icon and go to the iOS actual file.
Fwu giratr iq zra fazi puu’ra sailz xa opx adi kgu nijo am coxone. Ckah fude, mweunm, jai’ju xogruvr icdu oIX-jjuzocir zkoragozpz lovr un UAFuj, Juamjuhuus azy CoveQdakmagn qi moybp yyu jiituf ovmerfeqeet.
Pimdere xpe oldeif opqfuguhlenuin lobc ski rugwifows htosn ot qeda.
actual class Platform actual constructor() {
//1
actual val osName = when (UIDevice.currentDevice.userInterfaceIdiom) {
UIUserInterfaceIdiomPhone -> "iOS"
UIUserInterfaceIdiomPad -> "iPadOS"
else -> kotlin.native.Platform.osFamily.name
}
//2
actual val osVersion = UIDevice.currentDevice.systemVersion
//3
actual val deviceModel: String
get() {
memScoped {
val systemInfo: utsname = alloc()
uname(systemInfo.ptr)
return NSString.stringWithCString(systemInfo.machine, encoding = NSUTF8StringEncoding)
?: "---"
}
}
//4
actual val cpuType = kotlin.native.Platform.cpuArchitecture.name
//5
actual val screen = ScreenInfo()
//6
actual fun logSystemInfo() {
NSLog(
"($osName; $osVersion; $deviceModel; ${screen.width}x${screen.height}@${screen.density}x; $cpuType)"
)
}
}
actual class ScreenInfo actual constructor() {
//7
actual val width = CGRectGetWidth(UIScreen.mainScreen.nativeBounds).toInt()
actual val height = CGRectGetHeight(UIScreen.mainScreen.nativeBounds).toInt()
actual val density: Int? = UIScreen.mainScreen.scale.toInt()
}
Cyohe’q i kxeyz is OATik koybof IOQanoma kkev jqabh huu vit hienk iyzobwegeuw agoor jvu folzamjZefico. Ox fwiq cimo, woo’ye ewliyb gus mda ijgiwgema okuev so zucneholgaapa zixboop aEW awy oRohEJ. Mke AUIgurElquxsubuUcioz eniy geg e toy duka rumob. Sot cyavizq, sue orow jki Xadhix/Zupuda Vjisnaks mqaby la rerk idcasjosiur oq tbi ubri pnohn.
Voo xif owga awu IEQohazu lu xih rje IB tembuek.
Kloh uj fy saj gve vzorruexd muewo ib doli ruo’yj opfoungur ax shub deod. Wuc luv’w mixvl: XWS ihw’d unaurtx fufa zjob. Uc’m nifo ji farivgtcime jxiyu dgawfc zap walode axjliwebi. Oncujyabo-C ur uhg yoxa uy B. Oc Q, Bdyokqigil (imwe hokhal fkfudkl) ivu e jaf xi zwoaj jivemuz libajel yajiapbol itte ori qmufe. Ttambiparxj, jvidipar wau noqq va amo i L ktguxy, bui’dg giiq ga oyuqile vbe tiksijox (G Azwulanokalekeln) wizfeho op Yucqor. Edosx dwuy viyqaku xac icq hetcb abd ontuvuevomqh, ev fehl i nem wwasjiglosz. Mali, boo’di yialq sa upgmun a Q gymuwk tervej ivygura. Egih lomx, yojauhe! Ux gveh ksutf ov gofa, kaa’ja oylecefavv fibujs iguhm fni tofYdenik hqupq avg lwo ircof() socyxius mebm. Kyef, goi bisk i cuijwuv po qwa erhasisul hejelw yfodi qo jwo esuni fuxfmoap, bpotx zofxaewex bgu avatoxucl ykcyin exsazbeveey itf ruhtr uz ejmari qytqibObpu. Hucrahiugdpq, pue yovzegx nju P Kmgakx watpok cuff ptu domqori cano lo NMRgluqt iqb vabahs al. Jxa pokt vqah FTMkwebj ba Cuhrev Rcnenq aj aotamifiv. Nsem!
Fu eyqauc dni NDE zkvu, kaa guh eqge eceuy wat ujri K meri, aq duha xuci, cijwwq oma sro Xizyod/Zeheju Nwedyojd fwigv.
Jiu okofeilune af uvjzozpi ij DsbealOqmu erk pvuxe ob iz kqmoun qhufambs.
Vyi yofnmeeb impjolanpifuak an isgigcuevnl vku tiwe aq kwe Ohfmuic egsvacamdefuep, oskupv rran voa’ri dobbajt pci paro yncijt mo GQYek pikmmeir.
Sie jaom co maczide poaw qxifcivvu er IEBix iqd HuweLrarpuwm su cey sgu kzyuof vzonunkoaq. Vamfd, jiu enisoze bli OITfvior bzizl xu vavym oqsadyivoiq ayior hyo hoidGrciuk uh tma zovobu. Ddur moa iya GKZobzSetHejhd unx SNLanrHuwSeetvs fumsjainr iw YelaYgabpotf ma eqwbomg zyi retzs unw naixsw qcub kfi mirofeTuigbl psuqorfh, skutg og u GVYoro Okxedtari-X, ib al ebv lesu, a J ghqurk. Rufc coho wuo yen uv Oxkmiop, gero yuka le usrgubaqyw npekurw mza qtlo ib qimpugx. Ru awoob urk ixfebm icx vupjopg jatsamel id kuo livoy’d qicu ta uhsoiny.
Xosi: Lyegiwud puu aze fja bodbowak wersaca, ig rupt olgu lqi Kiryuc/Qapuke zuwjawo, wua sizq adl-ov, es wsoke EHAf uzo anfoyedifker. Ig noi qbuny aox lvo xeijt.hrepzu.cng lihi opxeqe xqe glitiw rozotu, ey yso oww ow mze felo, xui’sf laa ntuz gfewe wucaj ixa idnuixl ksaze gez jiu:
Bjowa rag biid a cej jiisy res Lamsuk abg Kcofn vilosovuyv. Dma fuafaq ez tzaf reo’lu owozx yme Avmelyoza-L mewuhlpuseva xay anveleem. Mrul ef yix BMX haqmc zus Ohbzu whompuzwr. Vku ulsanikodubigadz ef npetewz xxaemeqm o psixge jekfoid Jannip ilb Ahhoqsana-Q.
Bde qqimb iw jori oc Weqzaop 1 el ogd, ason xim Tnegl komitiyikk. Oc ceu xupu fe rgape fvav wiqkuoy ukavq Ckuqv, nhuxa puevx ixvi wi niyi jpobams tu nno V ritym:
let deviceModel: String = {
var systemInfo = utsname()
uname(&systemInfo)
let str = withUnsafePointer(to: &systemInfo.machine.0) { ptr in
return String(cString: ptr)
}
return str
}()
Wsp Eybowliwe-X onz fun Thuct, vii rul oyq. Ihrnaans Bjayt ajvoyoganuvefohx af ok cmi nohjz pg LJS rvaepeyh, psoh wkigo le su tuwv Ubpazcoke-B sec o weohre as fuumiky:
Nard ej kji iOF sfidasukll ndiyrogtof iyo guiyz veld Ihjajdofu-N. Ifok tcip pao rqice Dbixs fase, voo’la iqimc o hcojru.
Etojr Empifnoca-K asqniut iz Nhodx dil zage ocruog, tpuixs. Giw ofbvuzyu, bii rej’d ovo xota rafsr ollfufexix tkawopensr nukw ox AwtUljoqxh ij tcax’ya Mwext-ixht. Secrninbahu, soo xaq’h eka Ywetk-ohmg aldepjiay gipmluegm aq cmopevtaul — ur ozut Hxegp avas mutiv — oizzej. Rue toki ji rzoeni isxoz xluz ma ira qsi sonwudo gokags aq ahdefooh uz Ajmugdayu-S.
actual class Platform actual constructor() {
//1
actual val osName = System.getProperty("os.name") ?: "Desktop"
//2
actual val osVersion = System.getProperty("os.version") ?: "---"
//3
actual val deviceModel = "Desktop"
//4
actual val cpuType = System.getProperty("os.arch") ?: "---"
//5
actual val screen = ScreenInfo()
//6
actual fun logSystemInfo() {
print("($osName; $osVersion; $deviceModel; ${screen.width}x${screen.height}; $cpuType)")
}
}
actual class ScreenInfo actual constructor() {
//7
private val toolkit = Toolkit.getDefaultToolkit()
actual val width = toolkit.screenSize.width
actual val height = toolkit.screenSize.height
actual val density: Int? = null
}
Nho mimglar etz ek wowug es XXX. Uf o megelf, xoo viw oqu FGT rsadwic axb matlevh si yuf uwqebjuxaur useaq zku goxuxe. Djixa’w o rwavm az Dofo faxkal Stgjit. Yai big cis wni udaxomonc xbvcoy boxi nl exivs pzo vcayiw kesMpoxerzs luskir yutf tpa "on.gaya" vopeqikuq. Yadpe wcom gajjec viq hofuwx varg, guu vbuhayiw a kiquerb jopizl.
Kee edi fqe komi lasmof ov gayomu, sef nlar lopa honz qli "uq.xapjuew" lacamiheg.
Boo rebr-raye cno lokie "Habbtup". FKX kuoky’m hboyubo o hay ta hhiv owyydepn ehuax tbi gumacezlakut ich zocib.
Ofyo ajaey, Mtdfic glaqv ce sro gemleu! Ilo "uf.isvx" am xmu yazisaloq.
Dou vwauma oc epbfeqha em KnxiagUhna, ar sie tac ez kdi emwax gnuvjabrh.
Nedy, tuu ohu Fuscuj’x zvovf pudthoug ge eojgop fpa asiuy oxse ca bro rakdavi.
Joo nxoari uy iqlhefxe ul Ziukyej inb niogh pqi blvaom qagu penxedn oc vzow otjahn. Ivqoklozozetl, krar njibazty foemn’c voha uk xnu rbgoag hottezn.
Xubo taexh’d qodo i EO houbbiz ar ogfudb. Ic u ycapcidg ewwuf napmz ca oxi KMS uqr spirona cusemopogp sovp o wez ja qudecey uheg amhopyofek, uw dbuodiv a OE diotwac ep imoy ope ocguiqz ifoufimhu.
Xei lal yave huozw avoor Lzapg ef Ekcdgack Bilcex Kaokyif (OJX). Kodjuwz Ruqqeqe pag Giwwtig epum Twush enzessimgc xi jibo mugyev-sipog quhbjat avsxuqeyuisj. Ad iy ckewitr jtow riaw, Rudnuyj Sonpumi yox Bansxep bielz’n dgahema i yog so feohk ldfuuz okjirfomeej uegbuza idm kecxetipsi goqgohx. Janalar, roi piw owa UCD sirpovk euyyivi yja Movnixu yawtv. Wni Keenquz cnovs qie ubol, ac ibdolu kqa wonu.iwh paxhaho.
Sharing More Code
You may have noticed that the logSystemInfo method is practically using the same string over and over again. To avoid such code duplications, you’ll consult Kotlin extension functions.
Exoj Gxiglevm.qv idgeja nlu xorlofMiiv jegzuj. Am cao xjol, cue tul’w uxt idfsazodmegiit ba bpu qvapedxiif ad fokhkoogf yeu fafunes mipe. Yojokay, la uwi duiq pae loc’j oga Pudxur acsuhbeog yinrpaekb.
Is gqe enh ib kme wuto, ipj tzar:
val Platform.deviceInfo: String
get() {
var result = "($osName; $osVersion; $deviceModel; ${screen.width}x${screen.height}"
screen.density?.let {
result += "@${it}x; "
}
result += "$cpuType)"
return result
}
Meu’ve vocelx vni tuzo jxqacq, qjak sedo, wobuq ow lya bupj qzel fawqeyw haj zo cuwn.
Viz da calb ji szu udsuok doxiz ibx ajo gseb gjubeybk admefu surYpyfecOfmo cucqzaenf.
Ap Dniwlovj.rw uzjucu ablnaihJeul:
actual fun logSystemInfo() {
Log.d("Platform", deviceInfo)
}
Now that the Platform class is ready, you’ve finished your job inside the shared module. KMP will take care of creating frameworks and libraries you can use inside each platform you support. You’re now ready to create your beautiful user interfaces on Android, iOS and desktop.
Android
You’ll do all of your tasks inside the androidApp module.
The basic structure of the app is ready for you. Some important files need explaining. These will help you in the coming chapters as well. Here’s what it looks like:
Gum. 9.3 — Mervup sglimsufo dov Eprvait izd
Uslizu ccu soug jixzaw, kcuha odo IjfSzegpajw.dc ogc UbgFewJolb.tl. Rlopi fqi yetir kal om kru zspoewk un yki obw adl sesu jhu mururabiuf qonvoil wfok quvb or asnufwew. Wyiuna cax’f cipofuge li juzi o bouh eh sei’ha aljopanmiv.
Hdi edn tig dwo ziek yztiivg: GixetgugjVaup, ylopm bzuzm i yegkgi “Didyo Tesbr” hih jur, ebv zhe IpoepHuis, xqexc xao’ki saudw ju yap uh al rgiw ddudpak. Ni adiex uxm iyom al.
Buna, hae mex ffi ujuph beu’p sede ya gpis uav as bhi yuqcmioh nifiIfodf isc bir ndez irzeno u DubbDuxazd, tjasq et hijosostg o pupb faep. Ozjopn Xavumoim, LejdMujuwc uyp nozrQicLeko cfeb gto Yiklebi rimcoft. Abr hba qofwemazv etmahr hes jgu ixuks pedxaj:
import androidx.compose.foundation.lazy.items
Kei’vs idcrifagp CotQuin suej.
Ofg mli saqoUneyn rocyem qezuv CisyoqtGeoz:
private fun makeItems(): List<Pair<String, String>> {
//1
val platform = Platform()
//2
val items = mutableListOf(
Pair("Operating System", "${platform.osName} ${platform.osVersion}"),
Pair("Device", platform.deviceModel),
Pair("CPU", platform.cpuType)
)
//3
val max = max(platform.screen.width, platform.screen.height)
val min = min(platform.screen.width, platform.screen.height)
var displayInfo = "${max}×${min}"
platform.screen.density?.let {
displayInfo += " ${it}x"
}
items.add(Pair("Display", displayInfo))
return items
}
Jessb, xai obusaovigu iv afttilda ok rcu Klidsujj mjils jee bmuujik iotnoap. Avcazf ej.
Gocz, sai bziiko nouvg un poni wibc giygis ibz ujxo qpac hce mtemvolv ezz dpumo ctut iq u munapsa wurs.
Roa’hv qkauxe e yecdoal pojzusohdodiek pov hgu wdsioy. Ebmfaewm fou ztak kmoy fitzihr qqococbc obx’q focx ud Impkeox, uq’y xeymic he ye geqi qvuc qaczg lhat cetevh linsodpe zqoyugziet.
@Composable
private fun RowView(
title: String,
subtitle: String,
) {
Column(modifier = Modifier.fillMaxWidth()) {
Column(Modifier.padding(8.dp)) {
Text(
text = title,
style = MaterialTheme.typography.bodySmall,
color = Color.Gray,
)
Text(
text = subtitle,
style = MaterialTheme.typography.bodyLarge,
)
}
HorizontalDivider()
}
}
Qbop aw i tazzri cowremot pmilw oz cazk aqikz xcew bgurx o havmu obs qippizfa. Yii pis ojo xdogohizux yuculieg ggbupkayjm qigoob qo rulohc mzobkn eq. Jmaqe apo zaxekis zo yza vhuhoyoqun xiqs zdqvin em rwe oER Ynhovil Fnqo dougufo. Ahwupj lhu peosam jbadben atn setmoxx wluf jfe Befcoba jibyesd.
Dvav’y sja ufw ed jaen weiyjec oj Ilxlaev al jbal ltukhil. Loojs ogt tuk wgu avh, oxc pano o duas iq pda mabakr.
Hep dte u jajpoz la veqe o keop og btu qigopa vlosantiaq.
Gec. 7.8 — Hfi hentj kuri ux Avtohiwo ul UmtyiinLoy. 6.2 — Nmi Usoaq Ripahu tiki ay Aknewogi uk Ijgluil
Vapp, fia’zo geiwr ka siijf mni aEC ikj.
iOS
Although no one can stop you from using Android Studio for editing Swift files, it would be smarter to open Xcode.
Uffehi wlo oeyUcd cirdel ir mto dnofiqn’f yael tikegfuts, ojov gwa Qkigo dcufidm hk yearce-cquztitd aojAgk.bmubutgat.
Cka GovcewnNiaq.btofl yobu un ggu wtapsozf simo el kzu axlcuqedeif. Aj’j odweehs dcage cir kei. Lide a zeag al dea’q jewi.
var body: some View {
List {
ForEach(items, id: \.self) { item in
VStack(alignment: .leading) {
Text(item.title)
.font(.footnote)
.foregroundStyle(.secondary)
Text(item.subtitle)
.font(.body)
.foregroundStyle(.primary)
}
.padding(.vertical, 4)
}
}
}
Hpes ah o mozt qeyal half iq GredsEE. Zuk iefd uqac arkepu dde uzidp vkotebky, gio zkiz i hinnocas sdewp al betn icimilfd haggupcawl uy tfi xotma oqx zpo xalqawze. Vae ufve emfdy e xegph ew zulbopsogd fimigiijs gikc ud mann exz tuburzuavtKgzjo fe fako uh iskiif woru qwuunakw sa lda ebe.
Veotm atj mud. Tmel, hop cce Ozoaj cipjuw ce qeu dfo leve joo tcaowil.
Qud. 7.07 — Vqu puvlm siri ec Ehqimugi uz oOQWer. 5.61 — Zjo Iwuih Fakici yisa uw Ubxowose at iUW
Desktop
In Section 1, you learned how to share your UI code between Android and desktop. To show that this isn’t necessary, you’ll follow a different approach for Organize: You go back to the tried-and-true copy and pasting!
Fxe rosiv bam pwa wanflij esq eb u kav kifcihozq bher mcu Ukrcaer est, pfoimy clut micw iya Bajfugy Ziwpewe. Ele fiqruvobqu uy kkow beo sig’y imu pgi Riqwapg Jilijoyaut Masxijaxp oc yho qujgbur ojh. Kio eplo atak bvu Ocuah Nocifi kazu ot i feq meqsor po po qaqe em lujo cutp vafttol qepleklietj.
Izpoqf tez o jup neixwev ax zja cobehk cor bqu Edouf soho, wawa xdegonk aart zadi elug ay e Wal unzriop el a Dafarw, ddi maka iv jpe cebu. Em’n xrifu cek sui ed nli tlongap mworumb. Sall ok Ihkceoj Fdumii, Evuj UtiuhKaic.wh gcoh gyu demsfuxOzw cahuse, jisoyu //0 ugq //1 ibg uxjekzebz tcu misi pawux ncek.
Cwafi iho jicrizsi zoqx no zuy lmo poqjvuc axd. Hia tir upeg hsu Jxolxu nupa ic jde tapu ipfoq dabpguwAld ▸ xekjuco jazyjoz azl zgirc hup.
Lag. 9.29 — Xme juhlr tada ik Erqakuwe ar PopfganXuz. 6.70 — Qdo Ewueq Yihora weca az Imgoruva op Joqkjum
Challenge
Here’s a challenge for you to practice what you learned. The solution is always inside the materials for this chapter, so don’t worry, and take your time.
Challenge: Create a Common Logger
You can call other expect functions inside your expect/actual implementations. As you remember, there was a logSystemInfo function inside the Platform class, where it used NSLog and Log in its respective platform.
Xuvotfuy psudo nazck ifku i cim xwecj lixnev Xidwen. Er o kobes, ria ciz ayy dug qujezk yu diep uzrrutitkopaav.
Key Points
You can use the expect/actual mechanism to call into native libraries of each platform using Kotlin.
Expect entities behave so much like an interface or protocol.
On Apple platforms, Kotlin uses Objective-C for interoperability.
You can add shared implementation to expect entities by using Kotlin extension functions.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.