This profile
- Topic: Apple’s Spring Festival press conference
- Tips: How to display qr code in SwiftUI How do I code a JSON dictionary into JSONEncoder
- Interview module: iOS Memory Management: Autorelease Detail shorthand
- Excellent blog: SwiftUI Advanced Techniques
- Learning materials: KKBOX iOS/Mac OS X basic development materials
- Development tools: several UI debugging tools for iOS development
This topic
@Zhangferry: Apple held its spring press conference on The morning of March 9th, Beijing time. The press conference was also full of sincerity and brought many surprises. The most important is the M1 Ultra chip. M1 Ultra is a combination of two M1 Max chips, but this is not a simple splicing, but thanks to the hidden features of M1 Max: Breakthrough grain-to-grain technology, and then a package architecture called UltraFusion that fuses the two M1 Max together to make it a complete chip for the application layer. It has these things:
-
20-core CPU: 16 high-performance cores + 4 energy-efficient cores for CPU-intensive operations.
-
64 core graphics processor for graphics-intensive tasks.
-
32 neural network cores for machine learning.
-
10 multimedia processing engines to improve video codec capability, H264/HEVC/ProRes/ProRes RAW processing hardware level acceleration.
Of course, such a powerful chip must have a product to use, and it is the Mac Studio. It’s a new product line that looks like a “thicker” Version of the Mac Mini, but thanks to its powerful capabilities, is positioned as a workstation. So far, the M1 has been used in almost all Mac product lines, except for the Mac Pro. The Mac Pro was once a workstation, evolving from “trash can” to “suitcase”. It continues to impress us as the best representative of Apple’s performance, but with the arrival of THE M1, both products are no longer fragrant, not to mention the “suitcase” starting price of 47,999. While the M1 Ultra had us calling Out Apple for its lack of ethics, there was a deliberate mention of the Mac Pro at the end of the event, and there’s a good reason to believe that the next generation of the Mac Pro, the performance ceiling, is the real killer.
The development of Tips
How to display qr code in SwiftUI
Edited by FBY Zhan Fei
Use CoreImage to generate a QR code image.
import SwiftUI
import CoreImage.CIFilterBuiltins
struct QRView: View {
let qrCode: String
@State private var image: UIImage?
var body: some View {
ZStack {
if let image = image {
Image(uiImage: image)
.resizable()
.interpolation(.none)
.frame(width: 210, height: 210)
}
}
.onAppear {
generateImage()
}
}
private func generateImage(a) {
guard image = = nil else { return }
let context = CIContext(a)let filter = CIFilter.qrCodeGenerator()
filter.message = Data(qrCode.utf8)
guard
let outputImage = filter.outputImage,
let cgImage = context.createCGImage(outputImage, from: outputImage.extent)
else { return }
self.image = UIImage(cgImage: cgimg)
}
}
Copy the code
Reference: How to display qr code in SwiftUI – Swift community
How do I code a JSON dictionary into JSONEncoder
Edited by FBY Zhan Fei
JSONEncoder handles type safety, so we need to enumerate jsonValues for all possible type declarations. We also need a custom Initializer to initialize the JSONValue from the JSON dictionary.
import Foundation
enum JSONValue {
case string(String)
case int(Int)
case double(Double)
case bool(Bool)
case object([String: JSONValue])
case array([JSONValue])}extension JSONValue: Encodable {
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .string(let string): try container.encode(string)
case .int(let int): try container.encode(int)
case .double(let double): try container.encode(double)
case .bool(let bool): try container.encode(bool)
case .object(let object): try container.encode(object)
case .array(let array): try container.encode(array)
}
}
}
extension JSONValue {
init?(any: Any) {
if let value = any as? String {
self = .string(value)
} else if let value = any as? Int {
self = .int(value)
} else if let value = any as? Double {
self = .double(value)
} else if let value = any as? Bool {
self = .bool(value)
} else if let json = any as? [String: Any] {
var dict: [String: JSONValue] = [:]
for (key, value) in json {
dict[key] = JSONValue(any: value)
}
self = .object(dict)
} else if let jsonArray = any as? [Any] {
let array = jsonArray.compactMap { JSONValue(any: $0)}self = .array(array)
} else {
return nil}}}var dict: [String: Any] = [
"anArray": [1.2.3]."anObject": [
"key1": "value1"."key2": "value2"]."aString": "hello world"."aDouble": 1.2."aBool": true."anInt": 12
]
let encoder = JSONEncoder(a)let value = JSONValue(any: dict)
let data = try! encoder.encode(value)
print(String(data: data, encoding: .utf8))
Copy the code
How to encode JSON dictionary into JSONEncoder – Swift community
Zhangferry: This solution is for Encodable, which is fully Codable if you add Decodable support. We can name this data type AnyCodable so that we can seamlessly support Codable fields for an indefinite format, such as compound Dictionary.
Reference: making – AnyCodable
Parsing the interview
Hello World
Autorelease details shorthand
This article is based on the source code of autorelease-818. If you are not familiar with the principle of Autorelease, please follow another editor’s article to learn about AutoreleasePool. Some of the source details are described below.
AutoreleasePool data structure
AutoreleasePool’s underlying data structure is based on AutoreleasePoolPage, which is essentially a two-way linked list. Each page is 4K in size and can be checked for PAGE_MIN_SIZE in usr/include/mach/arm/vm_param.h.
#define PAGE_MAX_SHIFT 14
#define PAGE_MAX_SIZE (1 << PAGE_MAX_SHIFT)
#define PAGE_MIN_SHIFT 12
#define PAGE_MIN_SIZE (1 << PAGE_MIN_SHIFT)
class AutoreleasePoolPage : private AutoreleasePoolPageData
{
static size_t const SIZE =
// 'PROTECT_AUTORELEASEPOOL' is defined as 0 by default,
#if PROTECT_AUTORELEASEPOOL
PAGE_MAX_SIZE; // Must be multiple of VM page size (1<<14 = 4096K
#else
PAGE_MIN_SIZE; // Size and alignment, power of 2
#endif
}
Copy the code
Storage optimization on 64-bit systems
In the latest version of 818 code, AutoreleasePoolPage:: Add () in the continuous addition of the same object storage method has been optimized, using LRU algorithm combined with the new AutoreleasePoolEntry object to merge the storage, after simplifying the core source code is as follows:
struct AutoreleasePoolPageData
struct AutoreleasePoolEntry {
uintptr_t ptr: 48; // The object associated with autoRelease
uintptr_t count: 16; // The number of push times associated with the object
static const uintptr_t maxCount = 65535; // 2^ 16-1 Maximum number of times that can be stored
};
/ /... Other variables
}
id *add(id obj)
{
/ /.. The preparatory work
for (uintptr_t offset = 0; offset < 4; offset++) {
AutoreleasePoolEntry *offsetEntry = topEntry - offset;
if (offsetEntry <= (AutoreleasePoolEntry*)begin() || *(id *)offsetEntry == POOL_BOUNDARY) {
break;
}
if (offsetEntry->ptr == (uintptr_t)obj && offsetEntry->count < AutoreleasePoolEntry::maxCount) {
if (offset > 0) {
AutoreleasePoolEntry found = *offsetEntry;
// add offsetEntry + 1
memmove(offsetEntry, offsetEntry + 1, offset * sizeof(*offsetEntry));
*topEntry = found;
}
topEntry->count++;
ret = (id *)topEntry; // need to reset ret
goto done;
}
// The old version inserts the storage mode of the objects in sequence
}
Copy the code
If the LRU algorithm is used, the last four objects will be traversed up from the next pointer during insertion. If they match the current object in the traversal, the count attribute of Entry entity record will be increased by one, and then the memory data will be moved by memmove function. The matching Entry is placed closest to the next pointer to implement LRU characteristics. If the storage is simply merged, only entries adjacent to the next pointer are matched, and those that are not matched are inserted
Whether to enable the coalescing and LRU environment variables are OBJC_DISABLE_AUTORELEASE_COALESCING and OBJC_DISABLE_AUTORELEASE_COALESCING_LRU
In addition, it is best to prepare the cache elimination algorithm together, because if LRU is mentioned in the interview, the interviewer is likely to extend the cache algorithm implementation, such as LFU, LRU.
Threads and Runloops
AutoreleasePool intuitively relates to threads:
-
The data structure stores the thread-related member variable Thread,
-
In the implementation, TLS thread – dependent technology is used to store state data. Such as Hotpage and EMPTY_POOL_PLACEHOLDER status values.
-
Objc initialization calls when AutoreleasePoolPage: : init (), the function through the internal pthread_key_init_np tls_dealloc registered callback functions, destroyed in a thread calls when cleaning Autorelease related content. The process is as follows: _pthread_exit => _pthread_tsd_cleanup_new => _pthread_tsd_cleanup_key => TLs_dealloc. The source code can be found in libpthread.
static void tls_dealloc(void *p) { if (p == (void*)EMPTY_POOL_PLACEHOLDER) { // No objects or pool pages to clean up here. return; } // reinstate TLS value while we work setHotPage((AutoreleasePoolPage *)p); if (AutoreleasePoolPage *page = coldPage()) { if(! page->empty()) objc_autoreleasePoolPop(page->begin()); // pop all of the pools if (slowpath(DebugMissingPools || DebugPoolAllocation)) { // pop() killed the pages already } else { page->kill(a);// free all of the pages}}// clear TLS value so TLS destruction doesn't loop setHotPage(nil); } Copy the code
As you can see from the above flow, there are generally two ways for child threads to process autoreleases: when the thread is destroyed and when the custom pool scope exits
Since Runloop is enabled in the main thread and two callbacks are actively registered, AutoreleasePool is added by default for each Runloop loop. See AutoreleasePool for details and this is not repeated.
TLS based return value optimization scheme and failure scenario in Autorelease ARC environment
Mainly through the embedded objc_autoreleaseReturnValue & objc_retainAutoreleasedReturnValue two functions, based on TLS storage status value to realize the optimization.
The optimization ideas are summarized as follows:
objc_autoreleaseReturnValue
through__builtin_return_address()
The function can find the address of the next instruction after the function returns and determine whether it ismov x29, x29
(ARM64) to determine whether to optimize,- Set if optimization is enabled
tls
storageState value of 1
And return the object directly, otherwise put into automatic release pool go ordinary logic objc_retainAutoreleasedReturnValue
callacceptOptimizedReturn
checktls
If the value is 1, the object is returned directly after optimization is started. Otherwise, the unoptimized logic is used firstretain
Then put into the automatic release pool
The optimization idea is based on TLS and __builtin_return_address() to insert assembly instruction mov x29, x29 as the optimization identifier. While viewing source also need to pay attention to the difference objc_retainAutoreleasedReturnValue and objc_retainAutoreleaseReturnValue
Does the ARC function return value always turn on optimization? There is a case where the optimization logic of the system is broken, such as for or while scenarios. The following is an example:
- (HWModel *)takeModel {
// for (HWModel *model in self.models) {}
HWModel *model = [HWModel new];
return model;
}
Copy the code
If you open the comment code, it will result in the returned Model not being optimized, and you can use dynamic debugging to see why.
So the LR register stores the address of the instruction after the caller calls the takeModel function
With a for loop, the assembly instruction to jump to objc_autoreleaseReturnValue is BL.
Lash means to continue execution of subsequent instructions after executing a function. The purpose of subsequent assembly instructions is mainly to detect if there is a function call stack overflow operation. See Roche iOS Autorelease 2 for details. This causes the __builtin_return_address() function we mentioned above to get the return value of the next instruction address, not the optimization identifier instruction mov x29 x29, but the detection code instruction, causing the optimization not to be enabled.
The impact of not opening optimization is that one retain operation and two autorelease operations will be performed. The author did not test the situation that the autorelease object was not released encountered by the forefather of Goju. It may be that Apple has optimized it later
Summary: AutoreleasePool is an extension of the interview questions I collected. It is important to read AutoreleasePool closely, especially if you need to master the manual processing scenarios in ARC. I hope you can complete the Autorelease interview questions.
- Autorelease behind the black screen
- AutoreleasePool
- Revisit the iOS Autorelease one
- Revisit the iOS Autorelease. 2
- IOS13 a Crash location – freed nsurl.host
Good blog
SwiftUI has been launched for nearly 3 years in the blink of an eye. More and more developers are trying to build their apps using SwiftUI. This blog post will cover more advanced SwiftUI techniques to help developers gain a deeper understanding of SwiftUI.
Finishing editor: Dongpo elbow son
1. Unexplained SwiftUI — the essence of the Programming language SwiftUI — from: WeZZard
@Dongpo Elbow: Author WeZZard looks at and analyzes SwiftUI from a very new perspective. Using an example of Fibonacci numbers to demonstrate the Turing integrity of SwiftUI, it leads to the interesting point that SwiftUI is a programming language, not a UI framework.
SwiftUI base: Mutable view — from: The Moving Parts Team
This article introduces some apis in the View protocol that have not been exposed yet. Using these apis, developers can write containers that are more powerful, flexible, and similar to native implementations to build their own layout logic. The author’s Moving Parts team is currently developing a powerful SwiftUI component library.
3. Learn how and when SwiftUI decides to redraw views — from: Donny Wals
@Dongpo Zuozi: The author tries to understand and summarize the rules of view redrawing in SwiftUI through observation and practice. Although the article does not provide a concrete proof of the internal implementation, there are still valuable lessons to be learned along the author’s testing path.
4. Understand SwiftUI’s onChange — from: Elbow of Dongpo
OnChange is a feature provided after SwiftUI 2.0 and can be used as another means to drive view redrawing. This article will introduce the features, usage, precautions and alternatives of onChange in detail. Learn more about the calculation, layout, and drawing of a view from the previous articles “Understanding how and when SwiftUI decides to redraw a view” and “SwiftUI View Lifecycle Study.”
5. Who says we can’t unit test SwiftUI views? — From Alexey Naumov
Unit testing SwiftUI View is very difficult because it is difficult to build dependencies and runtime environments. Alexey Naumov is the author of ViewInspector, the famous SwiftUI testing framework. This article introduces the story behind his creation of ViewInspector framework, in which the ideas and ways of obtaining secrets in SwiftUI black box are worth learning from.
Javier Javier Javier Javier Javier Javier Javier Javier
With only a small amount of code, SwiftUI can achieve quite good animation effects for developers. But creating cool, flexible, and efficient animations requires a lot more knowledge and advanced skills. This series of articles has been updated for 2 years (SwiftUI was born less than 3 years ago), covering various topics related to advanced animation of SwiftUI.
Learning materials
Mimosa
KKBOX iOS/Mac OS X basic development textbook
Address: zonble. Gitbooks. IO/kkbox – ios – d…
A learning material for newcomers from the iOS/Mac OS development department of KKBOX in Taiwan. This learning material is not an introductory material for going from 0 to 1. Reading this material requires some simple basics. The material is mainly designed to help you explore some common problems and details in code based on the simple OC code you already know. The descriptions in the textbook are very friendly and not stiff, like having a peer next to you to tell you what’s wrong with your code. It’s a great read, and it’s a bit dated, but it’s worth reading for new developers.
Tools recommended
CoderStar
This recommended a series of UI debugging software, including computer side and App side two types;
The computer side
- Reveal: Classic UI debugging software that requires a fee.
- Lookin is a free iOS UI debugging software developed by Tencent.
The App end
- FLEX: FLEX (Flipboard Explorer) is a set of in-app debugging tools for iOS development;
- Screen Bird iOS development tool: A set of in-app debugging tools for iOS development produced by Ali;
Reveal, Lookin and FLEX all have tweaks that you can play if you have a jailbroken device.
About us
IOS Fish weekly, mainly share the experience and lessons encountered in the development process, high-quality blog, high-quality learning materials, practical development tools, etc. The weekly warehouse is here: github.com/zhangferry/… If you have a good content recommendation, you can submit it through the way of issue. You can also apply to be our resident editor to maintain the weekly. Also can pay attention to the public number: iOS growth road, backstage click into the group communication, contact us, get more content.
Phase to recommend
IOS Fishing Weekly 45th issue
IOS Fishing Weekly 44th issue
IOS Fishing Weekly 43
IOS Fishing Week 42nd issue