سويفت 5.2. نظرة عامة على جميع التغييرات

في نهاية مارس ، تم إصدار Swift 5.2 لـ Xcode 11.4. لقد قامت بتحسين تشخيص الأخطاء وتحليل التبعية وتوسيع وظائف SwiftPM. تم بالفعل نشر نظرة عامة على بعض التغييرات على حبري ، في نفس المقالة ، تم النظر في تطور اللغة نفسها مع أمثلة محتملة للاستخدام.


 

SE-0249 KeyPath كدالة


يضع الاختصار keyPath في دالة ، حيث تكون معلمة الإدخال هي الكائن نفسه ، والنتيجة هي خاصيتها.

لنلقي نظرة على مثال. إنشاء مجموعة من النماذج البسيطة:

struct Model {
    let isHidden: Bool
}
 
let modelArray = [Model(isHidden: true), Model(isHidden: false)]

تصفية الصفيف بواسطة الخاصية isHidden. فيما يلي 3 أمثلة لها نفس النتيجة:

// 1
let funcIsHidden: (Model) -> Bool = \.isHidden
modelArray.filter(funcIsHidden)
 
// 2
modelArray.filter(\.isHidden as (Model) -> Bool)
 
// 3
modelArray.filter(\.isHidden)

لا تعمل الوظيفة المعلنة في المثال التالي:

//   
let selfFunc: (Model) -> Model = \.self
modelArray.compactMap(selfFunc)
 
// ERROR: Expression type '(Model) -> Model' is ambiguous without more context
modelArray.compactMap(\.self as (Model) -> Model)
 
// ERROR: Key path value type 'Optional<_>' cannot be converted to contextual type '_'
modelArray.compactMap(\.self)

أيضًا ، على عكس keyPath ، لا يعمل الإكمال التلقائي.

إنه مناسب للاستخدام مع المصفوفات في وظائف مثل التصفية ، والخريطة ، والتصغير ، والفرز ، وما شابه.

قد تحتوي اشتراكات SR-6118 على الإعدادات الافتراضية


يمكن تعيين جميع معلمات الدالة على القيمة الافتراضية. قم بإنشاء بنية Box تحتوي على مصفوفة من العناصر ، ووظيفة ثانوية للوصول إليها.

struct Box {
    let items: [String]
    
    subscript(_ index: Int = 0) -> String {
        items[index]
    }
}

الآن ، للوصول إلى العنصر الأول ، يمكنك حذف الفهرس:

let box = Box(items: ["laptop, , mobile phone"])
let firstItem = box[] // "laptop"

تدعم وظائف SR-2189 المحلية المعلمات الافتراضية من الرؤية الخارجية


في الممارسة اليومية ، نادرًا ما يتم استخدام الوظائف المحلية. قد يكون من الصعب تبرير استخدامها. ومع ذلك ، أعترف أنه في بعض الحالات قد يكون هذا مفيدًا.

على سبيل المثال ، سننشئ دالة سنصف فيها وظيفة محلية:

func getXPosition() {
    func calculateWidth(x: CGFloat = minX) -> CGFloat { ... }
    let minX: CGFloat = 0
    ...
}

كمعلمة افتراضية للدالة calculateWidth ، يمكننا استخدام القيم داخل دالة getXPosition.

SE-0253 استخدام القيم كوظائف


الوظيفة ، على غرارdynamicCallable ، تسمح لك باستخدام قيمة كدالة. ولكنه تنفيذ "نداء ثابت".

عمليًا ، كل شيء بسيط للغاية: لاستدعاء الوظائف ، يمكنك الرجوع إلى القيم كطرق.

إنشاء هيكل لاعب:

struct Player {
    private(set) var isRunning = false
    
    mutating func callAsFunction() {
        isRunning.toggle()
    }
}

قم بإنشاء مثيل لـ Player وقم بالإشارة إليه كوظيفة:

var player = Player()
print(player.isRunning) // false
player()
print(player.isRunning) // true

في الوقت نفسه ، يُمنع إلقاء ، وبالتالي تمرير كائن كدالة:

// ERROR: Cannot convert value of type 'Player' to type '() -> Void' in coercion
let playerAsFunc = player as () -> Void

يمكنك إضافة العديد من الطرق مثل callAsFunction إلى فئة أو بنية أو بروتوكول:

extension Player {
    func callAsFunction(isRunning: Bool = false) throws { ... }
    func callAsFunction() -> Bool { ... }
}

التطبيق ممكن في القيم التي هي وظائف رياضية أو تعبيرات معقدة أو في الحالات التي تكون فيها القيمة دالة مهيمنة واحدة. ومع ذلك ، يجب عدم إساءة استخدام هذه الوظيفة ، فقد تكون مضللة.

SR-4206 خطأ ثابت مع تجاوز الوظيفة بمعلمة عامة


الآن ، بعد تجاوز الوظيفة ، لا يمكنك تغيير أو إضافة قيود على النوع العام. كمثال ، قم بإنشاء فئة CarBuilder والوراثة منها عن طريق تجاوز طريقة الإضافة:

protocol PowerfullEngine { }
 
class CarBuilder {
  func add<T>(engine: T) {}
}
 
class MercedesBuilder: CarBuilder {
    //  
    override func add<T>(engine: T) {}
    // ERROR: Overridden method 'add' has generic signature <T where T : PowerfullEngine> which is incompatible with base method's generic signature <T>; expected generic signature to be <T>
    override func add<T: PowerfullEngine>(engine: T) {}
}

SR-11298 توسيع بروتوكول بدون قيود فئة يرث هذا التقييد


في حالة القيود المفروضة على الذات ، سيطبق التمديد القيد.

على سبيل المثال ، قم بإنشاء القائمة والبروتوكول الملحق مع تقييد الفئة:

protocol Menu {}
 
class SideMenu: Menu {
  var sectionHeight = 0
}
 
extension Menu where Self: SideMenu {
  var menuHeight: Int {
    get { sectionHeight * 20 }
    set { sectionHeight = newValue / 20 }
  }
}

في الوقت نفسه ، فإن أداة الضبط غير متقطعة ، كما لو أن البروتوكول له تقييد فئة.

صب 11429 ريال للوظائف ذات الملصقات


عند إزالة وظائف الصب لكتابة التسميات الآن. بفضل هذا ، يمكنك إلقاء الوظائف باستخدام التسميات. في السابق ، كانت هذه الوظيفة تعمل فقط في الوظائف التي لا تحتوي على تصنيفات:

func setX(x: Int) {}
(setX as (Int) -> Void)(5)

ومع ذلك ، لن يتم حفظ القيم الافتراضية:

func setPoint(x: Int, y: Int = 0) {}
(setPoint as (Int, Int) -> Void)(5, 1)

ينطبق هذا أيضًا على الأدوية العامة ، لذلك لم يعد هذا الرمز صالحًا.

typealias Point<T> = T
func set(x: Int) {}
 
//  
(set as Point)(5) 
 
// ERROR: Extraneous argument label 'x:' in call
(set as Point)(x: 5) 

SR-11841 يتم استدعاء دالة التصفية (_ :) بالترتيب المتوقع في المجموعات البطيئة


قم بإنشاء مجموعة كسولة واستدعي طريقة العد:

let lazyArray = [0]
    .lazy
    .filter { _ in print("A"); return true }
    .filter { _ in print("B"); return true }
 
//  A B
_ = lazyArray.count

كانت نتيجة المكالمة عكس ذلك من قبل: B A.

SR-2790 يقوم عدد من مُهيئي النوع من عائلة UnsafePointer / UnsafeBufferPointer بإصدار تحذير الآن


ينطبق القيد على السلاسل ، والمصفوفات ، ومعاملات Inout غير الموجودة خارج استدعاء الوظيفة.

إنشاء بنية تأخذ UnsafePointer كمعلمة أثناء التهيئة:

struct Game {
    let info: UnsafePointer<Int8>
}
 
func createGame() {
    var i: Int8 = 0
    
    // WARNING: Initialization of 'UnsafePointer<Int8>' results in a dangling pointer
    _ = Game(info: .init(&i))
    
    // WARNING: Passing '[Int8]' to parameter, but argument 'character' should be a pointer that outlives the call to 'init(character:)'
    _ = Game(info: [1, 2])
    
    // WARNING: Passing 'String' to parameter, but argument 'character' should be a pointer that outlives the call to 'init(character:)
    _ = Game(info: "")
}

كانت هناك 9 تغييرات في هذا الإصدار ، ومع ذلك ، فقد قدموا بالتأكيد وظائف جديدة. أفترض أن الأكثر استخدامًا حاليًا هو KeyPath كدالة.

ونتطلع إلى الإصدار التالي. على ما يبدو ، ستدعم Swift على Windows وستظهر ميزات مثيرة للاهتمام ، مثل استخدام الذات في الهروب من عمليات الإغلاق دون الوصول من خلال الذات. * ( SE-0269 ) ووظائف الأدوية العامة ( SE-0267 ) ستتوسع .

مصدر

All Articles