You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
"copy on write" is an optimization technique that helps in managing memory more efficiently.
It is used primarly with value types such as Array, Dictionary and String to defer the actual copying of data until it is modified. This helps in minimizing unnecessary data copying and thus improve performance.
How "copy on write" works ?
When you assign or pass a value type to another variable or function. Swift doesn't immediately creates the copy of data.
Instead it shares the same underlying storage until the copy is modified.
Note: When you have an array of custom structs, the array itself will benefit from COW.
The memory layout of a type is determined at complie time based on its properties.
Allowing stored properties in extension would complicate this process, as compiler would need to accounts additional properties that might be added in extension and recompile the type.
If extension could add stored properties, the compiler needs to dynamically adjust the memory layout of a type, which could lead to performance overhead.
2. Initilization Complexity
Initialization logic becomes more complex if stored properties are allowed in extensions. The complier needs to ensure that all the stored properties are properly initialized even those are added in extensions.
3. Definition
Extensions are intended to extend existing types with new functionality rather than altering the fundamental structure.
Observation:
Frameworks provided by Apple like Foundation, UIKit, CoreGraphics etc is precomplied. They are dynamically linked at runtime rather than compiled being compiled with our source code.
Memory layout of a type, including its size (calculated from properties) is determined at compile time.
This means the exact memory structure is known and fixed when code is compiled.
For the layout and size the struct and classes includes all the stored properites while classes also include additional meta data for object management. Enums layout depends upon cases and associated values.
An enum type that represents either a wrapped value or absence of value.
It is a genric enum with two cases:
enumOptional<Wrapped>:ExpressibleByNilLiteral{case none
case some(Wrapped)publicinit(_ some:Wrapped){self=.some(some)}
// from ExpressibleByNilLiteral
publicinit(nilLiteral:()){self=.none
}}
ExpressibleByNilLiteral is a protocol, that helps the type to be initialized using nil value.
However, generally instead of using the .none case you would use nil to indicate the absence of a value.
Properties, methods, and subscripts can return an optional and unwrapping of an optional an be done in many ways like:
1. Force unwrap:
Force unwrapping either return the value if it exists or trigger a runtime error when value is nil.
If you are sure value won't be nil in your case, you can use force unwrap to avoid checking for nil's.
Example:
URL(string:) returns Optional
Int(string:) return Optional
2. If let and guard let
Both allow us to unwrap a value safely. In both cases statements will only be execute when optional contains a value instead of nil.
But guard let comes with slight difference. It helps you focus on happy path. guard let requires to exit the current scope optional contains nil value. Exit can be done using return, throw, break or continue keywords.
3. Nil Coelscing operator
It also helps in unwrapping a value and provide a default value when optional contains nil value.
4. Implicitly Unwrapped Optionals
It is not an unwrapping mechanism, but a way to prevent optional checking by alterting type.
It is written as:
letval:String!
May also contains value or be nil. But they don't need to be checked before they are used. If you try to use a value that contains nil your code will crash.
The usual reason is that there are some things we all know will start life as being nil, but will be non-nil by the time we need them and won’t be nil again.
Rethrows in swift allow forwarding a thrown error by a given function parameter. It is used a lot in methods like map, filter, reduce and foreach and helps the compiler to determine whether or not try prefix is needed.
How to use the rethrows keyword
The rethrow keyword used in functions that do not throw errors themselves but instead forward errors from their function parameters.
It also allows the compiler to ask for the try keyword only if given callback actually is throwing errors.
Take the following example of a rethrowing method taking a throwing callback:
extensionArray{func customMap<T>(_ closure:(Element)throws->T)rethrows->[T]{varresult:[T]=[]forelementinself{
result.append(tryclosure(element))}return result
}}
If the callback we pass in doesn’t throw an error, we can call the method as follows: