2017-06-26 1 views
1

Hails,UIPickerView ne remplit pas

Je suis difficile d'écrire du code propre. Par conséquent, je souhaite conserver ma source de données et la supprimer dans des fichiers et extensions de classe séparés. Alors, restez au plus près du style M-V-C. Par conséquent, mon modèle est séparé de toutes mes classes de contrôleurs et de mes classes de vue. Mais il y a un problème avec le remplissage de l'objet pickerView. Voici le code;

// Mon délégué et Datasource importation Fondation importation 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 
} 

}

// Mon modèle

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] 
} 
} 

// Mon contrôleur

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. 
}  

} 

Répondre

3

Les propriétés dataSource et delegate de la vue sélecteur sont déclarées weak - cela signifie qu'elles ne conservent pas votre instance MyPickerView. Puisque votre instance est une variable locale, dès que viewDidLoad se termine, elle sera libérée.

Vous devez tenir votre instance MyPickerView dans une propriété d'instance, afin qu'il soit conservé pendant toute la durée de votre contrôleur de vue:

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

Vous avez raison! J'ai raté le détail de la faiblesse de la source de données et du délégué. Donc, de plus, je ne vais pas utiliser la source de données et déléguer des instances comme variable locale. Puisque je sais que le mot-clé faible concerne les performances de la mémoire, pourriez-vous expliquer pourquoi les variables de source de données et de délégué sont déclarées faibles? Merci d'avance –

+1

Les déclarer comme «faibles» permet d'éviter les cycles de retenue. Votre contrôleur de vue contient une référence forte à la vue du sélecteur (via sa propriété 'view'). Si la source de données/délégué n'était pas faible, la vue du sélecteur contiendrait une forte référence vers le contrôleur de vue. Cela signifierait que si le contrôleur de vue était libre d'être libéré (c'est-à-dire que rien d'autre ne l'utilisait), il resterait en mémoire en tant que "fuite" à cause des références circulaires fortes sauf si vous spécifiez delegate/datasource à ' nul. En rendant le délégué/datasource faible cela ne se produira pas. – Paulw11

+0

Votre explication est parfaite et j'ai bien compris. Problème de fuite de mémoire est un problème important même les iPhones ne comprend pas beaucoup de concerts de la mémoire. Donc, pour ne pas faire face à l'appel de la fonction didReceiveMemoryWarning, je ferai très attention à utiliser le type de mots-clés sur la mémoire. Je me sens dérangé beaucoup plus mais une dernière question. Alors pourquoi l'instance pickerView locale n'est pas libérée lorsque viewDidLoad est terminé? Pourtant, je suis en interaction avec ma sélection, même si elle est libérée? J'ai une idée, peut-être que la méthode addsubview conserve la copie de mon pickerView? –