ฉันจะรับการอ้างอิงถึงตัวแทนแอพใน Swift ได้อย่างไร


409

ฉันจะรับการอ้างอิงถึงตัวแทนแอพใน Swift ได้อย่างไร

ในที่สุดฉันต้องการใช้การอ้างอิงเพื่อเข้าถึงบริบทวัตถุที่มีการจัดการ


8
โปรดทราบว่าบางคนอาจพิจารณาการใช้แอพผู้รับมอบสิทธิ์เป็นคอนเทนเนอร์สำหรับบริบทของวัตถุที่มีการจัดการหรือวัตถุ "ทั่วโลก" อื่น ๆ เพื่อเป็นรูปแบบการต่อต้าน ลองพิจารณาให้ตัวแทนแอพส่ง MOC ไปที่คอนโทรลเลอร์แทนที่จะทำให้ผู้ควบคุมพบมัน
คริสโตเฟอร์จอห์นสัน

1
@KristopherJohnson เฮ้คริสฉันจะอำนวยความสะดวกให้ AppDelegate ทำการแทรกการพึ่งพาเข้าไปในตัวควบคุมมุมมองได้อย่างไร ยกตัวอย่างตัวควบคุมมุมมองแบบเป็นโปรแกรมและใช้การไตร่ตรองเพื่อตัดสินใจว่าจะสร้างอินสแตนซ์ / ฉีดซ้ำอีกครั้งหรือไม่? มีกรอบใดบ้างที่สามารถช่วยเหลือสิ่งนี้ได้? ถ้าฉันต้องทำสิ่งนี้กับทุกคอนโทรลเลอร์มุมมองด้วยตนเอง AppDelegate ของฉันจะใหญ่มาก! โอ้โดยเฉพาะอย่างยิ่งโดยไม่ต้องสร้างโรงงานสำหรับทุกสิ่ง :)
โบ้

1
พบการค้นหาคร่าวๆSwinjectซึ่งมีสายอัตโนมัติ :)
โบ้

6
สำหรับโปรแกรมเมอร์ที่ให้คำแนะนำกับการวางอะไร "ภายนอก" ในผู้ร่วมประชุม app ที่มันเป็นเรื่องไร้สาระนิดเพราะเอกสารที่แอปเปิ้ลอย่างชัดเจนระบุว่า"crucial role"ของUIApplicationDelegateเดี่ยวเป็น"...to store your app’s central data objects or any content that does not have an owning view controller." developer.apple.com/documentation/uikit/uiapplicationdelegate
BSOD

คำตอบ:


757

อีกวิธีหนึ่งที่ถูกต้องคือจะให้คุณอ้างอิงถึงตัวแทนของแอปพลิเคชัน แต่จะไม่อนุญาตให้คุณเข้าถึงวิธีการหรือตัวแปรใด ๆ ที่เพิ่มโดยคลาสย่อยของ UIApplication เช่นบริบทวัตถุที่ได้รับการจัดการของคุณ ในการแก้ไขปัญหานี้เพียงแค่เลื่อนลงไปที่ "AppDelegate" หรือเรียกใช้คลาสย่อย UIApplication ของคุณ ในSwift 3, 4 & 5จะกระทำดังนี้:

let appDelegate = UIApplication.shared.delegate as! AppDelegate
let aVariable = appDelegate.someVariable

10
ในกรณีที่ใครยังคงมีปัญหาการกำหนดเป้าหมาย OS X กำหนดให้คุณต้องนำเข้า Cocoa เพื่อใช้กับ NSApplication.sharedApplication () ฉันเดาว่า iOS จะต้องเทียบเท่า
smaurice

2
นี่เป็นประโยชน์ของคำตอบทั้งสองนี้
โจ

3
@zacjordaan ใช้วิธีการนั้นคุณจะได้รับการเติมข้อความอัตโนมัติสำหรับคุณสมบัติ แต่จะไม่ได้ผลจริง วิธีนั้นจะสร้างอินสแตนซ์ใหม่ของคลาส AppDelegate ทุกครั้งที่คุณใช้ คุณควรใช้ผู้รับมอบสิทธิ์สามารถเข้าถึงได้ดีขึ้นผ่าน sharedApplication ซิงเกิล และเท่าที่คำถามที่สองของคุณไปใช่คุณอาจต้องการใช้ค่าคงที่ แม้ว่าคุณอาจจะเปลี่ยนคุณสมบัติของ AppDelegate คุณอาจจะไม่ได้กำหนดตัวชี้ให้กับสิ่งอื่นซึ่งในกรณีนี้ไม่จำเป็นต้องมีตัวแปร นี้ขึ้นอยู่กับคุณว่า ทำสิ่งที่เหมาะสมกับความต้องการของคุณ
Mick MacCallum

2
คำแนะนำที่ยอดเยี่ยม! ฉันคิดผิดว่า AppDelegate () เป็นซิงเกิลตัน แต่หลังจากคิดถึงสิ่งที่คุณพูดฉันก็รู้ว่าถ้าเป็นเช่นนั้นจะไม่มีรูปแบบแอปพลิเคชันที่แชร์ให้เราใช้ด้วยวิธีนี้ แน่นอนว่าฉันไม่ต้องการวางไข่ที่ไม่จำเป็นหากไม่จำเป็นดังนั้นการประกาศคงที่ของคุณจะเหมาะสมอย่างสมบูรณ์ ขอบคุณ.
zacjordaan

4
ฉันไม่ต้องการเพิ่มนี่เป็นคำตอบแยกต่างหาก แต่เพื่อให้ได้รับ AppDelegate ด้วยวิธีการของคุณเองคุณสมบัติในโครงการที่ใช้ทั้ง Swift และ Obj-c คุณควรเพิ่ม #import "AppDelegate.h" เป็น "ProjectName-BridgingHeader .h "
Marcin Mierzejewski

44

สวิฟท์ 4.2

ใน Swift เข้าถึง VC ของคุณได้ง่าย

extension UIViewController {
    var appDelegate: AppDelegate {
    return UIApplication.shared.delegate as! AppDelegate
   }
}

25

ตัวสร้างความสะดวกสบาย

เพิ่มใน AppDelegate Class ที่ส่วนท้ายของรหัส

สวิฟท์ 5

func appDelegate() -> AppDelegate {
    return UIApplication.shared.delegate as! AppDelegate
}

หากต้องการใช้การอ้างอิง AppDelegate ในชั้นเรียนของคุณ


โทรวิธี AppDelegate

AppDelegate (). setRoot ()


จะดีมากที่จะอธิบายว่า setRoot () ทำอะไรและเมื่อใดที่จะเรียกใช้ เช่นมันตกลงที่จะเรียกมันจาก ViewController? จากการทดสอบหน่วยที่ยังไม่ได้ตั้งค่าหน้าต่าง บริบทเพิ่มเติมจะดีมาก
Houman

@Houman setRoot เป็นวิธีการจาก AppDelegate ซึ่งสามารถใช้เพื่อสลับระหว่างหลาย Roots หรือ ParentViewController และอาจเป็นวิธีใดก็ได้ การสนทนาเกี่ยวกับวิธีรับการอ้างอิงของ AppDelegate เพื่อการเข้าถึงเพิ่มเติม แต่หวังว่า setRoot จะต้องชัดเจนเช่นกัน
AiOsN


19

สิ่งนี้สามารถใช้สำหรับ OS X

let appDelegate = NSApplication.sharedApplication().delegate as AppDelegate
var managedObjectContext = appDelegate.managedObjectContext?

3
หรือเพียงแค่let appDelegate = NSApp.delegate as AppDelegate
Vladimir Prudnikov

1
ในการใช้งานSwift 3let appDelegate = NSApplication.shared().delegate as AppDelegate
Dirk

4
ในSwift 4 :NSApp.delegate as? AppDelegate
Nick

12

นี่คือเวอร์ชั่น Swift 2.0:

let delegate = UIApplication.sharedApplication().delegate as? AppDelegate

และเพื่อเข้าถึงบริบทวัตถุที่ได้รับการจัดการ:

    if let delegate = UIApplication.sharedApplication().delegate as? AppDelegate {

        let moc = delegate.managedObjectContext

        // your code here

    }

หรือใช้ยาม:

    guard let delegate = UIApplication.sharedApplication().delegate as? AppDelegate  else {
        return
    }

    let moc = delegate.managedObjectContext

    // your code here

10

SWIFT <3

สร้างวิธีการใน AppDelegate Class เช่น

func sharedInstance() -> AppDelegate{
        return UIApplication.sharedApplication().delegate as! AppDelegate
    }

และเรียกมันว่าจะไปที่ไหน

let appDelegate : AppDelegate = AppDelegate().sharedInstance()

SWIFT> = 3.0

func sharedInstance() -> AppDelegate{
    return UIApplication.shared.delegate as! AppDelegate
}

2
ยังใช้งานได้และฉันชอบความคิดของการตั้งชื่อ sharedInstance ขอบคุณ!
John Griffiths

2
ตัวอย่างของคุณจะยังคงยกตัวอย่างAppDelegateวัตถุใหม่ทุกครั้งที่คุณเรียกว่าAppDelegate().sharedInstance()
pxpgraphics

1
ฉันชอบวิธีนี้ดีกว่าวิธีที่ยอมรับ (ซึ่งก็คือ "ไม่แน่นอน" verbose ถ้าคุณต้องใช้มันทั้งหมด) ฉันคิดเกี่ยวกับการทดลองที่มีextensionสำหรับNSApplicationก่อนที่ฉันจะพบคำตอบนี้ แต่จะดีกว่ามาก ทุกวันนี้คุณอาจต้องการใช้คุณสมบัติการคำนวณแบบอ่านอย่างเดียวของคลาสsharedบางทีคุณอาจต้องการโพสต์การอัปเดตสำหรับ Swift 3
Patru

1
จริง ๆ แล้วฉันกำลังอยู่ในขั้นตอนการปรับรหัสของฉันให้ใช้static var shared : TournamentDelegate? { get { return NSApplication.shared().delegate as? TournamentDelegate } }ซึ่งสอดคล้องกับการพัฒนารูปแบบ Swift 3 โดยใช้การคำนวณแบบอ่านอย่างเดียวคุณสมบัติสำหรับสิ่งต่าง ๆ ประเภทนี้ ฉันอาจจะลดลง?เมื่อเสร็จสิ้นการ refactoring คุณไม่คิดว่า? (ขออภัยการจัดรูปแบบโค้ดในความคิดเห็นมักเป็นเรื่องยุ่งเหยิง)
Patru

@ pxpgraphics UIApplication เป็นคลาสซิงเกิลดังนั้นไม่จำเป็นต้องกังวลเกี่ยวกับการสร้างอินสแตนซ์หลายตัว
Abhijith


6

ลองเพียงแค่นี้:

สวิฟต์ 4

// Call the method
(UIApplication.shared.delegate as? AppDelegate)?.whateverWillOccur()

ที่ไหนใน AppDelegate ของคุณ:

// MARK: - Whatever
func whateverWillOccur() {

    // Your code here.

}

5

นี่คือส่วนขยายสำหรับการUIApplicationDelegateหลีกเลี่ยงการเข้ารหัสAppDelegateชื่อคลาส:

extension UIApplicationDelegate {

    static var shared: Self {    
        return UIApplication.shared.delegate! as! Self
    }
}

// use like this:
let appDelegate = MyAppDelegate.shared // will be of type MyAppDelegate

ใน Mac สำหรับนี้ทำให้ผม:NSApplicationDelegate 'Self' is only available in a protocol or as the result of a method in a class; did you mean 'AppDelegate'?สิ่งนี้ล้าสมัยหรือไม่
pkamb

@pkamb ฉันเพิ่งลองในโครงการใหม่และฉันไม่มีข้อผิดพลาดนี้ ฉันแทนที่UIApplicationDelegateโดยNSApplicationDelegateและโดยUIApplication NSApplication
nyg


4

มันง่ายมาก

อินสแตนซ์ของตัวแทนแอป

let app = UIApplication.shared.delegate as! AppDelegate

คุณสามารถเรียกเมธอดด้วยไวยากรณ์บรรทัดเดียว

app.callingMethod()

คุณสามารถเข้าถึงตัวแปรด้วยรหัสนี้

app.yourVariable = "Assigning a value"

2

ในกรณีของฉันฉันหายไปimport UIKitด้านบนของNSManagedObjectคลาสย่อยของฉัน หลังจากนำเข้าฉันสามารถลบข้อผิดพลาดนั้นได้เช่นเดียวกับที่UIApplicationเป็นส่วนหนึ่งของUIKit

หวังว่ามันจะช่วยให้ผู้อื่น !!!


2

ฉันใช้สิ่งนี้ใน Swift 2.3

1. ในคลาส AppDelegate

static let sharedInstance: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate

2.Call AppDelegate ด้วย

let appDelegate = AppDelegate.sharedInstance


2

ตั้งแต่ iOS 12.2 และ Swift 5.0 AppDelegateไม่ใช่สัญลักษณ์ที่รู้จัก UIApplicationDelegateคือ. คำตอบที่อ้างถึงAppDelegateจึงไม่ถูกต้องอีกต่อไป คำตอบต่อไปนี้ถูกต้องและหลีกเลี่ยงการบังคับเปิด - ปิดซึ่งนักพัฒนาบางคนพิจารณากลิ่นรหัส:

import UIKit

extension UIViewController {
  var appDelegate: UIApplicationDelegate {
    guard let appDelegate = UIApplication.shared.delegate else {
      fatalError("Could not determine appDelegate.")
    }
    return appDelegate
  }
}

1
ใน swift5 รหัสของคุณจะให้คำเตือน "UIApplication.delegate ต้องใช้จากเธรดหลักเท่านั้น" คุณช่วยอัพเดตคำตอบได้ไหม
Mahesh Narla

ว่าfatalErrorเป็นหน้าที่เทียบเท่ากับแกะแรง!
pkamb

1

ใน Swift 3.0 คุณสามารถรับการappdelegateอ้างอิงได้

let appDelegate = UIApplication.shared.delegate as! AppDelegate

0

ใน Xcode 6.2 สิ่งนี้ใช้ได้เช่นกัน

let appDelegate = UIApplication.sharedApplication().delegate! as AppDelegate

let aVariable = appDelegate.someVariable

2
v01d จากที่ที่คุณทำไป?
NSPratik
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.