Swift Weekly Issue 37

Insert image description here

Insert image description here

Preface

This issue is the thirty-seventh issue of the weekly report compiled by the Swift editorial team , and each module has been initially formed. If readers have any good suggestions, please leave a message at the end of the article.

Swift Weekly is open source on GitHub . You are welcome to submit issues, contribute articles or recommend content. It is currently planned to be released every two weeks on Mondays. Like-minded friends are welcome to join in the weekly report compilation.

Trying to stop is bound to be depressing, but perseverance will eventually lead to a bright future. The Swift community is worth traveling with to achieve excellence together!

Weekly Picks

News and Community: Apple fell nearly 3%, losing $189.8 billion in market value in two days

Proposal: Package iteration proposal is under review

Swift Forum: Proposed User-Defined Tuple Consistency

Recommended blog post: Thread safety in Swift and how to use locks

Topic discussion:

How would you choose between HUAWEI Mate 60 Pro and iPhone 15?

News and Community

Apple fell nearly 3% and its market value evaporated by US$189.8 billion in two days.

It is rare for Apple's stock price to plummet for two consecutive days. As of the close, Apple was trading at $177.56, a decrease of 2.92%, and its latest market value was $2.8 trillion. Apple's cumulative decline for two consecutive days was 6.5%, and its market value evaporated by US$189.8 billion (approximately 1,391.1 billion yuan) in two days.

In terms of news, according to China Fund News, on the one hand, the iPhone 15 series of mobile phones will be announced next week, which will form fierce competition with the currently hot-selling Huawei mobile phones. On the other hand, there are reports that iPhone mobile phones have been banned on certain occasions.

It is also reported that the European Union has released a list of the most stringent digital regulations, and technology giants such as Apple are among them.

According to the Shanghai Securities News, the European Union will announce the first list of services regulated by the Digital Markets Act (DMA) on Wednesday. This list will include some of the “gatekeepers,” the tech giants that have absolute monopolies. Currently, Apple, Microsoft, Amazon, Alphabet, Meta and Samsung are already on the list. These companies will bear the obligations stipulated in the DMA such as not abusing their market dominance to suppress or acquire competitors, or establishing links with competitors.

According to the DMA, "gatekeeper" companies play a key role in the digital market and have huge market influence, so they need to be subject to stricter supervision. The specific conditions are: the company's annual turnover exceeds 7.5 billion euros, the market value exceeds 75 billion euros ($82 billion), and it has a platform with 45 million monthly active users in the EU. However, beyond these raw targets, the EU has some discretion over the regulations.

At the same time, the European Commission also launched four market investigations to further evaluate whether Microsoft Bing, Edge, Microsoft Ads, and Apple iMessage can be exempted.

An Apple spokesperson said the company remains "very concerned about the privacy and data security risks DMA poses to our users." "Our focus will be on mitigating these impacts and continuing to provide the best possible service to our European customers." Good products and services. (Source: Daily Economic News)

iPhone 15 series orders decline, Apple faces dual market impacts

On September 4, according to third-party sources, Apple expects the global smartphone market to be weak in the second half of 2023, so the number of iPhone 15 ordered may decrease.

Previously, Apple announced that its 2023 autumn new product launch will be held at 1 a.m. on September 13, Beijing time. The much-anticipated iPhone 15 series of smartphones will also be officially unveiled at the launch.

As the launch date approaches, the supply chain stock situation of the iPhone 15 series has also attracted industry attention.

Analysts revealed that Apple had placed orders for the iPhone 15 series in the second half of this year to the supply chain in August this year, with the order volume ranging from 80 million to 90 million units.

However, when the iPhone 14 is about to be unveiled in August 2022, Apple’s orders for the iPhone 14 series placed by Apple in the supply chain range from 90 million to 100 million units. Today’s iPhone 15 order volume is 2% higher than last year’s iPhone 14 order volume. A sharp decline!

In August, Apple mainly considered the market conditions in the second half of the year when placing orders. Apple cited the weakening global smartphone market as the reason for the decline in orders.

According to research data released by Canalys, in the first half of 2023, global smartphone shipments reached 528 million units, a year-on-year decrease of 12%. The Chinese smartphone market shipped 132 million units, a year-on-year decrease of 8%.

Neither the Chinese mobile phone market nor the global mobile phone market has recovered from the downturn in the mobile phone industry, and shipments are still falling. (Source: Tencent New Quotes Pro)

Apple's rival is back

At noon on August 29, without any notice or press conference, Huawei officially released a "Letter to Huawei Users". The letter stated that Huawei launched the "HUAWEI Mate 60 Pro Pioneer Plan" at 12:08 that day. Huawei Mate 60 Pro is officially launched on Huawei Mall.

Although there was no warning, Huawei Mate 60 Pro still received widespread attention, and news about Huawei suddenly became a hot search topic on Weibo.

Subsequently, within just a few hours, the first batch of Mate 60 Pro in Huawei Mall was sold out, and countless netizens called Huawei to hurry up and release the next batch!

What’s even more surprising is that the network speed of Huawei Mate 60 Pro has reached the 5G level, and it also has satellite call functions. This indicates that the chip quality in the mobile phone has reached the 5G chip level. Huawei is truly reborn after the disaster and the king is back.

At this time, Apple panicked and announced in a panic that it would release the iPhone 15 series of mobile phones on September 13 as a hedge against Huawei's release of new mobile phones.

Apple and Huawei can be said to be old rivals in the mobile phone industry. In 2019, if nothing unexpected happens, Huawei's mobile phone sales and market share will surpass Apple and become the world's largest mobile phone manufacturer.

However, after that, everyone saw that Huawei's supply chain had a crisis and had to separate the Honor sub-brand. Even when mobile phones fully entered the 5G era, it could only launch 4G mobile phones.

In the first half of this year, Huawei's mobile phone sales have completely fallen out of the top 7 in the industry. The industry once believed that Huawei might withdraw from the mobile phone industry.

However, now Huawei has really overcome the difficulties and returned with the Mate 60, which has directly shocked the global mobile phone market!

On September 4, according to media reports, Huawei has increased orders for its Mate 60 series mobile phones to 15-17 million units.

Industry insiders predict that Mate 60 Pro will become the highest-selling mobile phone in Huawei's Mate series, with final orders of around 17 million units. (Source: Tencent New Quotes Pro)

suggestion

Proposals passed

SE-0405 String Initializers with Encoding Validation proposal passes review. This proposal has been introduced in detail in the proposal module under review in the thirty-fifth weekly report .

Proposals under review

SE-0408 package iteration proposal is under review.

Building on the value and type parameter bag proposal SE-0393, this proposal allows iteration over each element in a value parameter bag and for-inbinding each value to a local variable using the syntax.

rejected proposal

SE-0403 Package Manager Mixed Language Target Support Proposal rejected. This proposal has been introduced in detail in the Proposal Under Review module of the thirty-fourth weekly report .

Swift Forum

  1. Proposed user-defined tuple consistency

introduce

Tuples cannot conform to today's protocols, and this manifests itself in the form of obvious limitations, such as the inability to use tuples of hashable values ​​as dictionary keys.

motivation

The motivation for SE-0283, which previously addressed the desire for tuples to conform to certain standard library protocols, proposed built-in language support for Equatable, Comparable, and Hashable tuples. Independently, Swift concurrency work adds a language extension where tuples of sendable values ​​are themselves sendable. We propose to unify all this special case behavior with user-defined tuple conformance, which can now be expressed using parameter packages (SE-0393). Both SE-0283 and SE-0393 list tuple consistency as a future direction.

Suggested solution

We recommend introducing parameterized extension syntax, as described in the generics declaration. In one specific case, it is allowed to declare tuple consistency in its most general form using this syntax:

extension <each T> (repeat each T): P where repeat each T: P { ... }

We will also allow general type aliases describing tuples to be extended with conditional consistency; we propose that the following tuple type aliases be added to the standard library to facilitate implementation:

protocol Shape {
  func draw()
}

typealias Tuple<each Element> = (repeat each Element)

extension Tuple: Shape where repeat each Element: Shape {
  func draw() {
    repeat (each self).draw()
  }
}

Recall that the requirements in the protocol are fulfilled by witnesses of specific conforming types. Above, we declared a tuple extension, so the witness of draw() implements the protocol requirement draw() on a tuple. The actual implementation calls draw() on each element, which itself conforms to the Shape. Note the use of each self in the repeating pattern of the draw() body.

detailed design

Any untagged tuple can be obtained by type substitution of the "most general" untagged tuple type. The most general type is (repeated for each T) if each T is a bag of parameters of some type; that is, the tuple type formed by the bag extension of each T's elements.

Today, extended extension types must be nominal types, whether they are structures, enumerations, classes, or protocols. We propose to allow extension of the most general tuple types; this is called tuple extension. Because extensions can declare protocol conformance, tuple extensions can implement protocol requirements for the most common tuple types. This is called tuple consistency.

This means that the type of self in the tuple extension is (repeated for each T), where each T is a common argument to the extension that declares consistency. Due to SE-0399, each reference to self in a package expansion expression will be expanded to the elements of the tuple.

As with structure, enumeration, and class extensions, Self in tuple extensions refers to the type of self, that is (repeated for each T).

Once the tuple consistency for a certain protocol P is declared, any tuple type will satisfy the consistency requirements of P as long as the elements of the tuple satisfy the conditions of tuple consistency. As we will see below, conditional requirements must consist of exactly one requirement repeating each T:P. When a protocol requirement is called on a value of tuple type, a packet is formed from the elements of the tuple type; this becomes a common parameter for every T in the calling protocol witness.

Orphan rules

In most cases, tuple conformance behaves as if they were user-defined retroactive conformance on standard library types. In particular, it is invalid for two modules to define two different tuples conforming to the same protocol. Therefore, we prohibit tuples from conforming to protocols outside the defining module.

Single element tuple expansion

Single-element tuple types are expanded after replacement according to the rules specified in the parameter pack proposal. This means that tuple consistency must be consistent with this unrolling.

This imposes some restrictions on the form tuple consistency can take. We can understand all the following restrictions in the form of a commutative graph. The top row shows the most common tuple types, the corresponding tuple conformances, and some witnesses of associated type A. Now, we apply substitution to each object, replacing each T's type parameter bag with a bag containing a single concrete type, say X. We require that all paths in the graph that start and end at the same object produce the same result:

(repeat each T) ---> [(repeat each T): P] ---> (repeat each T).A
      |                        |                        |
      |                        |                        |
      v                        v                        v
      X -------------------> [X: P] -----------------> X.A

Specifically, these restrictions are as follows:

  • Tuple extensions must declare conformance to a protocol.

  • This conformance condition requires that each T must be repeated exactly: P, where each T is an extended type parameter pack and P is the conformance protocol.

  • That is, a tuple extension extending Tuple: P where it repeats every T: Q makes no sense, since in the single-element case it will decay to X: P where X: Q; when P and Q might be This statement is generally false when it is not relevant to the agreement.

  • The associated type of P requires that A must be witnessed by a type alias whose underlying type is exactly (repeat (each T).A); that is, the tuple type of A is projected from each element.

That is, if XA is an Int and YA is a String, then we have no choice but to require that (X, Y).A equals (Int, String).
Note that because of all these rules, an empty tuple() will conform to every protocol with tuple conformance.

dynamic behavior

The above rules allow us to guarantee that the tuple consistency witness will never be called by a single-element package, in which case the call will be forwarded directly to the element consistency. Therefore, the runtime type of Self in tuple conformance must always be the true tuple type, not the unwrapped element.

If a function itself uses a parameter pack to form a tuple value from the pack, the protocol requirement for calling that value will be to invoke a tuple consistency witness or a witness for a single element, depending on the size of the pack.

Tag tuples and variance

Tuple tags are not something that parameter packs can abstract. However, the expression type system defines subtyping relationships between tagged tuples and corresponding untagged tuples.

By analogy with classes, if consistency is declared on a non-final class C, and there is a subclass relationship in which D inherits from C, the consistency is also inherited by D.

In order for replacing C with D to be valid in the case of class inheritance, we require that Self be used only in covariant or contravariant positions, not invariant. Therefore, we must impose the same restrictions on tuples that we currently impose on non-final classes.

This allows the following operations:

  • Complying with protocols such as Equatable, Self appears in the parameter position.
  • Conforms to the hypothetical Clonable protocol, with func clone() -> Selfthe requirement to return Self.

On the other hand, this is prohibited:

  • Conforms to protocols that require the Self position to be unchanged, for example func f() -> G<Self>.

In this case, it's not entirely reasonable to take a tagged tuple and G<>apply it to the corresponding unmarked tuple type.

Scope of use

Due to the subtle static and dynamic behavior outlined above, we expect tuple consistency to remain an advanced feature. For many purposes, it is better to declare a special-purpose variadic generic struct via SE-0398 and make it conform to the protocol, as this provides complete flexibility without any complications in terms of consistency:

struct EggFactory<each Bird> {}

extension EggFactory: OmletMaker where repeat each Bird: Chicken {}

This pattern also allows variadic types to define custom constructors and accessors to enforce invariants, etc.

Tuples should only conform to protocols that have an obvious "algebraic" implementation that generalizes inductively to all combinations of element types, such as the three standard library protocols discussed above.

For example, making tuples conform to IteratorProtocol is probably not a good idea since there are at least two obvious implementations; either compression or concatenation (in which case we also need to require that all sequences have the same element type, which is Tuple consistency cannot even be expressed).

  1. Discuss Is dispatchPrecondition a reasonable way to implement @unchecked Sendable types?

I'm trying to improve my @unchecked Sendableunderstanding of when it makes sense to use .

For example, using dispatchPreconditionguarantee that values ​​can only be read or modified on the main thread:

/// A wrapper that guaruntees that its value is only read or modified on the main thread.
/// For simplicity assume `T` is a value type.
final class MainThreadWrapper<T> {

  init(_ value: T) {
    dispatchPrecondition(condition: .onQueue(.main))
    _value = value
  }

  var value: T {
    get {
      dispatchPrecondition(condition: .onQueue(.main))
      return _value
    }
    set {
      dispatchPrecondition(condition: .onQueue(.main))
      _value = newValue
    }
  }

  private var _value: T

}

For the sake of discussion, let's assume that the wrapped value is a value type (rather than a reference type), so we don't need to account for modifications without a value setter.

@unchecked SendableIs it reasonable to make this type sendable using consistency?

// Is this reasonable, given the expectations of Sendable?
extension MainThreadWrapper: @unchecked Sendable { }

Data races are not possible when using this type. If an incorrect type is used on the wrong thread (for example, in a task other than the main actor), dispatchPreconditionit will fail and block the disallowed use:

struct NotSendable {
  var value: String
}

let wrapper = MainThreadWrapper(NotSendable(value: "foo"))

Task {
  // Allowed by the compiler since wrapper is Sendable, 
  // but a triggers a runtime error:
  print(wrapper.value)

  await MainActor.run {
    // Safe, prints "NotSendable(value: "foo")"
    print(wrapper.value)
  }
}

Given that this type can be safely passed across concurrent domains without data races, I tend to think this is a @unchecked Sendablereasonable use case for .

What do people think? I'm particularly interested in hearing any potential counterarguments.

answer

The wrapper here does keep the underlying data "safe", but it will break if the type is ever used outside of the main queue. This only works for @MainActortypes declared as ... but once you annotate it this way, then you've got the guarantee across concurrency domains that you'll be the primary actor.

Regarding what "safe" means to you, @unchecked Sendableis a promise that your type can be used in any concurrent domain and still protect its own state. I don't think it's correct to label your wrappers like this. It is still only safe to use from the main queue. (If this were not the case, it would crash quickly and efficiently.)

  1. Discussion Swift will not compile a dictionary with ReferenceWritableKeyPath unless it is a class attribute

This code can be compiled by:

@objcMembers final class DriversLicense1: NSObject {
    private let map: [String: ReferenceWritableKeyPath<DriversLicense1, String>] = [
        "DAA": \DriversLicense1.nameFull,
    ]
    private(set) var nameFull: String = ""

    override init() {
        super.init()

        for (key, keyPath) in map {
            self[keyPath: keyPath] = key
        }
    }
}

However, this code doesn't compile - the error is:

cannot convert value of type 'KeyPath<DriversLicense2, String>' to expected dictionary value type 'ReferenceWritableKeyPath<DriversLicense2, String>'
fileprivate let map: [String: ReferenceWritableKeyPath<DriversLicense2, String>] = [
    "DAA": \DriversLicense2.nameFull,
]
@objcMembers final class DriversLicense2: NSObject {
    private(set) var nameFull: String = ""

    override init() {
        super.init()

        for (key, keyPath) in map {
            self[keyPath: keyPath] = key
        }
    }
}

Why?

Answer
This definitely feels like a place where diagnostics might be more helpful - you'll get better news if you try using the setter directly in the same location:

Unable to assign to property: 'nameFull' setter is not accessible

It seems we can look at KeyPath -> (Reference)WritableKeyPaththe circumstances under which the conversion is attempted, and provide special diagnostics if we can form an appropriate writable key path while the setter is visible in the current scope.

  1. Discussion Unable to call swift extension method from Objective C class

I created a swift extension for the ViewController class and defined a method in it. When I try to call the same method from the same Obj-c ViewController, it gives the following error:

ViewControllerNo visible @interfacedeclare selectortestMe

My code is as follows:

Objective-C classes

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@end

@implementation ViewController

- (void)viewDidLoad {

[super viewDidLoad];

[self testMe]; // No visible @interface for 'ViewController' declares the selector 'testMe'

}
@end

Swift extension:
// ViewController+extnesion.swift

import UIKit

@objc public extension ViewController {
    
    func testMe() {
        print("Vish")
    }
}

answer

Your .m files need to import the compatibility headers emitted by the Swift compiler.

  1. Discussion Generic structs using type bags cannot store closures in properties using the same type bag
struct Foo<each T> {
    let foo: (repeat each T) -> Void

    init(
        fn: @escaping (repeat each T) -> Void
    ) {
        self.foo = fn
    }
}

The compiler responds with the following message using Xcode 15.0 beta 8 (15A5229m) and the swift-DEVELOPMENT-SNAPSHOT-2023-09-04-a toolchain

error: type of expression is ambiguous without a type annotation
        self.foo = fn
        ~~~~~~~~~^~~~

Recommended blog posts

SwiftDataKit: Lets you use Core Data’s advanced features in SwiftData

Summary: SwiftDataKit is designed to help developers use Core Data's advanced features in SwiftData. Because SwiftData is the successor of Core Data, it improves and extends Core Data in many aspects. However, the current version of SwiftData cannot fully implement all the advanced features of Core Data, which may be a problem for some developers.

In order to solve this problem, the author created SwiftDataKitthe library to enable developers to use the advanced functions of Core Data in SwiftData by extracting the underlying Core Data objects in SwiftData.

Thread safety and using locks in Swift

Summary: This article discusses thread safety and using locks in Swift. It begins with an introduction to the importance of thread safety and mentions related issues found in the code base. It then demonstrates the concept of state management through a simple example code and illustrates situations where such code can lead to data races and race conditions.

In order to solve this problem, the author introduces the use of lock mechanism to control concurrent access to shared variables. OSAllocatedUnfairLockIn order to achieve thread safety, the blog shows how to use NSRecursiveLocktwo types of locks in Swift . Finally, the blog concludes by summarizing the importance of making classes thread-safe and encouraging investing time early in the development process to build type-safe code.

Analysis of the underlying principles of Swift language-Array series-high-order functions

Abstract: This article introduces the internal source code of functions such as filter, forEach, , , and other functions in Swift arrays, mapand analyzes the implementation logic. The higher-order functions of the Array series are actually higher-order functions of , and are also suitable for other collection types such as Set and so on. The overall design is also quite clever, using many Swift-specific features, which will also inspire us to design Swift code in the future.compactMapflatMapreduceCollectionDictionaryProtocol

topic discussion

Recently, Huawei launched the "HUAWEI Mate 60 Pro Pioneer Plan", which truly represents a rebirth after the disaster and the return of the king. Apple will release the iPhone 15 series of mobile phones on September 13, and the real collision of kings has begun. So if you are considering changing your mobile phone in the near future, how will you choose?

1. Apple fans don’t need to make a choice. Hesitation for even a second is disrespectful to Apple.
2. Decisively choose Huawei. It is extremely cost-effective and an absolutely rational choice.
3. I think millet costing one to two thousand yuan is pretty good. Wouldn’t it be delicious if I bought two more pounds of pork ribs?

Welcome to leave a message at the end of the article to participate in the discussion.

about Us

The Swift community is a public welfare organization jointly maintained by Swift enthusiasts. We mainly operate WeChat public accounts in China. We will share technical content with Swift practice , SwiftUl , and Swift basics as the core, and also compile and collect excellent learning materials.

Special thanks to every editor in the Swift Community Editorial Department for their hard work, providing high-quality content for the Swift community, and contributing to the development of the Swift language.

Guess you like

Origin blog.csdn.net/qq_36478920/article/details/132801284