IOS - วิธีแยกย่อยโดยใช้โปรแกรมอย่างรวดเร็ว


185

ฉันกำลังสร้างแอพที่ใช้ Facebook SDK เพื่อตรวจสอบสิทธิ์ผู้ใช้ ฉันกำลังพยายามรวมตรรกะของ Facebook ไว้ในชั้นเรียนอื่น นี่คือรหัส (ปล้นเพื่อความเรียบง่าย):

import Foundation

class FBManager {
    class func fbSessionStateChane(fbSession:FBSession!, fbSessionState:FBSessionState, error:NSError?){
        //... handling all session states
        FBRequestConnection.startForMeWithCompletionHandler { (conn: FBRequestConnection!, result: AnyObject!, error: NSError!) -> Void in

            println("Logged in user: \n\(result)");

            let storyboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
            let loggedInView: UserViewController = storyboard.instantiateViewControllerWithIdentifier("loggedInView") as UserViewController

            loggedInView.result = result;

            //todo: segue to the next view???
        }
    }
}

ฉันใช้วิธีการเรียนข้างต้นเพื่อตรวจสอบการเปลี่ยนแปลงสถานะเซสชันและใช้งานได้ดี

ถาม:เมื่อฉันมีข้อมูลของผู้ใช้ฉันจะแบ่งมุมมองต่อไปจากภายในคลาสที่กำหนดเองนี้ได้อย่างไร

แก้ไข:เพื่อให้ชัดเจนฉันมีส่วนต่อขยายที่มีตัวระบุบนกระดานเรื่องราวและฉันกำลังพยายามหาวิธีที่จะแสดงบทต่อจากคลาสที่ไม่ใช่ตัวควบคุมมุมมอง


2
ชอบperformSegue:ไหม
HAS

ใช่ แต่รหัสไม่ได้อยู่ใน viewController ฉันจะทำสิ่งนี้ได้อย่างไร
Shlomi Schwartz

ในกรณีนี้คุณควรมอบหมายงานนั้น (การแยก) จากวัตถุที่คุณทำงานในตัวควบคุมมุมมอง (ผ่านบล็อกที่สมบูรณ์หรือวิธีการมอบหมาย)
HAS

รับข้อยกเว้นเลย์เอาต์ที่ไม่ใช่ศูนย์
Chris Hayes

คำตอบ:


340

หากซีคิวของคุณมีอยู่ในสตอรีบอร์ดที่มีตัวระบุซีเกดระหว่างมุมมองทั้งสองของคุณคุณสามารถเรียกมันโดยใช้การเขียนโปรแกรมโดยใช้:

performSegue(withIdentifier: "mySegueID", sender: nil)

สำหรับรุ่นเก่า:

performSegueWithIdentifier("mySegueID", sender: nil)

คุณสามารถทำได้:

presentViewController(nextViewController, animated: true, completion: nil)

หรือถ้าคุณอยู่ในตัวควบคุมทิศทาง:

self.navigationController?.pushViewController(nextViewController, animated: true)

7
ขอบคุณสำหรับการตอบฉันจะเรียก performSegueWithIdentifier จากคลาสที่กำหนดเองซึ่งไม่ใช่มุมมองได้อย่างไร
Shlomi Schwartz

2
ถ้าฉันใช้วิธีที่สองของคุณ จะส่งข้อมูลไปยังมุมมองถัดไปได้อย่างไร
iamprem

2
คุณจะใช้ func prepareForSegue (segue: UIStoryboardSegue, ผู้ส่ง: AnyObject?) และตั้งค่าคุณสมบัติ
Lloyd Sargent

1
หมายเหตุเมื่อเรียกใช้ performSequeWithIdentifer () การใช้งานของ prepareForSeque () ในตัวควบคุมการโทรของคุณจะถูกเรียกใช้และคุณสามารถทำข้อมูลต่าง ๆ ผ่านไปได้ - ในความเป็นจริงพารามิเตอร์ผู้ส่งที่ได้รับใน prepareForSeque () เป็นเพียงสิ่งที่ performSequeWithIdentifier ()
timbo

1
จะเกิดอะไรขึ้นถ้าไม่มีการแสดงส่วนย่อยในกระดานเรื่องราว ตัวอย่างเช่นหากคุณต้องการสร้างซีคูนให้กับ ViewController
scaryguy

20

คุณสามารถใช้NSNotification

เพิ่มวิธีการโพสต์ในชั้นเรียนที่กำหนดเองของคุณ:

NSNotificationCenter.defaultCenter().postNotificationName("NotificationIdentifier", object: nil)

เพิ่มผู้สังเกตการณ์ใน ViewController ของคุณ:

NSNotificationCenter.defaultCenter().addObserver(self, selector: "methodOFReceivedNotication:", name:"NotificationIdentifier", object: nil)

เพิ่มฟังก์ชั่นในตัวคุณ ViewController:

func methodOFReceivedNotication(notification: NSNotification){
    self.performSegueWithIdentifier("yourIdentifierInStoryboard", sender: self)
}

1
โปรดอย่าแจ้งเตือนการละเมิดเช่นนี้ ใช้ผู้รับมอบสิทธิ์และทำการเชื่อมต่อระหว่างตัวควบคุมมุมมองและคลาสของคุณอย่างชัดเจน เป็นไปไม่ได้ที่จะสังเกตเห็นลำดับการควบคุมของการแจ้งเตือนเนื่องจากอาจมีสมาชิกหลายรายและอินสแตนซ์สามารถสมัคร / ยกเลิกการสมัครได้ตามต้องการ
uliwitness

17

หากซีคิวของคุณมีอยู่ในสตอรีบอร์ดที่มีตัวระบุซีจีระหว่างมุมมองทั้งสองของคุณคุณสามารถเรียกมันได้โดยใช้โปรแกรม

self.performSegueWithIdentifier("yourIdentifierInStoryboard", sender: self)

หากคุณอยู่ในตัวควบคุมทิศทาง

let viewController = YourViewController(nibName: "YourViewController", bundle: nil)        
self.navigationController?.pushViewController(viewController, animated: true)

ฉันจะแนะนำคุณสำหรับแนวทางที่สองโดยใช้ตัวควบคุมทิศทาง


self.performSegue (withIdentifier: "yourIdentifierInStoryboard" ผู้ส่ง: ตนเอง)
Rajneesh071

14

คุณสามารถใช้ segue ดังนี้:

self.performSegueWithIdentifier("push", sender: self)
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
    if segue.identifier == "push" {

    }
}

ขอบคุณสำหรับการตอบกลับอย่างไรก็ตาม performSegueWithIdentifier เป็นวิธีการ viewController และรหัสของฉันทำงานในชั้นเรียนภายนอก
Shlomi Schwartz

13

Swift 3 - ใช้งานได้กับ SpriteKit

คุณสามารถใช้NSNotification

ตัวอย่าง:

1. ) สร้างการทำต่อในกระดานเรื่องราวและตั้งชื่อตัวระบุ "ทำต่อ"

2. ) สร้างฟังก์ชั่นใน ViewController ที่คุณแยกจาก

func goToDifferentView() {

    self.performSegue(withIdentifier: "segue", sender: self)

}

3. ) ใน ViewDidLoad () ของ ViewController ของคุณคุณจะแยกจากการสร้างผู้สังเกตการณ์

NotificationCenter.default.addObserver(self, selector: #selector(goToDifferentView), name: "segue" as NSNotification.Name, object: nil)

อัปเดต - ครั้งล่าสุดที่ฉันใช้สิ่งนี้ฉันต้องเปลี่ยนการ.addObserverโทรเป็นรหัสต่อไปนี้เพื่อปิดข้อผิดพลาด

NotificationCenter.default.addObserver(self, selector: #selector(goToDifferentView), name: NSNotification.Name(rawValue: "segue"), object: nil)

4. ) ใน ViewController หรือฉากที่คุณแบ่งเวลาให้เพิ่มวิธีการโพสต์ทุกที่ที่คุณต้องการให้มีการเรียกใช้ Segue

NotificationCenter.default.post(name: "segue" as NSNotification.Name, object: nil)

อัปเดต - ครั้งล่าสุดที่ฉันใช้สิ่งนี้ฉันต้องเปลี่ยนการ.postโทรเป็นรหัสต่อไปนี้เพื่อปิดข้อผิดพลาด

NotificationCenter.default.post(NSNotification(name: NSNotification.Name(rawValue: "segue"), object: nil) as Notification)

Swift 3:NotificationCenter.default.addObserver(self, selector: #selector(goToDifferentView), name: NSNotification.Name(rawValue: "segue"), object: nil)
Michael Samoylov

3

สิ่งที่คุณต้องการทำมีความสำคัญสำหรับการทดสอบหน่วย โดยทั่วไปคุณจำเป็นต้องสร้างฟังก์ชั่นท้องถิ่นขนาดเล็กในตัวควบคุมมุมมอง performSegueWithIndentifierชื่ออะไรฟังก์ชั่นเพียงรวม

func localFunc() {
    println("we asked you to do it")
    performSegueWithIdentifier("doIt", sender: self)
}

ถัดไปเปลี่ยนคลาสยูทิลิตี้ของคุณFBManagerเพื่อรวม initializer ที่รับอาร์กิวเมนต์ของฟังก์ชั่นและตัวแปรที่จะเก็บฟังก์ชั่นของ ViewController ที่ดำเนินการต่อ

public class UtilClass {

    var yourFunction : () -> ()

    init (someFunction: () -> ()) {
        self.yourFunction = someFunction
        println("initialized UtilClass")
    }

    public convenience init() {
        func dummyLog () -> () {
            println("no action passed")
        }
        self.init(dummyLog)
    }

    public func doThatThing() -> () {
        // the facebook login function
        println("now execute passed function")
        self.yourFunction()
        println("did that thing")
    }
}

(ความสะดวกสบาย init ช่วยให้คุณสามารถใช้สิ่งนี้ในการทดสอบหน่วยโดยไม่ต้องดำเนินการต่อ)

สุดท้ายที่คุณมี // todo: ทำต่อในมุมมองถัดไป ??? ให้ใส่บางสิ่งตามบรรทัดของ:

self.yourFunction()

ในการทดสอบหน่วยของคุณคุณสามารถเรียกมันว่า:

let f = UtilClass()
f.doThatThing()

โดยที่ doThatThing คือการเปลี่ยนสถานะ fbsession ของคุณและUtilClassFBManager

สำหรับรหัสจริงของคุณเพียงแค่ส่งlocalFunc(ไม่มีวงเล็บ) ไปยังคลาส FBManager


2

สิ่งนี้ใช้ได้สำหรับฉัน

ก่อนอื่นให้คอนโทรลเลอร์มุมมองในสตอรี่บอร์ดของคุณมี ID สตอรีบอร์ดภายในตัวตรวจสอบตัวตน จากนั้นใช้โค้ดตัวอย่างต่อไปนี้ (ตรวจสอบให้แน่ใจว่าคลาสชื่อสตอรีบอร์ดและ ID บอร์ดเรื่องราวตรงกับที่คุณใช้อยู่):

let viewController:
UIViewController = UIStoryboard(
    name: "Main", bundle: nil
).instantiateViewControllerWithIdentifier("ViewController") as UIViewController
// .instantiatViewControllerWithIdentifier() returns AnyObject!
// this must be downcast to utilize it

self.presentViewController(viewController, animated: false, completion: nil)

สำหรับรายละเอียดเพิ่มเติมดูhttp://sketchytech.blogspot.com/2012/11/instantiate-view-controller-using.html ความปรารถนาดีที่สุด


1

คุณสามารถทำสิ่งนี้โดยใช้performSegueWithIdentifierฟังก์ชั่น

ภาพหน้าจอ

ไวยากรณ์:

func performSegueWithIdentifier(identifier: String, sender: AnyObject?)

ตัวอย่าง:

 performSegueWithIdentifier("homeScreenVC", sender: nil)

1

อีกทางเลือกหนึ่งคือการใช้คำกริยาต่อ

ขั้นตอนที่ 1:ไปที่สตอรี่บอร์ดและให้มุมมองควบคุมStoryboard ID คุณสามารถค้นหาตำแหน่งที่จะเปลี่ยน ID สตอรีบอร์ดได้ใน Identity Inspector ทางด้านขวา ให้เรียกใช้สตอรีบอร์ด IDModalViewController

ขั้นตอนที่ 2:เปิดตัวควบคุมมุมมอง 'ผู้ส่ง' (เรียกมันว่าViewController) และเพิ่มรหัสนี้

public class ViewController {
  override func viewDidLoad() {
    showModalView()
  }

  func showModalView() {
    if let mvc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ModalViewController") as? ModalViewController {
      self.present(mvc, animated: true, completion: nil)
    }
  }
}

โปรดทราบว่า View Controller ที่เราต้องการเปิดนั้นเรียกอีกอย่างว่า ModalViewController

ขั้นตอนที่ 3:เพื่อปิด ModalViewController ให้เพิ่มเข้าไป

public class ModalViewController {
   @IBAction func closeThisViewController(_ sender: Any?) {
      self.presentingViewController?.dismiss(animated: true, completion: nil)
   }
}

0

สิ่งนี้ใช้ได้กับฉัน:

//Button method example
 @IBAction func LogOutPressed(_ sender: UIBarButtonItem) {

        do {
            try Auth.auth().signOut()
            navigationController?.popToRootViewController(animated: true)

        } catch let signOutError as NSError {
          print ("Error signing out: %@", signOutError)
        }


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