iOS Developer Mock Interview | Tech Round (Round-2)

iCode
22 Feb 202431:37

Summary

TLDR本期视频是关于iOS开发技术面试的第二轮,主要探讨了iOS应用的不同状态、应用生命周期、状态保存与恢复、委托模式、Combine框架的使用、Swift中的结构体与类、以及并发处理等话题。还讨论了UIKit的事件处理机制、视图生命周期和SwiftUI中状态属性与绑定属性的区别。整个讨论内容丰富,为iOS开发者提供了宝贵的知识和见解。

Takeaways

  • 📱 应用状态:应用有五种状态,包括未运行、不活跃、活跃、后台和挂起状态。
  • 📱 应用生命周期:应用在进入后台一段时间后,可能会被系统终止,此时应用处于挂起状态。
  • 📱 状态保存与恢复:为了在使用应用时保持用户状态,如阅读小说的页数,需要在应用进入后台时保存状态,并在返回前台时恢复。
  • 📱 委托模式:iOS中常用的设计模式,用于在对象间建立通信和数据传递,通过协议定义委托方法。
  • 📱 通知与闭包:除了委托模式,还可以使用通知和闭包作为替代方案,适用于不同的场景和需求。
  • 📱 Combine框架:用于处理异步和事件驱动的代码,提供声明式的Swift API。
  • 📱 发布者与订阅者:在Combine中,发布者负责发送值,订阅者负责接收值,可以处理复杂的数据流。
  • 📱 值类型与引用类型:Swift中的结构体是值类型,传递时会被复制,保证数据不变性;类是引用类型,需要小心管理以避免数据不一致。
  • 📱 线程安全:在多线程环境下,需要确保对共享资源的访问是线程安全的,可以使用串行队列等机制。
  • 📱 UIKit事件处理:UIKit中的事件处理机制包括触摸事件的传递,从硬件触发到视图响应。
  • 📱 SwiftUI:SwiftUI中的State和Binding属性用于不同场景,State用于同一视图内状态的维护,Binding用于父子视图间的数据传递和响应。

Q & A

  • iOS应用程序有哪些状态,以及它们分别在应用程序生命周期的哪个阶段发生?

    -iOS应用程序有五种状态:未运行状态(应用未启动或已被终止)、不活跃状态(应用在前台但不接收事件)、活跃状态(应用在前台并接收事件)、后台状态(应用在后台运行但不在前台,例如播放音乐或下载内容)、挂起状态(应用在后台但不执行代码)。

  • 当用户在使用应用时接到电话,应用会处于什么状态?

    -当用户在使用应用时接到电话,应用会进入不活跃状态,因为虽然应用仍在前台,但暂时不接收事件。

  • 操作系统是否可以自动结束后台应用,如果是,这通常是为了什么?

    -是的,操作系统可以终止后台应用,这通常是为了释放系统资源。

  • 当操作系统决定终止挂起状态的应用时,应用的状态是什么?

    -当操作系统终止挂起状态的应用时,应用处于挂起状态。

  • 在iOS开发中,如何确保应用在后台一段时间后重新进入前台时,用户能够回到之前的位置?

    -在应用进入后台时,应保存相关信息,如用户的当前页面。这可以通过将数据保存到文件、数据库或使用默认设置来实现。同时,监听应用进入后台的通知,执行保存代码。当用户将应用带回前台时,检查并恢复保存的状态数据。

  • Swift中结构体使用堆还是栈分配?

    -Swift中的结构体使用栈分配,这是因为它们是值类型,当赋值给新变量或作为函数参数传递时会被复制。

  • 为什么使用结构体可以提高性能?

    -使用结构体可以提高性能,因为它们是栈分配的,与堆分配的类相比,涉及的开销较小,通常对于小型轻量数据类型更加高效。

  • 为什么在需要维持状态的情况下使用类而不是结构体?

    -在需要维持状态的情况下使用类,因为类是引用类型,可以保持对象的状态在不同地方的一致性。此外,类支持继承,适合需要子类化的场景,如UI组件。

  • 如何处理类导致的数据处理不一致问题?

    -处理类导致的数据处理不一致问题可以通过使用串行队列来确保对类的属性的访问是同步和序列化的,或者使用其他同步机制,如操作队列、闭包等。

  • 在UIKit中,视图的生命周期是怎样的?

    -视图的生命周期包括初始化(使用coder或frame)、布局子视图(layoutSubviews)、添加到窗口(didMoveToWindow)、视图更新(setNeedsLayout和setNeedsDisplay)。

  • UIKit中setNeedsLayout和setNeedsDisplay方法有什么区别?

    -setNeedsLayout方法用于标记视图的布局为无效并需要更新,触发布局更新。setNeedsDisplay方法用于标记视图的内容需要重绘,触发视图的绘制方法。

  • 在SwiftUI中,状态属性和绑定属性有什么区别?

    -状态属性用于在同一视图中维护状态,提供双向数据绑定。绑定属性用于将数据传递给其他视图,并期望从子视图反映回父视图的变化,实现父子关系的双向绑定。

Outlines

00:00

📝 技术面试经验分享

本段落介绍了一个iOS技术面试经验分享系列视频的第二轮,重点讨论iOS开发相关的技术问题。面试者首先被问及iOS应用的不同状态及其在应用生命周期中出现的时间。接着讨论了当电话来电时应用的状态变化,以及操作系统可能在后台自动结束应用的情况。此外,还探讨了如何在应用进入后台时保存状态信息,以确保用户在重新打开应用时能够回到之前的阅读位置。

05:02

🔧 iOS委托模式和替代方案

这一段深入探讨了iOS中的委托模式,包括其工作原理和何时使用。委托模式是一种设计模式,用于在对象之间建立通信和数据传递。讨论了使用协议来实现委托模式,并比较了委托、通知和闭包等替代方案。还讨论了结合框架的使用,以及如何处理异步和事件驱动的代码。最后,面试者分享了他们在使用Combine框架时遇到的一些挑战。

10:03

🏗️ Swift结构体和类的应用

本段落讨论了Swift中结构体和类的不同用途。结构体是值类型,适合用于小型、轻量级的数据类型,因为它们在赋值或作为函数参数传递时会被复制,从而确保数据不变性。类则是引用类型,适合用于需要继承或与Objective-C组件交互的场景。讨论了使用类可能导致的数据不一致性问题,以及如何通过使用串行队列来解决并发读写操作导致的问题。

15:03

🔄 处理并发和数据不一致性

在这一段中,讨论了如何处理类可能导致的数据不一致性问题。提出了使用串行队列来同步对共享资源的访问,确保并发读写操作不会同时发生,从而避免数据不一致性。通过修改代码示例,展示了如何使用串行队列来安全地更新和读取资源。此外,还讨论了其他可能的解决方案,如使用Grand Central Dispatch(GCD)和操作队列。

20:05

📚 Swift UI和事件处理

本段落转向对Swift UI的讨论,特别是状态属性和绑定属性的区别。状态属性用于在同一视图内维护状态,而绑定属性用于在视图之间传递数据,并确保子视图的更改能够反映回父视图。此外,还探讨了UIView的生命周期,包括初始化、布局、绘制和事件处理。最后,讨论了如何通过自定义hit测试来改变触摸事件的处理方式。

25:06

🎥 总结与展望

这是视频脚本的最后一段,总结了整个技术面试经验分享的第二轮,并预告了下一轮将专注于系统设计。鼓励观众订阅频道以获取后续内容,并感谢观众的参与和支持。

Mindmap

Keywords

💡iOS开发

iOS开发是指针对苹果公司的移动操作系统iOS进行应用程序的设计、编码和测试。在视频中,提到iOS开发是为了引出面试者需要掌握的技术知识点,以及面试过程中可能会讨论到的相关概念。

💡应用状态

应用状态指的是一个iOS应用程序在其生命周期中可能处于的不同阶段,例如未运行、后台运行、前台运行等。了解这些状态对于开发者来说至关重要,因为它们影响应用程序如何响应用户交互和系统事件。

💡生命周期

生命周期是指一个对象或组件从创建到销毁的整个过程。在iOS开发中,理解视图或应用程序的生命周期对于管理内存、保存和恢复状态、以及确保应用程序响应用户操作至关重要。

💡委托模式

委托模式是一种设计模式,它允许一个对象将某些任务或职责委托给另一个对象。在iOS中,委托模式常用于建立对象之间的通信和数据传递,如视图控制器和它的委托之间的交互。

💡Combine框架

Combine框架是Swift的一个官方库,它提供了响应式编程的能力,允许开发者以声明式的方式处理异步事件和数据流。这个框架在处理复杂的异步操作和事件驱动的逻辑时非常有用。

💡结构体和类

结构体(Structs)和类(Classes)是Swift中的两种主要数据结构。结构体是值类型,它们在赋值或传递时会被复制,而类是引用类型,它们允许多个引用指向同一个实例。选择合适的数据结构对于确保代码的清晰性、性能和内存管理至关重要。

💡数据一致性

数据一致性是指在多线程环境中,确保数据在多个地方保持同步和准确的状态。在iOS开发中,处理并发访问和修改数据时,保持数据一致性是非常重要的,以避免潜在的错误和程序崩溃。

💡事件处理

事件处理是指应用程序如何响应用户交互或其他系统事件的过程。在UIKit中,事件处理涉及从硬件事件的捕获到视图和视图控制器的交互。

💡SwiftUI

SwiftUI是一个用于构建用户界面的框架,它允许开发者使用声明式Swift代码来构建iOS、macOS、watchOS和tvOS应用程序的界面。SwiftUI简化了界面构建过程,并提供了丰富的控件和动画效果。

💡视图层级

视图层级是指视图之间的层次结构,其中一些视图作为其他视图的父视图存在。在UIKit中,视图层级决定了视图的显示顺序和用户交互的处理方式。

Highlights

介绍了iOS应用的五种状态及其在应用生命周期中的发生时机。

讨论了在电话来电时应用的状态变化,即从活跃状态变为非活跃状态。

操作系统可以在后台终止应用以释放系统资源,此时应用处于挂起状态。

解释了挂起状态的特点,包括应用不在前台执行代码,但状态和数据保存在内存中。

讨论了如何在应用进入后台时保存用户状态,以便在回到前台时恢复到之前的位置。

提到了苹果提供的State preservation和restoration机制,用于保存和恢复应用状态。

讨论了委托模式在iOS中的应用,以及何时使用委托、通知或闭包。

解释了Combine框架的使用,以及如何处理异步和事件驱动的代码。

讨论了结构体在Swift中使用的原因,包括值类型的特性和性能优势。

探讨了类与结构体的区别,包括内存分配、引用计数和线程安全等方面。

讨论了如何处理类可能导致的数据不一致问题,包括使用串行队列进行同步。

解释了视图的生命周期,包括初始化、布局、添加到窗口和更新等阶段。

阐述了视图更新方法`setNeedsLayout`和`setNeedsDisplay`的区别及其用途。

描述了UIKit中事件处理机制的工作流程,特别是触摸事件从硬件到UI控制的传递过程。

讨论了Swift UI中状态属性和绑定属性的区别,以及它们在视图间传递数据时的不同用途。

提出了一个场景,说明了如何通过覆盖`pointInside`方法来改变触摸事件的处理,使其传递给视图层级中更低的视图。

讨论了Swift UI的舒适度,并提到了尝试和学习Swift UI的意愿。

Transcripts

play00:02

hey guys welcome back to iode in our

play00:05

mock interview experience Series this is

play00:07

the second video for the technical round

play00:10

before this we had an exploration round

play00:12

if you haven't watched it I'll mention

play00:14

its Link in the description please have

play00:16

a look now let's jump on to our second

play00:18

round which is going to be a very iOS

play00:20

specific technical round hi P how are

play00:24

you doing hi T I'm good how are you I'm

play00:28

also good Pa thanks for asking

play00:30

so let me give you a very quick walk

play00:32

through of how this round is going to be

play00:34

so in our last discussion we talked

play00:36

about your experience projects you have

play00:38

worked on challenges you have faced

play00:40

right so this one is going to be

play00:42

Technical and we'll talk only about is

play00:44

development sure so in next 30 45

play00:47

minutes we'll try to touch some of the

play00:48

important concepts for iOS development

play00:51

starting from the basics to complex

play00:53

Concepts and we'll cover both UI

play00:55

building and functionality

play00:57

implementation sure I may ask you to to

play01:00

fix some broken piece of code as well so

play01:02

I hope that's fine with you yeah totally

play01:04

all set yeah so let's get started with

play01:07

your interview sure can you explain the

play01:10

is application States and when each

play01:12

state occurs during an app's life

play01:15

cycle sure uh so there are five states

play01:19

of the app the first one that is not

play01:21

running uh this is the state where the

play01:23

app is not launched or has been

play01:25

terminated then comes the inactive that

play01:27

is the app is running in foreground but

play01:29

it is not receiving the events uh the

play01:32

active state where app is running in the

play01:34

foreground and receiving events as well

play01:37

the background state where app is

play01:38

running uh but but it is not in the

play01:40

foreground for example playing music or

play01:42

downloading something and then the

play01:44

suspended state where the app is in the

play01:46

background but not executing the code so

play01:48

these are the five states okay can you

play01:50

tell me the state when phone call comes

play01:53

when user is using any app yeah it would

play01:55

be inactive State because the app was

play01:58

being used by the user so it was in

play02:00

foreground but as soon as the call came

play02:02

it stopped receiving the events uh so it

play02:05

moved to the inactive state is it

play02:07

possible that OS can automatically kill

play02:10

the app when it is in

play02:11

background yeah definitely I mean OS can

play02:14

terminate the app running in background

play02:16

and uh this is generally done to free of

play02:18

the system

play02:20

resources so what is the state of the

play02:22

app and Os

play02:24

terminat uh app is in suspended State uh

play02:28

when it is terminated uh with the

play02:29

intention of freeing of the

play02:32

resources okay can you tell me more

play02:34

about suspended

play02:36

State sure so in the suspended State the

play02:39

app is in the background but it is not

play02:42

actively executing the code I mean uh it

play02:44

it it has been uh Frozen by the system

play02:47

to free up the system resources for the

play02:49

other tasks while in this state the App

play02:51

State and the data are preserved in the

play02:54

memory but the app is not consuming the

play02:56

CPU Cycles or using other system

play02:58

resources so if the system needs more

play03:00

resources or if the app has been in the

play03:02

suspended state for for an extended

play03:04

period uh without being brought to the

play03:07

foreground the OS may decide to

play03:09

terminate the app um when this happens

play03:12

the app is removed from the memory and

play03:13

its state is

play03:15

lost okay got it so assume that you are

play03:19

developing an app where users can read

play03:21

novels MH consider that user was on page

play03:25

167 then he or she got involved in

play03:27

something and app went in background

play03:30

after a couple of hours when user brings

play03:32

the app back to the foreground he or she

play03:34

should land on the same page same novel

play03:37

how can you ensure this sure so uh this

play03:40

is actually related to to the preserving

play03:43

of the state before it gets killed now

play03:46

when app enters the background uh we

play03:48

should save the relevant information

play03:49

including the users's current page in

play03:51

the novel uh using it can be done using

play03:55

the techniques like saving to a file or

play03:57

storing database or defaults for that

play03:59

matter

play04:00

now since there is a possibility that

play04:02

the app might get terminated uh when

play04:05

when it is in the suspended state so we

play04:07

should ensure that the information is

play04:09

saved even when the app is killed so for

play04:12

doing this we can listen to the

play04:13

notifications like application did move

play04:16

to background uh and there we can

play04:18

execute the code and when the user

play04:20

brings the app back to the foreground we

play04:22

can check that if we are having the

play04:24

preserved State data if it exists we can

play04:27

use that to to restore it and uh move

play04:29

move the users to the to the position

play04:31

the 167 page as you mentioned so I mean

play04:34

that is one of the ways through which we

play04:35

can do this yeah this will work I think

play04:38

but are you aware of any other way of

play04:40

achieving this something which Apple

play04:42

provides out of the box yeah I have

play04:45

heard of State preservation and

play04:48

restoration that Apple provides but uh I

play04:50

haven't used it um I mean I read

play04:53

articles about it and I'm aware that

play04:55

there are couple of delegate methods in

play04:57

F delegate I'm not sure about the the

play04:59

name but uh but it involves some

play05:02

protocol I think UI State restoring or

play05:05

something like that through that it can

play05:06

be done yeah you are right about the

play05:08

protocol it's totally fine if you

play05:10

haven't implemented it not every

play05:12

application needs State preservation in

play05:14

fact some of the apps it shouldn't be

play05:16

done like banking apps sure I mean yeah

play05:19

that that makes sense so let's talk

play05:22

about delegations how delegation Works

play05:24

in iOS it's Alternatives and when would

play05:26

you prefer one over the

play05:28

another sure so uh delegation is

play05:32

actually a design pattern which is

play05:33

commonly used in iOS for establishing

play05:37

communication U and the data passing

play05:39

between the objects now in this pattern

play05:41

one object which is the delegate it it

play05:44

trusts on other object which is

play05:46

delegator uh with the certain

play05:48

responsibilities or tasks the delegator

play05:50

calls the methods on delegate to inform

play05:53

about the events and to request the data

play05:55

and for its implementation we use

play05:57

protocols so the delegate adopts the

play06:00

protocol confirming to the required

play06:01

methods uh while the delegator holds a

play06:04

reference to the delegate and for the

play06:06

Alternatives of this delegate approach

play06:08

we can use notifications or closures and

play06:11

even even combined framework for that

play06:13

matter U sorry I missed the last part of

play06:16

your question what was it how do you

play06:18

decide which one should be used yeah

play06:20

right so uh the delegation is used when

play06:23

you need to establish a onetoone

play06:24

relationship between the objects um

play06:26

especially if the delegate needs to have

play06:28

more control over the delegator's

play06:30

behavior uh it's also beneficial when

play06:33

you need to ensure that type safety and

play06:35

the clear documentation between the

play06:38

objects uh while notification is more of

play06:40

a publisher subscriber mechanism where

play06:43

where an object broadcast the

play06:45

notifications to other objects without

play06:47

needing to know that uh who will receive

play06:49

them so it's a good choice for

play06:51

broadcasting events to multiple

play06:54

listeners however uh this can be less

play06:56

type save and harder to debug at times

play06:59

uh the way uh I mean because of its

play07:01

implicit nature for combine it provides

play07:05

uh a declarative Swift API for

play07:07

processing the values over the time it

play07:09

is used for handling asynchronous and

play07:12

and event driven code in a reactive

play07:14

manner I would say so when dealing with

play07:17

complex asynchronous data flows and and

play07:19

event handling the combined framework is

play07:21

a powerful choice I mean this is how we

play07:23

can

play07:25

decide uh how much comfortable are you

play07:27

with combine yeah I have been using

play07:30

combine for almost an year now so yeah

play07:33

quite comfortable so what all publisher

play07:35

have you used in combine and did you

play07:37

find any challenge with any one of them

play07:40

yeah uh I have used quite some

play07:42

Publishers uh to to name some just

play07:46

future uh data task publisher from URL

play07:48

session pass through subject and The

play07:50

Operators like map and filters because

play07:53

even they are Publishers internally uh

play07:55

and in terms of challenges I did face

play07:57

some so once I I tried replacing the

play08:00

dispatch group with the zip publisher

play08:02

and struggled with it later I realized

play08:04

that zip doesn't pass the data to

play08:06

Downstream uh if any of the Publishers

play08:08

fail which is not the case with dispatch

play08:11

group I mean it notify function is

play08:13

always called regardless of a success or

play08:15

failure so that was a challenge yeah

play08:18

that happens with zip anything else that

play08:20

you have faced while learning

play08:22

combine yeah another problem I faced uh

play08:25

it was with pass through subject so I

play08:28

thought that when I'll be having the

play08:29

data I'll pass it as data and when I

play08:31

won't have it I'll send the error so I

play08:34

wanted to do this repeatedly because the

play08:36

flow involved data validation but then I

play08:38

realized that once we pass the error we

play08:40

cannot use the publisher anymore so

play08:43

there I invested some time and initially

play08:45

it felt like a

play08:47

challenge uh you mentioned about pass

play08:49

through subject twice once with

play08:51

Publisher and once as a challenge is

play08:53

pass through subject really a

play08:55

publisher uh pass through subject is not

play08:58

actually a publisher but but it is used

play09:00

to create the custom Publishers so a

play09:03

pass through subject is basically a type

play09:05

that confirms to both subject and the

play09:06

publisher protocols and we can use it to

play09:09

manually send some values to the

play09:11

downstream subscribers and and handle

play09:13

errors on completion events so it allows

play09:16

us to create our own custom Publishers

play09:18

that can emit values errors and and

play09:20

completion

play09:21

events you said that it confirms to both

play09:24

subject and publisher protocols but if

play09:26

we look at the Declaration of pass

play09:27

through subject it says that it only

play09:29

confirms to

play09:31

subject yeah uh that is because the

play09:34

subject inherits from the publisher

play09:36

protocol so does publisher also inherits

play09:39

from some protocol or

play09:41

class uh I don't think so uh I'm not

play09:45

sure but as far as I remember uh it

play09:48

doesn't can you write the publisher

play09:51

protocol

play09:57

sure so it would be

play09:59

something like uh

play10:02

protocol

play10:04

publisher which will take uh uh which

play10:09

will return I think an output and a

play10:12

failure

play10:14

uh

play10:16

then uh it will have a

play10:18

method receive which will take a generic

play10:23

param generate

play10:26

subscriber uh subscribe which can be

play10:31

subscriber which can be of Type S that

play10:34

we have received as a generic

play10:38

parameter yeah uh this this is how it

play10:41

would

play10:43

be uh do you want to go through it again

play10:46

I mean do you think receive method would

play10:48

look like

play10:50

this uh yeah as far as I remember uh it

play10:54

takes only one parameter that is

play10:57

subscriber so yeah so so that means any

play10:59

entity can be a subscriber and that can

play11:02

be passed to receive

play11:03

method yeah uh any entity can be used as

play11:06

a subscriber uh no what I mean is are

play11:09

there any constraints for the entity to

play11:11

be a subscriber or can I directly pass

play11:13

some view models in STS and it will

play11:15

start receiving the

play11:17

events uh yeah oh yeah uh my bad uh it

play11:21

should confirm to uh the subscriber

play11:23

protocol so there should be some

play11:26

constraint for the parameter right yeah

play11:28

uh that we can do by adding a where

play11:31

Clause um let me modify just just a

play11:34

minute

play11:35

sure where s will be

play11:40

subscriber yeah and what about output

play11:43

and failure what are those um those are

play11:46

the associated types for defining that

play11:49

what type of output is expected and what

play11:51

type of failure is expected um my bad I

play11:54

missed on mentioning them as an as

play11:56

Associated types associated uh type this

play12:00

will be of type output and see type this

play12:04

will be a failure which should be an

play12:07

error

play12:08

yeah yeah I think yeah yeah actually

play12:11

there are a couple of more other

play12:12

modifications but yeah more or less this

play12:15

looks good so let's move on and discuss

play12:17

about

play12:18

struck I find strs really interesting

play12:22

why do you think that Swift uses truck

play12:24

for in build types yeah I think that uh

play12:27

one of the main reasons would be the

play12:29

nature of structs that they are value

play12:30

Type U this means that they are copied

play12:33

when when assigned to a new variable or

play12:35

or passed as an function argument now

play12:39

this ensures that the data remains

play12:40

unchanged when shared among different

play12:42

parts of the code and for the

play12:44

fundamental data types like integer

play12:46

double or or Boolean or or any type for

play12:48

that matter this value semantic

play12:50

simplifies the code and reduces the risk

play12:52

of unexpected behavior and on top of

play12:55

that structs also add to the performance

play12:57

so probably that would be the reason and

play12:59

how do they add to the performance so

play13:02

since instructs are stack allocated and

play13:04

involve less overhead compared to the

play13:06

Heap allocated classes U they are often

play13:09

more efficient for small lightweight

play13:11

data types so what is the overhead in

play13:13

Heap allocation or using classes for

play13:16

that

play13:16

matter definitely classes add certain

play13:19

overheads the first and foremost would

play13:21

be the the memory one so the Heap

play13:23

allocated class instances have have an

play13:26

additional memory aage due to the

play13:28

reference counting and and class

play13:30

metadata pointers uh this is not the

play13:32

case with structs uh then there's

play13:34

reference counting because classes rely

play13:37

on reference counting for the memory

play13:38

management so this involves tracking of

play13:41

how many references are pointing to an

play13:43

instance and and that can introduce the

play13:45

runtime

play13:46

overhead uh further classes are mutable

play13:50

by Nature so uh it requires a careful

play13:52

management to ensure the thread safety

play13:55

and that will introduce complexity and

play13:57

potential performance imp impacts U on

play14:00

top of that garbage collection is one of

play14:02

the considerations so U the managing the

play14:04

Heap allocated classes will definitely

play14:06

introduce an overhead of garbage

play14:08

collection Cycles which can potentially

play14:11

impact the realtime

play14:13

performance so if there are so many

play14:15

downsides with classes why do we use

play14:18

them so uh structs are by default the

play14:21

choice and that is what Apple also

play14:22

recommends but it is not like classes

play14:25

shouldn't be used anywhere so wherever

play14:27

we need subclassing or in is involved of

play14:29

course classes are needed uh UI UI view

play14:32

controller is one of the classic

play14:34

examples uh next wherever we need The

play14:37

Objective C interoperability classes are

play14:40

needed because structs cannot interact

play14:41

with the components written in Objective

play14:44

C and one of the Practical use cases

play14:46

that I see is wherever we need to

play14:49

maintain the state uh when we want that

play14:52

action at one point should reflect the

play14:53

changes at other places essentially the

play14:56

reference holding is needed so that is

play14:58

where classes are are required since

play15:00

classes are reference based it gives you

play15:02

the provision of maintaining the states

play15:04

but at the same time they can lead to

play15:06

data inconsistency definitely what do

play15:08

you think no to totally so data

play15:10

inconsistency is indeed one of the

play15:12

challenges with the class-based types

play15:14

and this is because the same instance

play15:16

can be accessed by multiple entities at

play15:19

the same time now as far as multiple

play15:21

reads are happening concurrently

play15:23

probably it is fine but in case if

play15:25

multiple rides are happening

play15:27

concurrently it will lead to the data

play15:29

inconsistency and those are hard to

play15:31

debug and and even crashes at times

play15:33

totally so how can you handle this yeah

play15:36

so uh for handling this we need to make

play15:39

sure that you know multiple readed right

play15:41

operations are are being uh prevented

play15:43

the concurrent ones and one of the easy

play15:45

ways would be to use the actors uh but

play15:49

and that is because actors provide us

play15:51

this entire concurrency handling issues

play15:54

out of the box but in case if we do not

play15:57

have the Liberty to to use the actors

play15:59

because of the the minimum Target

play16:01

supported version or any other

play16:03

limitation then we'll have to uh build

play16:06

the solution of Our Own by using the

play16:07

cues and the logs and those kind of

play16:09

things you mentioned actors um do actors

play16:12

support inheritance um My Bad actors do

play16:16

not support inheritance I just proposed

play16:18

that solution because uh because I

play16:20

thought that we are considering the

play16:22

reference based types which actors are

play16:24

but but if we are considering uh The

play16:26

Inheritance as well then of course

play16:28

classes are the only type and then we'll

play16:29

have to build that solution yeah that's

play16:32

right so PA let me share you one code

play16:34

snippet and uh would you please tell me

play16:37

what is the issue with data

play16:39

inconsistency here sure uh let me have a

play16:43

look last product uh andet date

play16:51

price

play16:53

yeah right um

play16:56

so yeah I think the the issue is with

play17:00

the update price uh method here so um if

play17:05

two callers for that method try to

play17:07

update the price at the same time by

play17:09

calling this method then it will lead to

play17:11

the data inconsistency since it's a

play17:13

class okay and how can we fix this U we

play17:17

can handle this by adding a Serial queue

play17:22

um can you make those changes yeah

play17:25

sure

play17:27

uh

play17:57

for

play18:23

yeah I think uh this this would work uh

play18:26

can you please explain the changes here

play18:28

name sure so uh the the price uh

play18:33

property uh I changed it to private to

play18:35

and and encapsulated and also added a

play18:38

price excess CU which is a Serial

play18:41

dispatch queue because cues are serial

play18:43

by default then I added a get price

play18:46

function to safely retrieve the

play18:48

product's price synchronously U and this

play18:52

this also ensures that only one thread

play18:54

access the price at a time the update

play18:56

price function that that updates the

play18:59

price asynchronously within the price

play19:01

exis Q uh that also makes it thread safe

play19:04

so this ensures that the concurrent

play19:06

rights do not lead to the data

play19:08

inconsistencies okay so what will happen

play19:12

if um first two threads try to update

play19:15

the price at the same time and second

play19:17

two threads try to read the price at the

play19:19

same time right so uh first considering

play19:23

the scenario where two threads are

play19:24

trying to update the price at the same

play19:26

time so in this the uh when two threads

play19:28

attempt to update the price of the

play19:30

product simultaneously uh the the serial

play19:33

dispatch queue will ensure that only one

play19:35

of the thread is allowed to modify the

play19:38

price property at that time U the first

play19:40

thread accesses the update price and it

play19:43

will acquire a lock on the price exis

play19:45

que it updates the price and then

play19:47

releases the lock the second thread

play19:50

attempting to the exess uh to access at

play19:52

the same time simultaneously it will be

play19:54

blocked until the lock is released by

play19:55

the first thread so as a result the

play19:58

concurrent updates will be serialized

play20:00

and only one of the threads price

play20:02

updates will be applied so this prevents

play20:04

the data inconsistencies and it it

play20:07

ensures that the price is updated by one

play20:09

thread at a time now when two threads

play20:11

try to read the price at the same time

play20:13

so uh the the get price method the the

play20:17

basically the price access Q is also

play20:19

used to synchronize the access uh to the

play20:21

price property uh the same way with the

play20:24

right uh the first thread will call the

play20:27

get price and will acquire the lock on

play20:28

the price XIs Q it will read the price

play20:31

and then release the lock the second

play20:33

thread will be blocked until the lock is

play20:35

not released by the first one reading

play20:36

the price this serialization again

play20:39

ensures that the concurrent reads are

play20:41

not happening at the same time for the

play20:43

inconsistencies and both the threads

play20:45

receive the the correct value they won't

play20:48

interfere with each other so in both the

play20:50

cases this this dispatch que it

play20:53

guarantees that access to the price

play20:55

property is synchronized and serialized

play20:57

uh which is preventing the data

play20:58

inconsistency

play21:01

here okay so you said that second thread

play21:05

will be blocked until the lock is

play21:06

released by the first thread right what

play21:09

does it mean it will keep waiting or

play21:11

will it be returned without any value or

play21:14

previous value exactly what will

play21:17

happen right so uh I meant that the

play21:19

second thread will be temporarily halted

play21:22

and prevent it from executing further

play21:25

until it it can acquire the lock so when

play21:28

the first thread enters a synchronized

play21:30

block it it acquires the lock on the

play21:32

serial dispatch queue uh which is our

play21:34

price exess Q in this case and it

play21:36

executes the code inside that block in

play21:39

the case of a read operation the first

play21:41

thread reads the price and then releases

play21:43

the loog while the first thread is is in

play21:46

the synchronized block the second thread

play21:47

also attempts to enter the same

play21:49

synchronized block uh and in in the case

play21:52

of concurrent exis to the get price

play21:54

method I'm referring to so however the

play21:56

second thread cannot immediately

play21:58

mediately enter the synchronized block

play21:59

because the lock is already held by the

play22:01

first thread U instead the second thread

play22:04

is blocked or put into a waiting State a

play22:06

temporary halted state it will not

play22:09

proceed further until the lock is

play22:10

released by the first thread so the

play22:13

second thread does not return a value or

play22:15

a previous value it waits for the lock

play22:18

to be released and once the lock is

play22:20

available it proceeds to read the

play22:22

current value of the period of the of

play22:24

the price and uh then it uh returns okay

play22:27

and why are we reading the value in a

play22:29

sync block but writing in async right so

play22:32

the decision to read the value within a

play22:34

sync block while writing it at an uh in

play22:37

an a sync block is based on a tradeoff

play22:39

between different requirements so uh

play22:42

reading the value within a sync block

play22:44

ensures that the value is read

play22:46

atomically uh meaning that that no other

play22:48

thread can exess or modify it

play22:50

concurrently while the read operation is

play22:52

in progress this way we also get a

play22:55

guarantee that the value returned by the

play22:56

get price method is is the most upd up

play22:59

toate value at the moment of the read uh

play23:01

which is essential when we want to

play23:03

ensure the data consistency in a

play23:04

multi-threaded

play23:06

envirment uh now writing the value

play23:08

within an async block means that the

play23:10

right operation is performed in in the

play23:12

background uh possibly on a different

play23:14

thread so this allows the calling thread

play23:17

uh to to continue its execution without

play23:21

waiting for the right to complete so

play23:23

using an asynchronous operation for

play23:25

right can I mean it can help in

play23:28

improving the responsiveness of the

play23:30

calling thread and prevent it from

play23:32

becoming blocked while the right

play23:33

operation uh may take some time U let's

play23:37

say if it depends on a network request

play23:39

or something something similar to that

play23:41

so the combination of synchronous read

play23:43

and asynchronous rights ensures that the

play23:45

concurrent reads do not interfere with

play23:47

the rights and vice versa okay yeah got

play23:50

it so what are the other ways through

play23:53

which you could have handled this uh we

play23:56

could have used dispat sopers or or or

play23:58

operation cues for handling this uh and

play24:01

even synchronized blocks would have

play24:02

worked but since they internally used

play24:04

Objective C which adds to the

play24:06

performance overhead so that's not the

play24:08

good choice but yeah we can use dispim

play24:11

firstand locks uh can you show how will

play24:13

you do it with this P Sima first

play24:26

sure

play24:39

yeah uh this this should

play24:42

work okay so you have used deer hair can

play24:46

you tell how it internally

play24:49

Works um I'm not sure uh but but from

play24:52

what I have seen maybe it internally

play24:55

maintains a stack uh this is because

play24:57

when when we write multiple defer blocks

play24:59

the last one is executed the first um in

play25:01

the Leo manner so when the control is

play25:04

about to move out of the current scope

play25:06

the execution uh blocks that are added

play25:08

to that stack would be probably popped

play25:11

uh so I think that it's stack but I'm

play25:13

not sure yeah I think that would be the

play25:15

idea um cool let's move on and discuss

play25:18

about the UI sure uh can you tell me the

play25:21

live cycle of a

play25:23

view sure um so first the view is

play25:26

initialized uh with in it with coder or

play25:29

in it with frame whatever is applicable

play25:31

that gets called then for laying out the

play25:33

subviews and applying the constraints

play25:36

the layout subview method is called uh

play25:38

then the system calls draw or draw re if

play25:42

if it if we have over uh overridden it

play25:44

then will move to Window or did move to

play25:47

Window uh when the view is added to the

play25:49

super View and then the view update

play25:51

methods like set needs layout set needs

play25:54

display those are called uh that's the

play25:57

cycle yeah and when is aw from Li called

play26:00

U it is called right after the

play26:02

initiation my bad I missed it because I

play26:05

was only considering the programmatic

play26:06

view creation flow u in that one the

play26:09

aake from n is not called but I mean it

play26:11

is only called when we initialize the

play26:13

the view from nib or the story board

play26:15

yeah so you mentioned about two methods

play26:18

set needs layout and set needs display

play26:20

what is the difference between two so uh

play26:23

both of these methods serve for

play26:25

different purpose uh set need layout it

play26:28

indicates that the View's layout is is

play26:31

invalid and needs to be updated so this

play26:34

method marks the view as as basically a

play26:36

dirty View and it triggers the layout

play26:37

updates on The View which means that the

play26:40

views layout sub views method will be

play26:41

called uh in the next run Loop cycle U

play26:45

we typically use set needs layout when

play26:46

we uh when we need to adjust the

play26:49

position or the size of the subv update

play26:51

constraints or perform any layout

play26:53

related changes uh while the set needs

play26:56

display method meod it is called when

play26:59

the content needs to be redrawn or the

play27:01

or it needs to be updated so this method

play27:03

marks the view as needing display and

play27:06

and it triggers the views draw method or

play27:08

Draw R if it has been overridden U to be

play27:10

called on the next run Loop cycle and uh

play27:13

this is typically used when we want to

play27:15

update the visual content of the view

play27:17

such as drawing of Graphics or or images

play27:20

within the view like that okay uh can

play27:23

you explain the event handling mechanism

play27:25

in UI kit uh event handling mechanism as

play27:29

in sorry I didn't get you yeah uh

play27:32

particularly the flow of a touch event

play27:34

from Hardware to the point where it

play27:36

triggers an action in a UI control got

play27:38

it got it sure so uh the process starts

play27:41

with a hardware event triggered by a

play27:43

users interaction such as say tapping

play27:46

the screen this Hardware event is then

play27:48

delivered to the topmost view in the

play27:50

hierarchy uh which is typically a UI

play27:53

window then the UI window performs the

play27:55

hit testing for identifying the view

play27:58

which intersects with the touch Point um

play28:01

and then after this UI kit establishes a

play28:03

UI responder chain and the view that

play28:05

that responded to the hit test becomes

play28:07

the initial first

play28:09

responder uh within the responder chain

play28:11

the initial first responder is is

play28:13

expected to handle the event U and in

play28:16

case if it doesn't it is passed on to

play28:18

the to the next responder in the Chain

play28:20

by calling the method next responder U

play28:23

and this is where the gesture recognizer

play28:25

also comes into the play since they are

play28:27

capable of recognizing the the gestures

play28:29

like tap swipe pinches and analyzing the

play28:32

sequence of the events so on recognizing

play28:35

a gesture uh they they trigger an

play28:37

Associated action uh essentially a

play28:39

selector and this is where we implement

play28:42

the custom logic and in response to the

play28:44

gesture recognizer basically the code

play28:46

that that we write uh okay so let me

play28:49

give you one scenario like you have two

play28:51

view on top of each other and you want

play28:54

the touch to be handled by The View

play28:55

lower in the hierarchy m essentially you

play28:58

want to pass the touch to a view which

play29:00

is below the view receiving the touch

play29:03

how can you do this got it so uh I mean

play29:06

for this uh we'll have to intervene in

play29:09

the process of the hit testing U as I

play29:11

mentioned earlier that hit testing

play29:13

decides that which view should respond

play29:16

so for achieving this we can override

play29:18

the method responsible for the hit

play29:19

testing U I think it's it's Point

play29:22

coincides with or or Point insides with

play29:25

something like this and and from there

play29:28

if we return false the touch would be

play29:30

passed on to the view Below in the

play29:32

hierarchy so that way we can achieve it

play29:34

yeah this would do so let's just have

play29:37

last question from Swift UI are you

play29:39

comfortable with swift UI uh yeah I mean

play29:42

although I haven't worked that much with

play29:44

the Swift UI but I would like to attempt

play29:47

okay so can you tell me the difference

play29:49

between state property and binding

play29:51

properties sure uh both state and

play29:54

binding property are I mean both are the

play29:56

property reper in Swift UI and state is

play29:59

used for maintaining the state uh within

play30:02

the same view so maybe I can explain you

play30:04

with an example say U you have a toggle

play30:08

uh now for maintaining the state of this

play30:09

toggle you would use a state property

play30:12

which will give uh you a kind of two-way

play30:14

data binding but in contrast to this The

play30:17

Binding property rapper is used when you

play30:19

need to pass some data to other view but

play30:23

we expect that the changes from that

play30:24

view should should be reflected back to

play30:26

the view who passed it a kind of parent

play30:29

child relation sort of thing so in such

play30:31

scenarios you pass a binding variable to

play30:34

the child and the changes then are

play30:36

reflected back to the parent okay so it

play30:38

means I cannot pass the State Properties

play30:40

to child views uh no no you can pass a

play30:43

state property but uh but but then you

play30:45

won't get the two-way binding because

play30:47

when State properties are passed they

play30:49

are passed as as a copy and the changes

play30:52

made by the child won't be passed back

play30:54

to the parent yeah that's correct so PA

play30:57

I think we have discussed quite a bit

play31:00

that's it from my side it was really

play31:02

good discussion uh definitely da I mean

play31:04

indeed it was a great discussion U thank

play31:07

you thanks for your time

play31:09

yeah so that was about the second round

play31:12

in our interview experience series the

play31:14

next round we'll be focusing on the

play31:15

system design and if you think that this

play31:17

went well hopefully that will get

play31:19

scheduled very soon please stay tuned

play31:21

for it and if you like our videos if you

play31:24

like the content that we create you can

play31:26

consider subscribing to Channel see you

play31:29

in the next round till then Happy

play31:35

Gooding

Rate This

5.0 / 5 (0 votes)

Related Tags
iOS开发技术面试应用状态视图生命周期SwiftUI数据一致性多线程事件处理委托模式Combine框架
Do you need a summary in English?