เราจะสร้างตัวแทนได้อย่างไรเช่นNSUserNotificationCenterDelegate
รวดเร็ว?
เราจะสร้างตัวแทนได้อย่างไรเช่นNSUserNotificationCenterDelegate
รวดเร็ว?
คำตอบ:
ไม่ต่างจาก obj-c ขั้นแรกคุณต้องระบุโปรโตคอลในการประกาศคลาสของคุณดังต่อไปนี้:
class MyClass: NSUserNotificationCenterDelegate
การใช้งานจะมีลักษณะดังนี้:
// NSUserNotificationCenterDelegate implementation
func userNotificationCenter(center: NSUserNotificationCenter, didDeliverNotification notification: NSUserNotification) {
//implementation
}
func userNotificationCenter(center: NSUserNotificationCenter, didActivateNotification notification: NSUserNotification) {
//implementation
}
func userNotificationCenter(center: NSUserNotificationCenter, shouldPresentNotification notification: NSUserNotification) -> Bool {
//implementation
return true
}
แน่นอนคุณต้องตั้งผู้รับมอบสิทธิ์ ตัวอย่างเช่น:
NSUserNotificationCenter.defaultUserNotificationCenter().delegate = self;
@interface MyCustomClass: UIViewController <ClassIWantToUseDelegate>
ทำให้คุณสามารถเริ่ม / กำหนดค่าตัวควบคุมมุมมองรวมถึงเรียกวิธีการมอบหมายในมุมมองย่อยได้ อะไรทำนองนี้ ?
ต่อไปนี้เป็นความช่วยเหลือเล็กน้อยสำหรับผู้ร่วมประชุมระหว่างตัวควบคุมมุมมองสองตัว:
ขั้นตอนที่ 1:สร้างโปรโตคอลใน UIViewController ที่คุณจะลบ / จะส่งข้อมูล
protocol FooTwoViewControllerDelegate:class {
func myVCDidFinish(_ controller: FooTwoViewController, text: String)
}
ขั้นที่ 2: ประกาศผู้รับมอบสิทธิ์ในคลาสการส่ง (เช่น UIViewcontroller)
class FooTwoViewController: UIViewController {
weak var delegate: FooTwoViewControllerDelegate?
[snip...]
}
ขั้นตอนที่ 3: ใช้ผู้รับมอบสิทธิ์ในวิธีการคลาสเพื่อส่งข้อมูลไปยังวิธีการรับซึ่งเป็นวิธีการใด ๆ ที่ใช้โปรโตคอล
@IBAction func saveColor(_ sender: UIBarButtonItem) {
delegate?.myVCDidFinish(self, text: colorLabel.text) //assuming the delegate is assigned otherwise error
}
ขั้นตอนที่ 4:ใช้โปรโตคอลในคลาสรับ
class ViewController: UIViewController, FooTwoViewControllerDelegate {
ขั้นตอนที่ 5:ใช้วิธีการมอบสิทธิ์
func myVCDidFinish(_ controller: FooTwoViewController, text: String) {
colorLabel.text = "The Color is " + text
controller.navigationController.popViewController(animated: true)
}
ขั้นตอนที่ 6:ตั้งค่าผู้รับมอบสิทธิ์ในการจัดเตรียมสำหรับเซก:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "mySegue" {
let vc = segue.destination as! FooTwoViewController
vc.colorString = colorLabel.text
vc.delegate = self
}
}
และนั่นควรได้ผล แน่นอนว่านี่เป็นเพียงส่วนของโค้ด แต่ควรให้แนวคิดแก่คุณ สำหรับคำอธิบายยาว ๆ เกี่ยวกับรหัสนี้คุณสามารถไปที่รายการบล็อกของฉันได้ที่นี่:
หากคุณสนใจในสิ่งที่เกิดขึ้นภายใต้ประทุนกับตัวแทนฉันเขียนไว้ที่นี่:
weak
จำเป็นสำหรับคลาสเท่านั้นที่ไม่ใช่โครงสร้างและ enums หากผู้รับมอบสิทธิ์จะเป็นโครงสร้างหรือ enum คุณไม่จำเป็นต้องกังวลเกี่ยวกับการรักษารอบ อย่างไรก็ตามผู้รับมอบสิทธิ์เป็นคลาส (ซึ่งเป็นเรื่องจริงสำหรับหลาย ๆ กรณีเนื่องจากมักจะเป็น ViewController) คุณต้องweak
แต่คุณต้องประกาศโปรโตคอลของคุณเป็นคลาส มีข้อมูลเพิ่มเติมที่นี่stackoverflow.com/a/34566876/296446
ผู้ได้รับมอบหมายเสมอฉันสับสนจนฉันตระหนักว่าเป็นตัวแทนเป็นเพียงระดับที่ไม่ทำงานบางอย่างสำหรับการเรียนอีก มันเหมือนกับมีคนอื่นมาทำงานสกปรกแทนคุณโดยที่คุณไม่อยากทำเอง
ฉันเขียนเรื่องราวเล็กน้อยเพื่อแสดงให้เห็นถึงสิ่งนี้ อ่านใน Playground ถ้าคุณต้องการ
// MARK: Background to the story
// A protocol is like a list of rules that need to be followed.
protocol OlderSiblingDelegate: class {
// The following command (ie, method) must be obeyed by any
// underling (ie, delegate) of the older sibling.
func getYourNiceOlderSiblingAGlassOfWater()
}
// MARK: Characters in the story
class BossyBigBrother {
// I can make whichever little sibling is around at
// the time be my delegate (ie, slave)
weak var delegate: OlderSiblingDelegate?
func tellSomebodyToGetMeSomeWater() {
// The delegate is optional because even though
// I'm thirsty, there might not be anyone nearby
// that I can boss around.
delegate?.getYourNiceOlderSiblingAGlassOfWater()
}
}
// Poor little sisters have to follow (or at least acknowledge)
// their older sibling's rules (ie, protocol)
class PoorLittleSister: OlderSiblingDelegate {
func getYourNiceOlderSiblingAGlassOfWater() {
// Little sis follows the letter of the law (ie, protocol),
// but no one said exactly how she had to respond.
print("Go get it yourself!")
}
}
// MARK: The Story
// Big bro is laying on the couch watching basketball on TV.
let bigBro = BossyBigBrother()
// He has a little sister named Sally.
let sally = PoorLittleSister()
// Sally walks into the room. How convenient! Now big bro
// has someone there to boss around.
bigBro.delegate = sally
// So he tells her to get him some water.
bigBro.tellSomebodyToGetMeSomeWater()
// Unfortunately no one lived happily ever after...
// The end.
ในการตรวจสอบมีสามส่วนสำคัญในการสร้างและใช้รูปแบบผู้รับมอบสิทธิ์
เมื่อเปรียบเทียบกับเรื่องราว Bossy Big Brother ของเราข้างต้นผู้ได้รับมอบหมายมักใช้สำหรับการใช้งานจริงดังต่อไปนี้:
ส่วนที่ดีคือคลาสเหล่านี้ไม่จำเป็นต้องรู้อะไรเกี่ยวกับกันและกันก่อนยกเว้นว่าคลาสที่ได้รับมอบหมายนั้นเป็นไปตามโปรโตคอลที่ต้องการ
ฉันขอแนะนำให้อ่านบทความสองบทความต่อไปนี้ พวกเขาช่วยให้ฉันเข้าใจผู้ได้รับมอบหมายให้ดียิ่งขึ้นกว่าเอกสารได้
อีกหนึ่งบันทึก
ผู้รับมอบสิทธิ์ที่อ้างอิงคลาสอื่น ๆ ที่พวกเขาไม่ได้เป็นเจ้าของควรใช้weak
คีย์เวิร์ดเพื่อหลีกเลี่ยงรอบการอ้างอิงที่รัดกุม ดูคำตอบนี้สำหรับรายละเอียดเพิ่มเติม
ฉันได้รับการแก้ไขเล็กน้อยในการโพสต์ของ @MakeAppPie
ก่อนอื่นเมื่อคุณสร้างโปรโตคอลตัวแทนควรเป็นไปตามโปรโตคอลคลาส เช่นในตัวอย่างด้านล่าง
protocol ProtocolDelegate: class {
func myMethod(controller:ViewController, text:String)
}
ประการที่สองผู้แทนของคุณควรอ่อนแอเพื่อหลีกเลี่ยงการรักษาวงจร
class ViewController: UIViewController {
weak var delegate: ProtocolDelegate?
}
สุดท้ายคุณปลอดภัยเพราะโปรโตคอลของคุณเป็นค่าที่ไม่บังคับ นั่นหมายความว่าข้อความ "ศูนย์" จะไม่ถูกส่งไปยังคุณสมบัตินี้ คล้ายกับคำสั่งเงื่อนไขrespondToselector
ใน objC แต่ที่นี่คุณมีทุกอย่างในบรรทัดเดียว:
if ([self.delegate respondsToSelector:@selector(myMethod:text:)]) {
[self.delegate myMethod:self text:@"you Text"];
}
ด้านบนคุณมีตัวอย่าง obj-C และด้านล่างคุณมีตัวอย่าง Swift ว่ามีลักษณะอย่างไร
delegate?.myMethod(self, text:"your Text")
delegate?.myMethod
จะไม่เกิดปัญหาเพราะถ้าเป็นผู้รับมอบสิทธิ์nil
ก็จะไม่มีอะไรเกิดขึ้น แต่ถ้าคุณทำผิดพลาดและเขียนdelegate!.myMethod
คุณอาจมีปัญหาหากตัวแทนไม่ได้ตั้งค่าดังนั้นโดยทั่วไปวิธีสำหรับคุณที่จะปลอดภัย ...
นี่คือสาระสำคัญที่ฉันรวบรวมไว้ ฉันสงสัยเหมือนกันและสิ่งนี้ช่วยปรับปรุงความเข้าใจของฉัน เปิดสิ่งนี้ในXcode Playgroundเพื่อดูว่าเกิดอะไรขึ้น
protocol YelpRequestDelegate {
func getYelpData() -> AnyObject
func processYelpData(data: NSData) -> NSData
}
class YelpAPI {
var delegate: YelpRequestDelegate?
func getData() {
println("data being retrieved...")
let data: AnyObject? = delegate?.getYelpData()
}
func processYelpData(data: NSData) {
println("data being processed...")
let data = delegate?.processYelpData(data)
}
}
class Controller: YelpRequestDelegate {
init() {
var yelpAPI = YelpAPI()
yelpAPI.delegate = self
yelpAPI.getData()
}
func getYelpData() -> AnyObject {
println("getYelpData called")
return NSData()
}
func processYelpData(data: NSData) -> NSData {
println("processYelpData called")
return NSData()
}
}
var controller = Controller()
UIViewController
ชั้นเรียนของฉันเป็นไปตามตัวแทนที่เราทำไว้ได้อย่างไร พวกเขาต้องประกาศในไฟล์ที่รวดเร็วเพียงไฟล์เดียวหรือไม่ ความช่วยเหลือใด ๆ จะมีความหมายมาก
class ViewController : UIViewController NameOfDelegate
ดังนั้นสิ่งที่ต้องการ
a.swift
b.swift
ฉันไม่สามารถเข้าถึงชั้นเรียนใด ๆ นอกเหนือจากไฟล์ที่รวดเร็วของฉัน ความเหนียวใด ๆ ?
DELEGATES ใน SWIFT 2
ฉันกำลังอธิบายด้วยตัวอย่าง Delegate with two viewControllers ในกรณีนี้ SecondVC Object กำลังส่งข้อมูลกลับไปที่ View Controller ตัวแรก
คลาสที่มีการประกาศโปรโตคอล
protocol getDataDelegate {
func getDataFromAnotherVC(temp: String)
}
import UIKit
class SecondVC: UIViewController {
var delegateCustom : getDataDelegate?
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func backToMainVC(sender: AnyObject) {
//calling method defined in first View Controller with Object
self.delegateCustom?.getDataFromAnotherVC("I am sending data from second controller to first view controller.Its my first delegate example. I am done with custom delegates.")
self.navigationController?.popViewControllerAnimated(true)
}
}
ใน First ViewController Protocol สอดคล้องกันที่นี่:
class ViewController: UIViewController, getDataDelegate
นิยามวิธีโปรโตคอลใน First View Controller (ViewController)
func getDataFromAnotherVC(temp : String)
{
// dataString from SecondVC
lblForData.text = dataString
}
ระหว่างการกด SecondVC จาก First View Controller (ViewController)
let objectPush = SecondVC()
objectPush.delegateCustom = self
self.navigationController.pushViewController(objectPush, animated: true)
ชั้นหนึ่ง:
protocol NetworkServiceDelegate: class {
func didCompleteRequest(result: String)
}
class NetworkService: NSObject {
weak var delegate: NetworkServiceDelegate?
func fetchDataFromURL(url : String) {
delegate?.didCompleteRequest(url)
}
}
ชั้นสอง:
class ViewController: UIViewController, NetworkServiceDelegate {
let network = NetworkService()
override func viewDidLoad() {
super.viewDidLoad()
network.delegate = self
network.fetchDataFromURL("Success!")
}
func didCompleteRequest(result: String) {
print(result)
}
}
Type 'ViewController' does not conform to protocol 'NetworkServiceDelegate'
แนะนำ เป็นวันที่ 6 ของฉันอย่างรวดเร็ว :)
ทีละขั้นตอนง่ายมาก (ทำงานและทดสอบได้ 100%)
ขั้นตอนที่ 1:สร้างวิธีการในตัวควบคุมมุมมองแรก
func updateProcessStatus(isCompleted : Bool){
if isCompleted{
self.labelStatus.text = "Process is completed"
}else{
self.labelStatus.text = "Process is in progress"
}
}
ขั้นตอนที่ 2:ตั้งค่าผู้รับมอบสิทธิ์ในขณะที่กดไปยังตัวควบคุมมุมมองที่สอง
@IBAction func buttonAction(_ sender: Any) {
let secondViewController = self.storyboard?.instantiateViewController(withIdentifier: "secondViewController") as! secondViewController
secondViewController.delegate = self
self.navigationController?.pushViewController(secondViewController, animated: true)
}
ขั้นตอนที่ 3:ตั้งค่าผู้รับมอบสิทธิ์เช่น
คลาส ViewController: UIViewController, ProcessStatusDelegate {
ขั้นตอนที่ 4:สร้างโปรโตคอล
protocol ProcessStatusDelegate:NSObjectProtocol{
func updateProcessStatus(isCompleted : Bool)
}
ขั้นตอนที่ 5:รับตัวแปร
var delegate:ProcessStatusDelegate?
ขั้นตอนที่ 6:ในขณะที่กลับไปที่วิธีการมอบสิทธิ์การเรียกใช้ตัวควบคุมมุมมองก่อนหน้าดังนั้นตัวควบคุมมุมมองแรกจะแจ้งให้ทราบด้วยข้อมูล
@IBAction func buttonActionBack(_ sender: Any) {
delegate?.updateProcessStatus(isCompleted: true)
self.navigationController?.popViewController(animated: true)
}
@IBAction func buttonProgress(_ sender: Any) {
delegate?.updateProcessStatus(isCompleted: false)
self.navigationController?.popViewController(animated: true)
}
ตัวอย่างง่ายๆ:
protocol Work: class {
func doSomething()
}
class Manager {
weak var delegate: Work?
func passAlong() {
delegate?.doSomething()
}
}
class Employee: Work {
func doSomething() {
print("Working on it")
}
}
let manager = Manager()
let developer = Employee()
manager.delegate = developer
manager.passAlong() // PRINTS: Working on it
ผู้รับมอบสิทธิ์เป็นรูปแบบการออกแบบที่อนุญาตให้วัตถุหนึ่งส่งข้อความไปยังวัตถุอื่นเมื่อเกิดเหตุการณ์เฉพาะ ลองนึกภาพวัตถุ A เรียกวัตถุ B เพื่อดำเนินการ เมื่อการดำเนินการเสร็จสิ้นวัตถุ A ควรรู้ว่า B ทำงานเสร็จแล้วและดำเนินการตามความจำเป็นสิ่งนี้สามารถทำได้ด้วยความช่วยเหลือของผู้ได้รับมอบหมาย! นี่คือบทช่วยสอนการใช้งานตัวแทนทีละขั้นตอนใน swift 3
โซลูชันข้างต้นดูเหมือนจะเชื่อมโยงกันเล็กน้อยและในขณะเดียวกันก็หลีกเลี่ยงการนำโปรโตคอลเดียวกันมาใช้ซ้ำในตัวควบคุมอื่น ๆ นั่นเป็นเหตุผลที่ฉันมาพร้อมกับโซลูชันที่พิมพ์ได้ชัดเจนยิ่งขึ้นโดยใช้การลบประเภททั่วไป
@noreturn public func notImplemented(){
fatalError("not implemented yet")
}
public protocol DataChangedProtocol: class{
typealias DataType
func onChange(t:DataType)
}
class AbstractDataChangedWrapper<DataType> : DataChangedProtocol{
func onChange(t: DataType) {
notImplemented()
}
}
class AnyDataChangedWrapper<T: DataChangedProtocol> : AbstractDataChangedWrapper<T.DataType>{
var base: T
init(_ base: T ){
self.base = base
}
override func onChange(t: T.DataType) {
base.onChange(t)
}
}
class AnyDataChangedProtocol<DataType> : DataChangedProtocol{
var base: AbstractDataChangedWrapper<DataType>
init<S: DataChangedProtocol where S.DataType == DataType>(_ s: S){
self.base = AnyDataChangedWrapper(s)
}
func onChange(t: DataType) {
base.onChange(t)
}
}
class Source : DataChangedProtocol {
func onChange(data: String) {
print( "got new value \(data)" )
}
}
class Target {
var delegate: AnyDataChangedProtocol<String>?
func reportChange(data:String ){
delegate?.onChange(data)
}
}
var source = Source()
var target = Target()
target.delegate = AnyDataChangedProtocol(source)
target.reportChange("newValue")
เอาต์พุต : มีค่าใหม่ newValue
สร้างผู้รับมอบสิทธิ์ในชั้นเรียนที่ต้องการส่งข้อมูลบางอย่างหรือมอบฟังก์ชันการทำงานบางอย่างให้กับชั้นเรียนอื่น
ชอบ
protocol GetGameStatus {
var score: score { get }
func getPlayerDetails()
}
หลังจากนั้นในชั้นเรียนที่จะยืนยันกับผู้รับมอบสิทธิ์นี้
class SnakesAndLadders: GetGameStatus {
func getPlayerDetails() {
}
}