2017-06-26 140 views
1

Hails,UIPickerView未填充

我很難寫出乾淨的代碼。因此,我想保留我的數據源和deletegate在單獨的類文件和擴展名。所以想要更接近M-V-C風格。因此,我的模型是從我所有的控制器類和視圖類中分離出來的。但是填充pickerView對象存在一個問題。這是代碼;

//我的委託和數據源 進口基金會 進口的UIKit

class MyPickerView: NSObject{ 
var data = PickerViewData.getData() 



} 
extension MyPickerView: UIPickerViewDataSource{ 
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { 
    return 1 
} 

func numberOfComponents(in pickerView: UIPickerView) -> Int { 
    return self.data.count 
}  
} 

extension MyPickerView: UIPickerViewDelegate{ 
func pickerView(_ pickerView: UIPickerView, rowHeightForComponent 
component: Int) -> CGFloat { 
    return 100 
} 

func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, 
forComponent component: Int, reusing view: UIView?) -> UIView { 

    let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) 
    let dayLbl = UILabel(frame: CGRect(x: 0, y: 10, width: 100, height: 15)) 
    let priceLbl = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) 
    let petLbl = UILabel(frame: CGRect(x: 0, y: 78, width: 100, height: 15)) 
    dayLbl.text = data[row].dayName 
    priceLbl.text = String(data[row].price) 
    petLbl.text = data[row].petName 

    dayLbl.textAlignment = .center 
    priceLbl.textAlignment = .center 
    petLbl.textAlignment = .center 
    view.addSubview(dayLbl) 
    view.addSubview(priceLbl) 
    view.addSubview(petLbl) 
    return view 
} 

}

//我的模型

import Foundation 

struct PickerViewModel{ 
var dayName:String! 
var price:Double! 
var petName:String! 
init(dayName:String,price:Double,petName:String) { 
    self.dayName = dayName 
    self.price = price 
    self.petName = petName 
} 

} 
struct PickerViewData { 
static func getData() -> [PickerViewModel]{ 
    let m = PickerViewModel(dayName: "Pazartesi", price: 32.3, 
petName: "Köpek") 
    let p = PickerViewModel(dayName: "Salı", price: 32.3, petName: 
"Kuş") 
    let z = PickerViewModel(dayName: "Çarşamba", price: 32.3, 
petName: "Kedi") 
    let t = PickerViewModel(dayName: "Perşembe", price: 32.3, 
petName: "Domuz") 
    let k = PickerViewModel(dayName: "Cuma", price: 32.3, petName: 
"Kanarya") 
    return [m,p,z,t,k] 
} 
} 

//我的控制器

import UIKit 

class FirstVC: UIViewController { 

override func viewDidLoad() { 
    super.viewDidLoad() 
    self.view.backgroundColor = .white 
    let pickerView = UIPickerView(frame: CGRect(x: 100, y: 100, 
width: 200, height: 500)) 
    let deldat = MyPickerView() 
    pickerView.delegate = deldat 
    pickerView.dataSource = deldat 
    self.view.addSubview(pickerView) 
} 

override func didReceiveMemoryWarning() { 
    super.didReceiveMemoryWarning() 
    // Dispose of any resources that can be recreated. 
}  

} 

回答

3

拾取器視圖的dataSourcedelegate屬性被聲明爲weak - 這意味着它們不保留您的MyPickerView實例。由於你的實例是一個局部變量,只要viewDidLoad退出,它就會被釋放。

你需要把你MyPickerView例如在實例屬性,因此它保留您的視圖控制器的生命週期:

import UIKit 

class FirstVC: UIViewController { 

    private var deldat: MyPickerView! 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     self.view.backgroundColor = .white 
     let pickerView = UIPickerView(frame: CGRect(x: 100, y: 100, 
width: 200, height: 500)) 
     self.deldat = MyPickerView() 
     pickerView.delegate = deldat 
     pickerView.dataSource = deldat 
     self.view.addSubview(pickerView) 
    } 
} 
+0

你是正確的!我錯過了關於數據源和代表弱點的細節。所以進一步說,我不會使用數據源和委託實例作爲本地變量。因爲我知道弱關鍵字是關於內存性能的,所以你會解釋爲什麼數據源和委託變量被聲明爲弱? 在此先感謝 –

+1

聲明它們爲「弱」有助於防止保留週期。您的視圖控制器擁有對picker視圖的強大引用(通過其「view」屬性)。如果數據源/代理不弱,那麼選擇器視圖將持有一個強大的參考返回到視圖控制器。這意味着,如果視圖控制器可以自由釋放(即沒有其他人正在使用它),由於循環強引用,它仍然會留在內存中作爲「泄漏」,除非您專門將委託/數據源設置爲' nil'。通過使委託/數據源變弱,這不會發生。 – Paulw11

+0

你的解釋是完美的,我理解正確。內存泄漏問題是一個重要的問題,即使iPhone沒有包含大量內存。所以爲了不面對didReceiveMemoryWarning函數調用,我會非常小心地使用關於內存的那種關鍵字。 我感到困擾你更多,但最後一個問題。 那麼爲什麼當viewDidLoad完成時,本地pickerView實例還沒有釋放?即使它被釋放,我仍然與我的pickerview交互? 我有一個想法,也許addsubview方法保持我pickerView的副本? –