I'm trying to request basic info from Wikipedia - user selects tableView row and is taken to a new view that displays info associated with the row (album descriptions). Flow is:
tableView Cell passes user choice to network struct, performs segue to new view
network struct uses choice to query Wikipedia API
received info is passed via delegate method to new view
info is displayed in new view to user
Two issues I'm having:
Networking seems to not be carried out until after the new view is triggered and updated. Initially I didn't use delegate, and just had networking method return its result. But either way, I need networking to get its result back before we get to and update the new view. I've added Dispatch.main.async to the new view for the UI. I thought I may need a completion handler, but I don't fully understand this
Delegate protocol was introduced to fix problem 1, but it still doesn't work. For some reason nothing of the delegate method in the new view is triggering.
Here's the initial tableView trigger:
extension TopTenViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
albumManager.getAlbumInfo(albumTitle: topTenList[indexPath.row][1])
performSegue(withIdentifier: "topTenAlbumInfoSeg", sender: self)
}
Here is the delegate and all the networking:
protocol AlbumManagerDelegate {
func didUpdateAlbumInfo(albumInfo: String)
}
struct AlbumManager {
var newResult: String = ""
var delegate: AlbumManagerDelegate?
func getAlbumInfo(albumTitle: String) {
let wikipedia = Wikipedia.shared
let language = WikipediaLanguage("en")
let _ = wikipedia.requestArticle(language: language, title: albumTitle, imageWidth: 5) { result in
switch result {
case .success(let article):
print(article.displayTitle)
self.delegate?.didUpdateAlbumInfo(albumInfo: article.displayTitle)
print("delegate should be updated")
case .failure(let error):
print(error)
}
}
}
}
Here is the target view:
class AlbumInfoViewController: UIViewController, AlbumManagerDelegate {
#IBOutlet weak var albumDescriptionLabel: UILabel!
#IBOutlet weak var myWebView: WKWebView!
var albumDescription: String = ""
var albumManager = AlbumManager()
override func viewDidLoad() {
super.viewDidLoad()
albumManager.delegate = self
print(albumDescriptionLabel.text)
}
func didUpdateAlbumInfo(albumInfo: String) {
DispatchQueue.main.async {
print("This worked: \(albumInfo)")
self.albumDescriptionLabel.text = "Hi this is: \(albumInfo)"
}
}
}
Currently nothing in didUpdateAlbumInfo in the new view is being triggered. albumDescriptionLabel is not being updated. Could the issue be that the segue is performed too soon? Thanks in advance!
Related
I am new to Swift and am building an app to learn. Right now I am making the registration section of the app.
I thought the UX would be better if there were multiple VC's asking a single question, i.e. one for your name, one for your birthdate, etc as opposed to jamming all that into a single view controller. The final view controller collects all of that information and sends a dictionary as FUser object to be saved on Firebase.
I figured I could instantiate the final view controller on each of the previous five view controllers and pass that data directly to the end. I kept getting errors and figured out that the variables were nil. It works just fine if I pass the data directly to the next view controller but it doesn't seem to let me send it several view controllers down. Obviously there's a nuance to how the memory is being managed here that I'm not tracking.
Is there a way to do what I am trying to do or do I have to pass the data through each view controller along the way?
import UIKit
class FirstViewController: UIViewController {
//MARK: - IBOutlets
#IBOutlet weak var firstNameTextField: UITextField!
//MARK: - ViewLifeCycle
override func viewDidLoad() {
super.viewDidLoad()
}
//MARK: - IBActions
#IBAction func continueToMiddleViewController(_ sender: Any) {
let vcFinal = storyboard?.instantiateViewController(withIdentifier:
"finalVC") as! finalViewController
vcFinal.firstName = firstNameTextField.text
let vc = storyboard?.instantiateViewController(withIdentifier:
"middleVC") as! middleViewController
vc.modalPresentationStyle = .fullScreen
present(vc, animated: false)
}
...
}
import UIKit
class FinalViewController: UIViewController {
var firstName: String?
...
//MARK: - ViewLifeCycle
override func viewDidLoad() {
super.viewDidLoad()
}
...
}
TL;DR: The fastest one that would solve your problem is creating a singleton
There are many strategies for this. For a starter, it might be a good idea to read some begginer articles, like this one. I can update this answer if you don't find it useful, but it'd look just like the article
Viewcontroller's variable can't be initiated until any of the init method is called.
There are detailed answers on this thread.
Passing Data between ViewControllers
Another way to approach this problem could be to make use of closures. Note that personally I've moved away from using storyboards but I'll try to explain still. Closures are also referred to as callbacks, blocks, or in some context like here - completions.
You can declare a closure like let onSubmitInfo: (String?) -> Void below, it stores a reference to a block of code that can be executed at a later stage just like a function and it takes an optional string as a parameter just like a function can.
The closures are specified in the initialisers where a block of code is passed into the respective classes below and the closures are then called in the IBActions that will trigger the block of code that is defined where the below classes are initialised:
class First: UIViewController {
// MARK: - IBOutlets
#IBOutlet weak var firstNameTextField: UITextField!
// MARK: - Properties
private let onSubmitInfo: (String?) -> Void
init(onSubmitInfo: (String?) -> Void) {
self.onSubmitInfo = onSubmitInfo
}
// MARK: - IBActions
#IBAction func continue(_ sender: Any) {
onSubmitInfo(firstNameTextField.text)
}
}
class Second: UIViewController {
// MARK: - IBOutlets
#IBOutlet weak var lastNameTextField: UITextField!
// MARK: - Properties
private let onSubmitInfo: (String?) -> Void
init(onSubmitInfo: (String?) -> Void) {
self.onSubmitInfo = onSubmitInfo
}
// MARK: - IBActions
#IBAction func continue(_ sender: Any) {
onSubmitInfo(lastNameTextField.text)
}
}
To manage showing the above views and collecting the values returned by their closures (i.e. onSubmitInfo) we create a FlowController class that will also show the next view when the closure is called.
In FlowController we define the closures or blocks of code to be executed when it is called inside the IBAction in the respective First and Second classes above.
The optional string that is provided in the respective First and Second classes is used as the (firstName) and (secondName) closure properties below:
class FlowController: UIViewController {
private var fistName: String?
private var lastName: String?
...
private func showFirstView() {
let firstViewController = First(onSubmitInfo: { (firstName) in
self.firstName = firstName
showSecondView()
})
navigationController?.pushViewController(
firstViewController,
animated: true)
}
private func showSecondView() {
let secondViewController = Second(onSubmitInfo: { (lastName) in
self.lastName = lastName
showFinalView()
})
navigationController?.pushViewController(
secondViewController,
animated: true)
}
private func showFinalView() {
let finalViewController = Final(
firstName: firstName,
lastName: lastName)
navigationController?.pushViewController(
finalViewController,
animated: true)
}
}
The FlowController finally shows the Final view controller after it has collected the firstName form the First view controller and the lastName form the Second view controller in the showFinalView function above.
class Final: UIViewController {
let firstName: String
let lastName: String
...
}
I hope this is a shove in the right direction. I have moved away from storyboards because I find creating views in code is more verbose and clear on peer reviews and it was also easier for me to manage constraints and just to manage views in general.
I am developing a small app to connect to my site, download data via a PHP web service, and display it in a table view. To get started I was following a tutorial over on Medium by Jose Ortiz Costa (Article on Medium).
I tweaked his project and got it running to verify the Web service was working and able to get the data. Once I got that working, I started a new project and tried to pull in some of the code that I needed to do the networking and tried to get it to display in a tableview in the same scene instead of a popup scene like Jose's project.
This is where I am running into some issues, as I'm still rather new to the swift programming language (started a Udemy course and have been picking things up from that) getting it to display in the table view. I can see that the request is still being sent/received, but I cannot get it to appear in the table view (either using my custom XIB or a programmatically created cell). I thought I understood how the code was broken down, and even tried to convert it from a UITableViewController to a UITableviewDataSource via an extension of the Viewcontroller.
At this point, I'm pretty stumped and will continue to inspect the code and tweak what I think might be the root cause. Any pointers on how to fix would be really appreciated!
Main Storyboard Screenshot
Struct for decoding my data / Lead class:
import Foundation
struct Lead: Decodable {
var id: Int
var name: String
var program: String
var stage: String
var lastAction: String
}
class LeadModel {
weak var delegate: Downloadable?
let networkModel = Network()
func downloadLeads(parameters: [String: Any], url: String) {
let request = networkModel.request(parameters: parameters, url: url)
networkModel.response(request: request) { (data) in
let model = try! JSONDecoder().decode([Lead]?.self, from: data) as [Lead]?
self.delegate?.didReceiveData(data: model! as [Lead])
}
}
}
ViewController:
import UIKit
class LeadViewController: UIViewController {
// Buttons
#IBOutlet weak var newButton: UIButton!
#IBOutlet weak var firstContactButton: UIButton!
#IBOutlet weak var secondContactButton: UIButton!
#IBOutlet weak var leadTable: UITableView!
let model = LeadModel()
var models: [Lead]?
override func viewDidLoad() {
super.viewDidLoad()
//Make Buttons rounded
newButton.layer.cornerRadius = 10.0
firstContactButton.layer.cornerRadius = 10.0
secondContactButton.layer.cornerRadius = 10.0
//Delegate
model.delegate = self
}
//Send request to web service based off Buttons Name
#IBAction func findLeads(_ sender: UIButton) {
let new = sender.titleLabel?.text
let param = ["stage": new!]
print ("findLead hit")
model.downloadLeads(parameters: param, url: URLServices.leads)
}
}
extension LeadViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
print ("number of sections hit")
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
guard let _ = self.models else {
return 0
}
print ("tableView 1 hit")
return self.models!.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Create an object from LeadCell
let cell = tableView.dequeueReusableCell(withIdentifier: "leadID", for: indexPath) as! LeadCell
// Lead selection
cell.leadName.text = self.models![indexPath.row].name
cell.actionName.text = self.models![indexPath.row].lastAction
cell.stageName.text = self.models![indexPath.row].stage
cell.progName.text = self.models![indexPath.row].program
print ("tableView 2 hit")
// Return the configured cell
return cell
}
}
extension LeadViewController: Downloadable {
func didReceiveData(data: Any) {
//Assign the data and refresh the table's data
DispatchQueue.main.async {
self.models = data as? [Lead]
self.leadTable.reloadData()
print ("LeadViewController Downloadable Hit")
}
}
}
EDIT
So with a little searching around (okay...A LOT of searching around), I finally found a piece that said I had to set the class as the datasource.
leadTable.dataSource = self
So that ended up working (well after I added a prototype cell with the identifier used in my code). I have a custom XIB that isn't working right now and that's my next tackle point.
You load the data, but don't use it. First, add the following statement to the end of the viewDidLoad method
model.delegate = self
Then add the following LeadViewController extension
extension LeadViewController: Downloadable {
func dicReceiveData(data: [Lead]) {
DispatchQueue.main.async {
self.models = data
self.tableView.reloadData()
}
}
}
And a couple of suggestions:
It is not a good practice to use the button title as a network request parameter:
let new = sender.titleLabel?.text
let param = ["stage": new!]
It is better to separate UI and logic. You can use the tag attribute for buttons (you can configure it in the storyboard or programmatically) to check what button is tapped.
You also have several unnecessary type casts in the LeadModel class. You can change
let model = try! JSONDecoder().decode([Lead]?.self, from: data) as [Lead]?
self.delegate?.didReceiveData(data: model! as [Lead])
to
do {
let model = try JSONDecoder().decode([Lead].self, from: data)
self.delegate?.didReceiveData(data: model)
}
catch {}
I have been working on an app. I am a beginner so please ignore any mistakes.
The problem is that i have a view controller, which has 2 container view controllers controlled by a segmented control.
enter image description here
All three of them have separate classes: (say)
MainViewController
FirstViewController
SecondViewController
In the main view controller, i am getting some data from firebase, which i am storing in an array, and this array is to be passed to the first and second container views, which have their table views, which will load data based on this array which is passed.
Now before the data comes back in the MainViewController, the First and Second view controllers are already passed with an empty array, and no data loads up in their table views (obviously because the array is empty).
I want the container view controllers to load up after the data is received, and array is loaded. Any help ?, Thanks
P.s I am not performing any segue because these are container views, and they are automatically loaded as the main view container loads.
EDIT: Being more precise and clear with original code:
Originally I have 3 view controllers
SearchResultsScreenViewController (Main VC)
GuidesListSearchScreenViewController (First Container VC)
ServicesListSearchScreenViewController (Second Container VC)
In the Main VC i used a segmented control to see container vc's on screen, here:
import UIKit
import Firebase
class SearchResultsScreenViewController: UIViewController
{
#IBOutlet weak var GuideListView: UIView!
#IBOutlet weak var ServicesListView: UIView!
var searchQueryKeyword: String?
var guidesDataArray = [GuideDM]()
override func viewDidLoad()
{
super.viewDidLoad()
ServicesListView.isHidden = true
populateGuidesList()
}
#IBAction func SegmentChanged(_ sender: UISegmentedControl)
{
switch sender.selectedSegmentIndex
{
case 0:
GuideListView.isHidden = false
ServicesListView.isHidden = true
break
case 1:
GuideListView.isHidden = true
ServicesListView.isHidden = false
break
default:
break
}
}
func populateGuidesList()
{
let dbRef = Firestore.firestore().collection("guide")
dbRef.getDocuments
{ (snapshot, error) in
if let err = error
{
print(err.localizedDescription)
print("Error: Unable to find guides list")
}
else
{
if let snap = snapshot
{
print("List is started now")
for doc in snap.documents
{
if doc.exists
{
let data = doc.data()
let city = data["city"] as? String ?? ""
let province = data["province"] as? String ?? ""
let country = data["country"] as? String ?? ""
if city.localizedCaseInsensitiveContains(self.searchQueryKeyword!) || province.localizedCaseInsensitiveContains(self.searchQueryKeyword!) || country.localizedCaseInsensitiveContains(self.searchQueryKeyword!)
{
let guideId = doc.documentID
let guideEmail = data["email"] as? String ?? ""
let name = data["name"] as? String ?? ""
let dob = data["dob"] as? String ?? ""
let feeCurrency = data["feeCurrency"] as? String ?? ""
let status = data["status"] as? String ?? ""
let totalReviews = data["totalReviews"] as? Int ?? 0
let rating = data["rating"] as? Int ?? 0
let baseFee = data["baseFee"] as? Int ?? 0
let isGuideFeatured = data["isGuideFeatured"] as? Bool ?? false
//make a model of guide and append in array
let guide = GuideDM(id: guideId, email: guideEmail, name: name, dob: dob, city: city, province: province, country: country, feeCurrency: feeCurrency, status: status, baseFee: baseFee, rating: rating, totalReviews: totalReviews, isGuideFeatured: isGuideFeatured)
self.guidesDataArray.append(guide)
}
}
}
print("list is finalized now")
}
}
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if segue.identifier == "searchScreentoGuideListSegment"
{
let guidesListContainerVC = segue.destination as! GuidesListSearchScreenViewController
guidesListContainerVC.guidesDataArray = self.guidesDataArray
}
}
}
In the above class my code makes a call to function "populateGuidesList()" which makes a network call to get data, and at the same time loads up my container views. The problem is, before the network call returns data, the empty array gets passed to my "GuidesListSearchScreenViewController" i.e. (First container VC), which is a table view, and loads an empty table because the array is not filled yet.
My First container VC class:
import UIKit
import Firebase
class GuidesListSearchScreenViewController: UIViewController
{
#IBOutlet weak var guidesListTableView: UITableView!
var guidesDataArray = [GuideDM]()
override func viewDidLoad()
{
super.viewDidLoad()
guidesListTableView.delegate = self
guidesListTableView.dataSource = self
guidesListTableView.register(UINib(nibName: "GuidesListCellSearchScreenTableViewCell", bundle: nil), forCellReuseIdentifier: "guidesListCell")
}
}
extension GuidesListSearchScreenViewController: UITableViewDataSource, UITableViewDelegate
{
// below functions are to setup the table view
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return guidesDataArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = guidesListTableView.dequeueReusableCell(withIdentifier: "guidesListCell") as! GuidesListCellSearchScreenTableViewCell
//adding properties to cell and then returning cell
return cell
}
}
GOAL: Either load the container view, after the data is received in the array, or refresh the table by again passing the array to container VC and reloading table.
Other solution: I had tried loading up all this array data inside First container VC class, and reloading table view data from there, which works perfectly fine, but to me which is a very inefficient approach, as i need this array in both container views, so making network calls for each container vc seems very inefficient. Therefore, i am trying to get the data once and pass in both container views. Kindly correct me if you feel me wrong.
P.s I have deleted other functionality and simplified the code.
And help would be highly appreciated.
The container view controllers will load when the main view controller is loaded. Therefore you will have to update the container view controllers when the main view controller receives the data.
A simple way to do this is to update the arrays in the container view controllers, and use a didSet on the arrays to force the container view controllers to reload themselves.
For example, if your FirstViewController displays the array data in a table view, you might do this:
var array: [ArrayItem] {
didSet {
tableView.reloadData()
}
}
Then in your main view controller, when the data is received, set this property:
getData() { resultArray in
firstViewController.array = resultArray
}
Please note, since you didn't provide any code, these are just examples and you will have to adjust them to fit your specific situation.
EDIT: Per comment below, you should be careful not to set the array in your FirstViewController before its view has loaded or the call to tableView.reloadData() will cause your app to crash.
I can only speculate without seeing the code, so here goes nothing... 😉
Try doing the following on viewDidLoad() of MainViewController:
Use the property related to FirstViewController (for the sake of my explanation let’s assume it’s named ‘firstVC’). What you want to do is go, firstVC.view.isHidden = true
Do the same to SecondViewController.
Why? Doing so will hide the container VC’s (ViewController) from the MainViewController’s view.
Now what you want to do is, at the place where you get data from Firebase (at the closure), add the following:
firstVC.view.isHidden = false
Do the same to SecondViewController.
This brings it back to view with the data you fetched already populating it.
Hopefully this helps you out some way.
This question already has answers here:
Passing data between view controllers
(45 answers)
Closed 5 years ago.
I'm trying to go back to my las viewController with sending data, but it doesn't work.
When I just use popViewController, I can go back to the page, but I can't move my datas from B to A.
Here is my code :
func goToLastViewController() {
let vc = self.navigationController?.viewControllers[4] as! OnaylarimTableViewController
vc.onayCode.userId = taskInfo.userId
vc.onayCode.systemCode = taskInfo.systemCode
self.navigationController?.popToViewController(vc, animated: true)
}
To pass data from Child to parent Controller, you have to pass data using Delegate pattern.
Steps to implement delegation pattern, Suppose A is Parent viewController and B is Child viewController.
Create protocol, and create delegate variable in B
Extend protocol in A
pass reference to B of A when Push or Present viewcontroller
Define delegate Method in A, receive action.
After that, According to your condition you can call delegate method from B.
You should do it using delegate protocol
class MyClass: NSUserNotificationCenterDelegate
The implementation will be like following:
func userDidSomeAction() {
//implementation
}
And ofcourse you have to implement delegete in your parent class like
childView.delegate = self
Check this for more information
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html
You have to send back to last ViewController with 2 options.
1. Unwind segue. (With use of storyboard)
You can refer this link.
2. Use of delegate/protocol.
You can refer this link.
Also this link will be useful for you.
You can use Coordinator Pattern
For example, I have 2 screens. The first displays information about the user, and from there, he goes to the screen for selecting his city. Information about the changed city should be displayed on the first screen.
final class CitiesViewController: UITableViewController {
// MARK: - Output -
var onCitySelected: ((City) -> Void)?
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
onCitySelected?(cities[indexPath.row])
}
...
}
UserEditViewController:
final class UserEditViewController: UIViewController, UpdateableWithUser {
// MARK: - Input -
var user: User? { didSet { updateView() } }
#IBOutlet private weak var userLabel: UILabel?
private func updateView() {
userLabel?.text = "User: \(user?.name ?? ""), \n"
+ "City: \(user?.city?.name ?? "")"
}
}
And Coordinator:
protocol UpdateableWithUser: class {
var user: User? { get set }
}
final class UserEditCoordinator {
// MARK: - Properties
private var user: User { didSet { updateInterfaces() } }
private weak var navigationController: UINavigationController?
// MARK: - Init
init(user: User, navigationController: UINavigationController) {
self.user = user
self.navigationController = navigationController
}
func start() {
showUserEditScreen()
}
// MARK: - Private implementation
private func showUserEditScreen() {
let controller = UIStoryboard.makeUserEditController()
controller.user = user
controller.onSelectCity = { [weak self] in
self?.showCitiesScreen()
}
navigationController?.pushViewController(controller, animated: false)
}
private func showCitiesScreen() {
let controller = UIStoryboard.makeCitiesController()
controller.onCitySelected = { [weak self] city in
self?.user.city = city
_ = self?.navigationController?.popViewController(animated: true)
}
navigationController?.pushViewController(controller, animated: true)
}
private func updateInterfaces() {
navigationController?.viewControllers.forEach {
($0 as? UpdateableWithUser)?.user = user
}
}
}
Then we just need to start coordinator:
coordinator = UserEditCoordinator(user: user, navigationController: navigationController)
coordinator.start()
I have very strange bug, that I didn't have in objective-c.
I have two navigations controller one after another. In first I have UITableView. On cell click I navigate to second controller, and with clicking back button I navigate to first navigation controller. (I don't do anything else.) My memory go up every time that I navigate to second controller but it doesn't go down when I go back.
Code that I have :
First View Controller :
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "segue", sender: self)
}
// MARK: - Navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segue",
let destination = segue.destination as? SecondViewController,
let rowIndex = table.indexPathForSelectedRow {
let item = allItems[rowIndex.section][rowIndex.row]
destination.itemId = segue.id as Int?
destination.coreDataManager = self.coreDataManager
}
}
Second View Controller
override func viewDidLoad() {
super.viewDidLoad()
// reload data
reloadData()
}
private func reloadData() {
// We need database ready to reload data from server
guard coreDataManager != nil else {
print("We try to prepare view, but core data is not ready jet.")
// stop loader
self.loader.stopLoader()
return
}
self.model = Model.init(itemId: itemId! as NSNumber!, managadContext: coreDataManager!.privateChildManagedObjectContext())
}
Model object is object from Objective-c library.
I know that this object is problematic, because if I comment out last row, the step memory graph disappear.
I use same library with same call in previous Objective-C application and I didn't have this memory leak.
I try with :
deinit {
self.model = nil
}
but it didn't help.
How to solve this memory leak, because if you look at the graph it is quite huge. After opening 4 cells I have 187 MB memory used.
EDIT:
I figured that deinit {} is never called.
SUGGESTION
I make coreDataManager as weak var:
weak var coreDataManager: CoreDataManager? // weak property of Second Controller
FULL CODE:
Second controller
import UIKit
import BIModel
class SecondViewController: UIViewController {
// MARK: - Properties
/// This object represent connection to database.
weak var coreDataManager: CoreDataManager?
/// This is a Server object that represent on witch server we try to connect.
var currentServer: Server?
/// This is a cube id that we would like to open in this dashboard.
var itemId: Int? = 1193 // TODO: replace this
/// This is a model object. This object holds all calculations, all data,...
var model : Model?
// MARK: - Life Cicle
override func viewDidLoad() {
super.viewDidLoad()
// reload data
reloadData()
}
private func reloadData() {
// We need database ready to reload data from server
guard coreDataManager != nil else {
print("We try to prepare view, but core data is not ready jet.")
return
}
guard itemId != nil else {
return
}
self.model = Model.init(cubeId: currentCubeId! as NSNumber!, managadContext: coreDataManager!.privateChildManagedObjectContext())
}
einit {
print("DEINIT HAPPENED")
model = nil
}
}
I clean code a little bit. This is now whole code. "DEINIT HAPPENED" is printed, but memory stack is the same.