Swift-style-guide: نمط التهيئة الكسول

تم إنشاؤها على ١٥ أبريل ٢٠١٥  ·  29تعليقات  ·  مصدر: raywenderlich/swift-style-guide

يستخدم الكثير منا في البرامج التعليمية هذه الأيام أنماطًا مثل هذه لتهيئة المتغيرات:

lazy var locationManager: CLLocationManager = {
    let manager = CLLocationManager()
    manager.desiredAccuracy = kCLLocationAccuracyBest
    manager.delegate = self
    manager.requestAlwaysAuthorization()
    return manager
  }()

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

اعتقدت أنني سأبدأ مناقشة لمعرفة ما إذا كان هذا هو النمط الذي نريد تشجيعه في دليل الأسلوب؟

التعليق الأكثر فائدة

بصفته لمعلوماتك ، أكد Joe Groff من Swift أن vars الكسولة تكون تلقائيًا @noescape لذلك لن تلتقط نفسها.

https://twitter.com/jckarter/status/704100315587477504

ضع في اعتبارك أنك قد تظل قادرًا على التقاط الذات بطرق أخرى (على سبيل المثال ، حظر المتغيرات التي تلتقط الذات في متغير كسول)

ال 29 كومينتر

راجع للشغل ، هل يتم الاحتفاظ بالنفس دوريًا هنا؟ أعتقد أنه يجب إضافة [unowned self] أو [weak self]

لديك سؤال أيضا:
ما هو الاسم الموصى به لـ strongSelf في هذه الحالة ، لم يتم العثور على هذا في دليلك:

if let strongSelf = self {

}

لا أعتقد أنه من المهم الاحتفاظ بالنفس أم لا ، لأنه يتم تنفيذ الإغلاق عندما يتم استخدام المتغير locationManager ثم يتم إتلافه.

على الرغم من أنني لست متأكدًا تمامًا مما يحدث عندما لا تتصل أبدًا بـ locationManager . في هذه الحالة ، قد يكون الإغلاق بالفعل متمسكًا بذاته. مثير للاهتمام. :-)

تحرير: اختبرت هذا للتو واستخدام الذات في هذا الإغلاق يبدو جيدًا. أفترض أن الإغلاق لم يتم إنشاؤه حقًا حتى تتصل بـ locationManager لأول مرة. وبعد ذلك ينتهي على الفور ويتم تدميره مرة أخرى.

بالمناسبة ، ! غير مطلوب ؛ هذا يعمل بشكل جيد:

lazy var locationManager: CLLocationManager = {

شكرًا ، لقد قمت بتحديث مقطع التعليمات البرمجية الأصلي لإزالة ! . لكن ما زلنا بحاجة إلى مناقشة السؤال الرئيسي - هل يجب أن نشجع هذا النمط في دليل الأسلوب الخاص بنا أم لا؟

احب ذلك. إنها تحافظ على تهيئة الشيء بالقرب من إعلان الشيء. نتيجة لذلك ، يصبح viewDidLoad() أقصر وأسهل في القراءة.

أنا أحب ذلك أيضا. 👍

إذا كانت هناك مشكلات تتعلق بدورة مرجعية قوية ، فيجب أن يصلحها [unowned self] على ما أعتقد:

lazy var locationManager: CLLocationManager = {
  [unowned self] in
  let manager = CLLocationManager()
  manager.delegate = self
  ...
  return manager
}()

يعجبني هذا النهج ، لكنني أجد صعوبة في رؤية الاعتراضات. هل فقط أن هذا النهج غير واضح إلى حد ما ، وأنه يمكن أن يكون له فروق دقيقة (مثل احتمالية دورات الاحتفاظ القوية)؟

(المرجع: https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html#//apple_ref/doc/uid/TP40014097-CH20-ID57)

IMO هذا مجرد نمط. ربما ينتمي إلى الريبو السريع الأنماط. أما بالنسبة لدورات الاحتفاظ ، فأنا أفتقدها. إنها مجرد مهمة مندوب نموذجية. لماذا يجب التعامل مع هذا بشكل مختلف عما إذا كنت قد أجريت للتو عناصر تهيئة CLLocationManager في طريقة التهيئة؟ يشجع نمط المفوض عادةً على تعريف خاصية المفوض (في هذه الحالة ، داخل CLLocationManager) على أنها ضعيفة ، أليس كذلك؟

خطأي هو إعادة دورات الاحتفاظ القوية. إنها ليست مشكلة لأنه تم تنفيذ الإغلاق. إذا كانت تعيد الإغلاق ، فقد يكون من الضروري استخدام [unowned self] ، على الرغم من أنه ليس في هذه الحالة لأنه تم تعيينه كمفوض ضعيف.

من الجدير أيضًا أن نأخذ في الاعتبار أن الإغلاق المحدد لإنشاء var البطيء يجب ألا يعتمد على أي خصائص قابلة للتغيير للفئة. عند النقطة التي يتم فيها إنشاء var البطيء (من خلال تقييم الإغلاق) ، فسوف يلتقط القيم الحالية لهذه التبعيات. سيكون الأمر محيرًا إذا لم يتغير var.

انظر هذا المثال من http://mikebuss.com/2014/06/22/lazy-initialization-swift/

class Person {
    var name: String

    lazy var personalizedGreeting: String = {
        [unowned self] in
        return "Hello, \(self.name)!"
        }()

    init(name: String) {
        self.name = name
    }
}

أعتقد أن هذا محير:

let p = Person(name: "sam")
p.personalizedGreeting
// => "Hello, sam!"

p.name = "definitely somebody else"
p.personalizedGreeting
// => "Hello, sam!"

بعد كل هذا التجوال ، ما زلت أعتقد أنه نمط جيد ومناسب للاستخدام في البرامج التعليمية ، لكن من المهم أن يفهم المؤلفون هذه المشكلات حتى لا يرتكبوا هذه الأخطاء المعقدة نسبيًا.

/ سأصمت الآن

في مستندات Apple التي تربط sammyd ، تقدم Apple هذا كمثال في الواقع:

lazy var asHTML: () -> String = {
    [unowned self] in
    if let text = self.text {
        return "<\(self.name)>\(text)</\(self.name)>"
    } else {
        return "<\(self.name) />"
    }
}

في الرابط الثاني الذي يقدمهsammyd (هو الرابط سعيد اليوم:]) ، يعطي المؤلف هذا كمثال:

lazy var personalizedGreeting: String = {
        [unowned self] in
        return "Hello, \(self.name)!"
        }()

لا أعتقد أن استخدام unowned self سيكون مشكلة في أي وقت في هذه الحالات ... أي في إنشاء خصائص كسولة ... أتخيل في بعض الحالات ، على الرغم من (كما يذكر sammyd مرة أخرى ، إعادة ، وربما أخرى؟) _not_ استخدام unowned قد يكون مشكلة.

للتبسيط ، لماذا لا تستخدم دائمًا unowned للخصائص البطيئة؟

بغض النظر ، أنا جميعًا لاستخدام هذا النمط. : +1:

لاحظ أن المتغير asHTML _stores_ هو الإغلاق للاستخدام لاحقًا. ما نتحدث عنه هنا هو تهيئة متغير عادي باستخدام إغلاق يتم تنفيذه على الفور.

يعجبني ، لكل من الخصائص lazy وغير الممتلكات lazy .

لست متأكدًا من الإرشادات الموجودة في هذا الدليل. _Always_ تفعل ذلك بهذه الطريقة؟ إذا كان لديك بعض الثوابت أو الألوان المحسوبة ، يمكنني أيضًا رؤية فائدة "الطريقة القديمة" في تهيئة أشياء متعددة في viewDidLoad() لإعادة استخدام الكائنات. يبدو الأمر وكأنه شيء بالنسبة لي كل حالة على حدة.

لقد استخدمت استدعاءات initWithFrame لإنشاء مثيل لوجهات نظر واجهة المستخدم لسنوات مع عروض فرعية لعلامات uilabels / textviews / وهو يبسط الكود ويتجنب التعثر في مكالمات دورة حياة العرض - خاصةً عند استدعاء الفئات الفائقة.
هل تعاني من أداء ضئيل؟ يمكن. هل هذا يتعارض مع تدفق uikit واستخدام ملفات nib؟ نعم. هل أقضي ساعات في استكشاف أخطاء ملفات nib؟ لا ، هل يتم شحن تطبيقاتي في الوقت المحدد؟ نعم. هل انا قلق؟ لا. هل فزع المطورون الآخرون؟ من المحتمل. هل يهمني - لا.
رمز بسيط = منطق بسيط - سهل الصيانة.

قد يجادل البعض أنه من أجل الأداء أو الذاكرة حتى يتم تقديم وحدة التحكم في العرض (تم دفعها إلى متحكم التنقل) - ثم لا تقم بإنشاء مثيل لعناصر التحكم (انتظر viewDidLoad / loadView). كان ذلك قبل أن نتمكن من الوصول إلى أدوات التحكم البطيئة على وحدات التحكم في العرض بأنفسهم.
لذا فإن هذا يحل مشكلة إنشاء مثيل وقائي.

على سبيل المثال
lazy var loginVC = {return LoginVC ()} ()

ملاحظة - لقد تجاوزت طريقة init هنا - (لا توجد ملفات xib)

required public init() {
    super.init(nibName: nil, bundle: nil)
}

من Stackoverflow
http://stackoverflow.com/questions/27585409/using-a-programmatically-created-uitableviewcell-subclass-in-swift/31801507#31801507

هذه

فئة EventCell: UITableViewCell {

var eventName: UILabel = UILabel()
var eventCity: UILabel = UILabel()
var eventTime: UILabel = UILabel()

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)

    self.contentView.addSubview(eventName)
    self.contentView.addSubview(eventCity)
    self.contentView.addSubview(eventTime)
}

override func layoutSubviews() {
    super.layoutSubviews()

    eventName = UILabel(frame: CGRectMake(20, 10, self.bounds.size.width - 40, 25))
    eventCity = UILabel(frame: CGRectMake(0, 0, 0, 0))
    eventTime = UILabel(frame: CGRectMake(0, 0, 0, 0))

}

}

ضد

class EventCell: UITableViewCell {
   lazy public  var lblName = {
    return UILabel (frame: CGRectMake(10, 0, self.bounds.size.width , 40))
  }()

  lazy public  var lblCity = {
   return UILabel (frame: CGRectMake(10, 40, self.bounds.size.width , 20))
  }()
 lazy public  var lblTime = {
      return UILabel (frame: CGRectMake(self.bounds.size.width - 80, 10, , 25))
   }()


   override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
   super.init(style: style, reuseIdentifier: reuseIdentifier)

    self.contentView.addSubview(lblName)
    self.contentView.addSubview(lblCity)
    self.contentView.addSubview(lblTime)
 }

}  

تم استخدام حوالي [unowned self] لمنع دورة الاحتفاظ: لم يعد الأمر كذلك.

لم يعد نموذج الكود الذي قدمته Apple والمرتبط أعلاه بواسطة sammyd يستخدم [unowned self] :

lazy var asHTML: Void -> String = {
    if let text = self.text {
        return "<\(self.name)>\(text)</\(self.name)>"
    } else {
        return "<\(self.name) />"
    }
}

وبالفعل لا يمكنني أبدًا تفويت deinit باستخدام var كسول تمت تهيئته بإغلاق يشير إلى self عارية.

الآن لا أعرف ما إذا كان self هو ضمنيًا unowned أو unowned(unsafe) في تلك الإغلاق. ومع ذلك ، يجب أن نتوقف عن توضيحها ، لأنها ضمنية.

مثال asHTML لا يهيئ قيمة بإغلاق ، إنه يخزن إغلاق في متغير. في حالة asHTML ، [الذات غير المملوكة] لا تزال مطلوبة لمنع دورة مرجعية قوية. كل هذا مذكور في وثائق Swift المرتبطة.

إريك تشامبرلين ، كبير المهندسين المعماريين - iOS
ArcTouch - استوديو تطوير التطبيقات

اريك. [email protected] mailto: [email protected]
+ 1-415-944-2000

تطبيقات مخصصة للعلامات التجارية العالمية و Fortune 500
arctouch.com/work | arctouch.com/blog

في 8 كانون الأول (ديسمبر) 2015 ، الساعة 8:18 صباحًا ، كتب جويندال رووي [email protected] :

حول [الذات غير المملوكة] المستخدمة لمنع دورة الاحتفاظ: لم يعد الأمر كذلك.

نموذج الكود https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html#//apple_ref/doc/uid/TP40014097 -CH20-ID57 المقدم من Apple والمرتبط أعلاه بواسطة sammyd https://github.com/sammyd لم يعد يستخدم [نفس غير مملوك]:

lazy var asHTML: Void -> String = {
إذا دع النص = self.text {
إرجاع "<(self.name)> (نص) (self.name)>"
} آخر {
إرجاع "<(self.name) />"
}
}
وبالفعل ، لا يمكنني أبدًا تفويت كلمة deinit باستخدام var كسول تمت تهيئته بإغلاق يشير إلى الذات العارية.

الآن لا أعرف ما إذا كانت الذات غير مملوكة ضمنيًا أو غير مملوكة (غير آمنة) في تلك الإغلاقات. ومع ذلك ، يجب أن نتوقف عن توضيحها ، لأنها ضمنية.

-
قم بالرد على هذه الرسالة الإلكترونية مباشرةً أو اعرضها على GitHub https://github.com/raywenderlich/swift-style-guide/issues/88#issuecomment -162933300.

@ arctouch-ericchamberlain ، أنت على حق ، نموذج التعليمات البرمجية الآن يخزن الإغلاق في الممتلكات.

ومع ذلك ، أكرر نفسي ، "لا يمكن أن يفوتني أي شيء باستخدام فار كسول تمت تهيئته بإغلاق يشير إلى الذات العارية."

على سبيل المثال:

class C {
    lazy var d: String = { "\(self)" }()
    deinit { print("deinit") }
}

C()   // deinit
C().d // deinit

يمكنك أن تجرب ذلك بنفسك. إذا وجدت دورة احتفاظ ، فسيسعدني استخدام [unowned self] مرة أخرى.

ذلك بسبب

var شيء كسول = {..} ()

لا يحتفظ بأي شيء. يتم إنشاء الإغلاق وتنفيذه عند تهيئة المتغير. بينما،

lazy var something = {…}

ينشئ دورة مرجعية قوية عند تهيئة المتغير.

يقع متغير asHTML في نموذج التعليمات البرمجية في الحالة الأخيرة.

قم بإزالة () من أداة التهيئة الخاصة بك ، ثم انظر ماذا يحدث.

إريك تشامبرلين ، كبير المهندسين المعماريين - iOS
ArcTouch - استوديو تطوير التطبيقات

اريك. [email protected] mailto: [email protected]
+ 1-415-944-2000

تطبيقات مخصصة للعلامات التجارية العالمية و Fortune 500
arctouch.com/work | arctouch.com/blog

في 9 كانون الأول (ديسمبر) 2015 ، في الساعة 2:10 مساءً ، كتب جويندال روي إخطارات github.com:

@ arctouch-ericchamberlain https://github.com/arctouch-ericchamberlain ، أنت على حق ، نموذج الكود الآن يخزن الإغلاق في العقار.

ومع ذلك ، أكرر نفسي ، "لا يمكن أن يفوتني أي شيء باستخدام فار كسول تمت تهيئته بإغلاق يشير إلى الذات العارية."

على سبيل المثال:

فئة ج {
lazy var d: String = {"(self)"} ()
deinit {print ("deinit")}
}

ج () // deinit
ج (). د // deinit
يمكنك أن تجرب ذلك بنفسك. إذا وجدت دورة احتفاظ ، فسيسعدني استخدام [الذات غير المملوكة] مرة أخرى.

-
قم بالرد على هذه الرسالة الإلكترونية مباشرةً أو اعرضها على GitHub https://github.com/raywenderlich/swift-style-guide/issues/88#issuecomment -163413290.

أنا لا أتبعك.

لا تتطلب أي من هذه المتغيرات الكسولة [unowned self] :

lazy var d: String = { "\(self)" }()
lazy var asHTML: Void -> String = { "\(self)" }

أي نوع من فار الكسول يفعل؟

عفوًا ، يؤدي استدعاء asHTML بالفعل إلى إنشاء دورة الاحتفاظ.

شكرا @ arctouch-ericchamberlain. لقد كنت مخطئا.

تضمين التغريدة

سبب اكتشافك أن مستندات Apple لا تستخدم [unowned self] هو أنها تقوم بإعداد الموقف الذي توجد فيه مشكلة:

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

ثم يواصلون إصلاح ذلك بإضافة [unowned self] :

المرجع غير المملوك هو طريقة الالتقاط المناسبة لاستخدامها في حل الدورة المرجعية القوية في مثال HTMLElement السابق.

مما ينتج عنه هذا التنفيذ:

lazy var asHTML: Void -> String = {
    [unowned self] in
    if let text = self.text {
        return "<\(self.name)>\(text)</\(self.name)>"
    } else {
        return "<\(self.name) />"
    }
}

تحتوي صفحة التوثيق هذه على وصف جيد عندما تكون دورات الاحتفاظ ممكنة ومتى يجب عليك استخدام unowned أو weak للخروج منها.

تضمين التغريدة

حاول المقارنة مع هذا التنفيذ ، لست متأكدًا مما فاتني ولكن العينات التي رأيتها من Apple ، تميل إلى تجنب أقواس الإغلاق لمجرد ضبط الأشياء.

class EventCell: UITableViewCell {

    lazy public var lblName = UILabel(frame: CGRectZero)
    lazy public var lblCity = UILabel(frame: CGRect())
    lazy public var lblTime = UILabel(frame: CGRect(x: 0, y: 0, width: 0, height: 0))

} 

لا أوافق على فكرة أنه يجب استخدام lazy لسهولة القراءة. الغرض الوحيد هو الأداء حقًا ، لأنه قد يؤدي إلى مشاكل مع الحالة ، على سبيل المثال استخدام الخصائص القابلة للتغيير داخل الإغلاق. لديك بالفعل تهيئة في مكان واحد ، تسمى init المعينة.

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

لذلك هناك احتمالات ، سيحتفظ الإغلاق بنفسه بعد ملكيتك للفصل المذكور ، مما يؤدي إلى حدوث تسرب.
استخدم دائمًا ضعيفًا / غير مملوك حتى لو كنت متأكدًا بنسبة 100٪ من أنه سيتم استدعاء الإغلاق.
في النهاية ، أظن أن المترجم سيتعامل مع ذلك. لا يمكن تنفيذ خاصية كسولة مع إغلاق إلا مرة واحدة ، فكر في dispatch_once(..) . على أي حال ، ربما هذه هي الطريقة التي سأدحرج بها.

أولاً ، دعنا نحصل على الشيء المرجعي للذاكرة من الطريق. (حتى أعلى منشورات المدونة على موقع lazy تفهم هذا الخطأ. نحن بحاجة إلى تغيير Maxime!) للأسباب الموضحة أعلاه ، هذا لا يتسرب. هذا هو: يتم تنفيذ الإغلاق ببطء مرة واحدة. إذا تم تنفيذه ، يتم الاحتفاظ بالنفس ثم تحريرها. إذا لم يتم تنفيذه فلن يتم الاحتفاظ به أبدًا.

يوضح نموذج الكود أدناه هذا بشكل قاطع:

import XCPlayground
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true

class Person {
  init(name: String) {
    self.name = name
    print("\(name) is born.")
  }

  deinit {
    print("\(name) dies.")
  }

  var name: String

  lazy var greeting: String = {
    return "Hello \(self.name)!"
  }()

}

do {
  let t = Person(name: "Ray")
  print(t.greeting)
}

print ("Next")

// Prints: 
// Ray is born.
// Hello Ray!
// Ray dies.
// Next

do {
  let t = Person(name: "Ray")
}

print ("End of the world")

// Prints:
// Ray is born.
// Ray dies.
// End of the world

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

النمط الآخر الذي يبدو أقل بقليل من Javascript-y هو إنشاء عملية خاصة تسمى واستدعاء ذلك:

lazy var locationManager: CLLocationManager = self.makeLocationManager()

private func makeLocationManager() -> CLLocationManager
    let manager = CLLocationManager()
    manager.desiredAccuracy = kCLLocationAccuracyBest
    manager.delegate = self
    manager.requestAlwaysAuthorization()
    return manager
}

بضع ملاحظات:

  • لست متأكدًا من إصدار Swift الذي أصبح هذا ممكنًا.
  • لا تسرب كومة نفس الأسباب أعلاه. لا تصدقني؟ جربها!
  • يحتوي locationManager على نوع التعليق التوضيحي الصريح. هذا مطلوب حاليًا بواسطة المترجم أو تحصل على رسالة خطأ مشفرة حول عدم حل مشكلة self .
  • يعمل للفئات ولكن ليس الهياكل الثابتة.

بالنسبة لمكونات واجهة المستخدم التي لم يتم تخصيصها في لوحة العمل أو بدون شروط في viewDidLoad() ، أعتقد أن الكسل هو نمط جيد. لكنني لا أعتقد أنني مستعد لقول "كل الأشياء كسول" لأنها قد تتطلب بعض الحيل مثل LazyBoxes للتغلب على أخطاء الثبات.

يجب أن أذكر أنه على الرغم من عدم قبوله ، إلا أن هناك تغييرًا كبيرًا ربما يأتي في كيفية العمل الكسول:
https://github.com/apple/swift-evolution/blob/master/proposals/0030-property-behavior-decls.md

ما رأيك بهذا:

كسول
ضع في اعتبارك استخدام التهيئة البطيئة للتحكم الدقيق في الحبوب على عمر الكائن.

// Mark: - Location services
extension MyViewController {
  lazy var locationManager: CLLocationManager = self.makeLocationManager()

  private func makeLocationManager() -> CLLocationManager
    let manager = CLLocationManager()
    manager.desiredAccuracy = kCLLocationAccuracyBest
    manager.delegate = self
    manager.requestAlwaysAuthorization()
    return manager
  }
  // :
}

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

بالمناسبة ، حدد locationManager على أنها خاصية فئة لا تعمل بسبب تعيين manager.delegate = self

ماذا تقترح؟

فقط اجعل فصلك (عرض وحدة التحكم؟) متوافقًا مع CLLocationManagerDelegate.

rayfix لقد قمت بنقل هذا المقتطف إلى فئة فائقة. فاتني تضمين بروتوكول CLLocationManagerDelegate إلى القاعدة.

شكرا 😀

بصفته لمعلوماتك ، أكد Joe Groff من Swift أن vars الكسولة تكون تلقائيًا @noescape لذلك لن تلتقط نفسها.

https://twitter.com/jckarter/status/704100315587477504

ضع في اعتبارك أنك قد تظل قادرًا على التقاط الذات بطرق أخرى (على سبيل المثال ، حظر المتغيرات التي تلتقط الذات في متغير كسول)

أردت فقط إخبارك أنه باستخدام عرض الرسم البياني الجديد للذاكرة في Xcode 8 ، وجدت أنه كان هناك التقاط عندما لم أستخدم البنية الذاتية غير المملوكة في ما يلي:

lazy var locationManager: CLLocationManager = {
    [unowned self] in
    var _locationManager = CLLocationManager()
    _locationManager.delegate = self
    _locationManager.desiredAccuracy = Set.shared.trackingAccuracy
    _locationManager.allowsBackgroundLocationUpdates = true
    _locationManager.activityType = .fitness      
    _locationManager.distanceFilter = Double(Set.shared.waypointInterval)
    return _locationManager
}()

لكنها لم تحدث عندما قمت بتضمينها ولم أجري أي تغييرات أخرى.

rondiel لاحظ أن مندوب CLLocationManager أعلن أنه تعيين (iOS 10 SDK)
@property(assign, nonatomic, nullable) id<CLLocationManagerDelegate> delegate;

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات