Swift 如何通过segue将数据从一个视图控制器传递到另一个视图控制器(可选)
当我单击NSCollectionViewItem时,我试图让数据从一个视图传递到下一个视图。当一个项目被点击时,我只想将一些数据传递给一个新的视图,以获得每个项目的更“详细”的视图 我不断得到“致命错误:在展开可选值时意外发现nil”。我觉得ProductDetail.swift文件中缺少了一个关键步骤。错误发生在my prepare()方法中ViewController.swift的底部。如何在OSX上实现这一点的过程与iOS完全不同,因此非常感谢您的帮助 ViewController.swiftSwift 如何通过segue将数据从一个视图控制器传递到另一个视图控制器(可选),swift,macos,segue,swift3,nsstoryboard,Swift,Macos,Segue,Swift3,Nsstoryboard,当我单击NSCollectionViewItem时,我试图让数据从一个视图传递到下一个视图。当一个项目被点击时,我只想将一些数据传递给一个新的视图,以获得每个项目的更“详细”的视图 我不断得到“致命错误:在展开可选值时意外发现nil”。我觉得ProductDetail.swift文件中缺少了一个关键步骤。错误发生在my prepare()方法中ViewController.swift的底部。如何在OSX上实现这一点的过程与iOS完全不同,因此非常感谢您的帮助 ViewController.swi
import Cocoa
class ViewController: NSViewController {
@IBOutlet weak var colView: NSCollectionView!
var productCategories: [ProductCategory]?
var productsArray: [ProductModel]?
var detailLabel: test1?
override func viewWillAppear() {
super.viewWillAppear()
preferredContentSize = NSSize(width: 1025, height: 1200)
}
override func viewDidLoad() {
super.viewDidLoad()
getJSON()
}
func getJSON() {
let requestURL: NSURL = NSURL(string: "http://myurl.php")!
let urlRequest: NSMutableURLRequest = NSMutableURLRequest(url: requestURL as URL)
let session = URLSession.shared
let task = session.dataTask(with: urlRequest as URLRequest) {
(data, response, error) -> Void in
let httpResponse = response as! HTTPURLResponse
let statusCode = httpResponse.statusCode
if (statusCode == 200) {
do{
let json = try JSONSerialization.jsonObject(with: data!, options:.mutableContainers)
self.productsArray = [ProductModel]()
if let products = json as? [[String: Any]] {
for product in products {
let testproduct = ProductModel()
testproduct.product_name = product["product_name"] as? String
testproduct.product_price = product["product_price"] as? String
testproduct.product_image = product["product_image"] as? String
self.productsArray?.append(testproduct)
}
DispatchQueue.main.async(){
self.colView.reloadData()
}
}
}catch {
print("Error parsing the JSON: \(error)")
}
}
}
task.resume()
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}
extension ViewController: NSCollectionViewDataSource, NSCollectionViewDelegate{
func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
return productsArray?.count ?? 0
}
func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
let item = collectionView.makeItem(withIdentifier: "test1", for: indexPath) as! test1
item.buildProduct = productsArray?[indexPath.item]
return item
}
func collectionView(_ collectionView: NSCollectionView, didSelectItemsAt indexPaths: Set<IndexPath>) {
print("selected")
self.performSegue(withIdentifier: "showProductDetail", sender: self)
}
override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
if (segue.identifier == "showProductDetail") {
if let detailVC = segue.destinationController as? ProductDetail {
detailVC.testLabel.stringValue = (detailLabel?.label.stringValue)!
}else{
detailLabel?.label.stringValue = "failed"
}
}
}
}
ProductDetail.swift
import Cocoa
class test1: NSCollectionViewItem {
@IBOutlet weak var label: NSTextField!
@IBOutlet weak var label2: NSTextField!
@IBOutlet weak var productImageView: NSImageView!
var productItem: ProductModel?
var buildProduct: ProductModel? {
didSet{
label.stringValue = (buildProduct?.product_name)!
label2.stringValue = (buildProduct?.product_price)!
setupAppIconImage()
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
func setupAppIconImage() {
if let appIconImageURL = buildProduct?.product_image {
let url = NSURL(string: appIconImageURL)
URLSession.shared.dataTask(with: url! as URL,completionHandler:{(data, response, error) in
if error != nil {
print(error)
return
}
self.productImageView.image = NSImage(data: data!)
}).resume()
}
}
}
import Cocoa
class ProductDetail: NSViewController {
@IBOutlet weak var testLabel: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
}
}
class ProductDetail: NSViewController {
@IBOutlet weak var testLabel: NSTextField!
var theBigPass = String()
override func viewDidLoad() {
super.viewDidLoad()
testLabel.stringValue = theBigPass
}
}
我终于弄明白了。这比我想象的要简单得多。我需要创建一个变量来保存传入的新数据。感谢桑托什的帮助和指导 ProductDetail.swift
import Cocoa
class test1: NSCollectionViewItem {
@IBOutlet weak var label: NSTextField!
@IBOutlet weak var label2: NSTextField!
@IBOutlet weak var productImageView: NSImageView!
var productItem: ProductModel?
var buildProduct: ProductModel? {
didSet{
label.stringValue = (buildProduct?.product_name)!
label2.stringValue = (buildProduct?.product_price)!
setupAppIconImage()
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
func setupAppIconImage() {
if let appIconImageURL = buildProduct?.product_image {
let url = NSURL(string: appIconImageURL)
URLSession.shared.dataTask(with: url! as URL,completionHandler:{(data, response, error) in
if error != nil {
print(error)
return
}
self.productImageView.image = NSImage(data: data!)
}).resume()
}
}
}
import Cocoa
class ProductDetail: NSViewController {
@IBOutlet weak var testLabel: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
}
}
class ProductDetail: NSViewController {
@IBOutlet weak var testLabel: NSTextField!
var theBigPass = String()
override func viewDidLoad() {
super.viewDidLoad()
testLabel.stringValue = theBigPass
}
}
ViewController.swift Segue方法
func collectionView(_ collectionView: NSCollectionView, didSelectItemsAt indexPaths: Set<IndexPath>) {
print("selected")
let selectedIndexPath = collectionView.selectionIndexPaths.first
let item = collectionView.item(at: selectedIndexPath!)
detailLabel = item as! test1?
self.performSegue(withIdentifier: "showProductDetail", sender: self)
}
override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
if (segue.identifier == "showProductDetail") {
if let detailVC = segue.destinationController as? ProductDetail {
let passed = (detailLabel?.label.stringValue)!
detailVC.theBigPass = passed
}
}
}
func collectionView(\collectionView:NSCollectionView,didSelectItemsAt indexpath:Set){
打印(“选定”)
让selectedIndexPath=collectionView.SelectionIndexPath.first
让item=collectionView.item(位于:selectedIndexPath!)
detailLabel=项目名称为!test1?
self.performsgue(带有标识符:“showProductDetail”,发件人:self)
}
覆盖功能准备(对于segue:NSStoryboardSegue,发送方:有吗?){
if(segue.identifier==“showProductDetail”){
如果让detailVC=segue.destinationController作为?ProductDetail{
通过=(detailLabel?label.stringValue)!
detailVC.theBigPass=已通过
}
}
}
尝试在didSelectItemAt
方法中使用let item=collectionView.item(at:indexPaths)将其初始化为!test1 detailLabel=item
尝试以下操作:让selectedIndexPath=collectionView.SelectionIndexPath.first让item=collectionView.item(在:selectedIndexPath!)detailLabel=item
是,因为它没有你在访问它之前需要设置的值。你从一个VC向另一个VC传递数据是正确的,但是当你有数据时,只有你才能正确地传递?因此,当您选择一个项目时,您需要捕获该值以便可以传递,正如前面提到的那样,您可以在didselect中执行该操作,这很好,您可以捕获要传递的值。现在,检查您的testLabel是否正确连接到ProductDetail xib/情节提要中。而且还要确保在情节提要中定义了segue。