どのようにしてデリゲートを作成するの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>
、viewcontrollerを初期化/構成し、サブビューでデリゲートメソッドを呼び出すことができます。これに似たもの?
2つのView Controller間のデリゲートに関する小さなヘルプを次に示します。
手順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:デリゲートをprepareForSegueに設定します。
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
構造体や列挙型ではなく、クラスにのみ必要です。デリゲートが構造体または列挙型になる場合は、保持サイクルを心配する必要はありません。ただし、デリゲートはクラスです(多くの場合はViewControllerであるため、これは多くの場合に当てはまります)weak
。必要なプロトコルはクラスとして宣言する必要があります。詳細はこちらStackoverflow.com/a/34566876/296446
デリゲートは、別のクラスで機能するクラスにすぎないことに気づくまで、デリゲートは常に私を混乱させていました。それは、あなたが自分でやりたくないすべての汚い仕事を他の誰かに依頼するようなものです。
私はこれを説明するために少し話を書きました。必要に応じて、プレイグラウンドで読んでください。
// 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.
復習すると、デリゲートパターンの作成と使用には3つの重要な部分があります。
上記のBossy Big Brotherのストーリーと比較すると、デリゲートは次の実用的なアプリケーションによく使用されます。
大きな部分は、デリゲートクラスが必要なプロトコルに準拠していることを除いて、これらのクラスが事前にお互いについて何も知る必要がないことです。
次の2つの記事を読むことを強くお勧めします。これらは、ドキュメントよりも代理人を理解するのに役立ちました。
もう一つのメモ
所有していない他のクラスを参照するデリゲートは、weak
強い参照サイクルを回避するためにキーワードを使用する必要があります。詳細については、この回答を参照してください。
@MakeAppPieの投稿にいくつか修正を加えました
最初に、デリゲートプロトコルを作成するときは、クラスプロトコルに準拠する必要があります。以下の例のように。
protocol ProtocolDelegate: class {
func myMethod(controller:ViewController, text:String)
}
第2に、保持サイクルを回避するためにデリゲートを弱くする必要があります。
class ViewController: UIViewController {
weak var delegate: ProtocolDelegate?
}
最後に、プロトコルはオプションの値なので、安全です。つまり、「nil」メッセージはこのプロパティに送信されません。これrespondToselector
はobjCでの条件付きステートメントに似ていますが、ここでは1行にすべてが含まれています。
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
デリゲートに準拠するようにクラスを作成するにはどうすればよいですか?それらは1つの迅速なファイルで宣言する必要がありますか?どんな助けも意味があります。
class ViewController : UIViewController NameOfDelegate
。
a.swift
上記の答えに従ってデリゲートクラスを作成すると、で表示されませんb.swift
。Swiftファイル以外のクラスにはアクセスできません。どんな考え?
SWIFT 2のデリゲート
2つのviewControllerを持つデリゲートの例で説明します。この場合、SecondVCオブジェクトは最初の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)
}
}
最初のViewControllerプロトコルでの適合はここで行われます:
class ViewController: UIViewController, getDataDelegate
First View Controller(ViewController)でのプロトコルメソッド定義
func getDataFromAnotherVC(temp : String)
{
// dataString from SecondVC
lblForData.text = dataString
}
First View Controller(ViewController)からのSecondVCのプッシュ中
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)
}
}
2番目のクラス:
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'
plzが表示されます。それは迅速な私の6日目です:)
ステップバイステップで非常に簡単(100%動作し、テスト済み)
ステップ 1 :最初のView Controllerでメソッドを作成する
func updateProcessStatus(isCompleted : Bool){
if isCompleted{
self.labelStatus.text = "Process is completed"
}else{
self.labelStatus.text = "Process is in progress"
}
}
ステップ2: 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