Swift: pushed ViewController deinit not called - ios

View Controller Structure
Main View Controller -> Table View Controller -> Detail View Controller
They are all embedded in Navigation Controller.
I pushed Detail View Controller by calling pushViewController. When I come back to Table View Controller from Detail View Controller, I realized Detail View Controller deinit() is not called, which causes fatal error at my project.
How can I make DetailViewController to deinit?? Thank you
Part of Table View Controller code where calls pushViewController
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedTilId = thisDayTIL[indexPath.row].id
if let detailVC = storyboard?.instantiateViewController(withIdentifier: "TILDetailViewController") as? TILDetailViewController {
detailVC.tilId = selectedTilId
detailVC.tilViewModel = self.tilViewModel
detailVC.subjectViewModel = self.subjectViewModel
self.navigationController?.pushViewController(detailVC, animated: true)
}
}
Whole Detail View Controller code
//
// TILDetailViewController.swift
//
import UIKit
import RxSwift
class TILDetailViewController: UIViewController {
#IBOutlet weak var tilTitleLabel: UILabel!
#IBOutlet weak var tilSubjectLabel: UILabel!
#IBOutlet weak var tilContentLabel: UILabel!
var til: TIL!
var tilId: Int!
var tilViewModel: TILViewModel!
var subjectViewModel: SubjectViewModel!
var disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
_ = tilViewModel.allTIL
.map {
$0.filter { $0.id == self.tilId }
}
.subscribe(onNext: { [weak self] til in
self?.setLabelText(til[0])
self?.til = til[0]
})
.disposed(by: disposeBag)
let rightBarButton = UIBarButtonItem(title: "Edit", style: .plain, target: self, action: #selector(editButtonClicked))
self.navigationItem.rightBarButtonItem = rightBarButton
}
deinit {
print("DetailVC deinitialized")
}
#objc private func editButtonClicked(_ sender: Any) {
guard let editVC = storyboard?.instantiateViewController(withIdentifier: "TILEditViewController") as? TILEditViewController else {
return
}
editVC.til = til
editVC.tilViewModel = self.tilViewModel
editVC.subjectViewModel = self.subjectViewModel
editVC.modalPresentationStyle = .overFullScreen
self.present(editVC, animated: true, completion: nil)
}
func setLabelText(_ til: TIL) {
tilTitleLabel.text = til.title
tilContentLabel.text = til.content
tilSubjectLabel.text = subjectViewModel.getSubjectNameById(til.subjectId)
}
}

You're holding a strong reference to self in your Detailed VC which prevents it from being deallocated. This is called a retain cycle.
On this line: $0.filter { $0.id == self.tilId }.
Adding [weak self] to your map block will fix this.

Related

Deinit not called where blocks used in swift 3.0

I have used blocks in cell for getting switch value but now my problem is that deinit not called where i used the blocks. it is completely working previously but in swift 3.0 it is not working.
My switch cell :
import UIKit
class CellSwitch: UITableViewCell {
#IBOutlet weak var objSwitch: UISwitch!
#IBOutlet weak var btnInfo: UIButton!
#IBOutlet weak var lblTitle: UILabel!
var blockSwitch_Change : ((_ isOn:Bool) -> Void)!
var blockBtn_Clicked : (() -> Void)!
override func awakeFromNib() {
super.awakeFromNib()
self.lblTitle.font = Font.init(Font.FontType.custom(Font.FontName.NotoSans_Regular), size: Font.FontSize.standard(Font.StandardSize.Regular)).instance
// Initialization code
}
//MARK:- switch object change
#IBAction func switch_ValChanged(_ obj:UISwitch){
self.blockSwitch_Change?(obj.isOn)
}
//MARK:- button clicked
#IBAction func btnInfo_Clicked(_ sender: UIButton) {
self.blockBtn_Clicked?()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Uses of this cell
let cell = tableView.dequeueReusableCell(withIdentifier: CellSwitch.identifier) as? CellSwitch
cell?.lblTitle.textColor = Color.custom(hexString: objModel.titleLblColor, alpha: 1.0).value
cell?.lblTitle.text = objModel.strTitle
cell?.objSwitch.isOn = objModel.isOn
cell?.btnInfo.isHidden = !objModel.isInfoBtn
cell?.blockBtn_Clicked = {
print("button clicked")
}
cell?.blockSwitch_Change = { (isOn) in
print("switch value changed \(isOn)")
}
if objModel.isEnable == false
{
cell?.isUserInteractionEnabled = false
cell?.contentView.alpha = 0.5
}
else
{
cell?.isUserInteractionEnabled = true
cell?.contentView.alpha = 1.0
}
return cell!
Also if i comment this two blocks then my deinit will called.
It sounds like you are creating a retain cycle by referencing the view controller strongly inside the blocks. Instead you should create a weak reference to the vc to use. This is my preferred method
cell?.blockBtn_Clicked = { [weak self]
print("button clicked")
self?.viewModel.//do something
}
cell?.blockSwitch_Change = { [weak self] (isOn) in
print("switch value changed \(isOn)")
self?.viewModel.//do something
}
The [weak self] portion will pass a weak reference of self into the block, although note this reference is now an optional. You can then use optional chaining or unwrap it after that.

How can I go about controlling 1 view controller from another?

So I have the following layout for my iOS app.
What I'm intending to do is put a table view in the purpleVC to control the Green viewcontroller...the top peachVC will have text in it which will need to change. I'm just not sure how to control one view controller from another. This includes having the purple slide in and out when a button on the GreenVC is clicked. I know there are classes out there to do this however I want to learn as well.
TESTING DELEGATES:
MAINVIEW CONTROLER
import UIKit
protocol Purpleprotocol {
func buttonpressed()
}
protocol Greenprotocol {
}
extension UIViewController {
func alert(message: String, title: String = "") {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
let OKAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alertController.addAction(OKAction)
self.present(alertController, animated: true, completion: nil)
}
}
class MainViewController: UIViewController,Purpleprotocol,Greenprotocol {
weak var infoNav : UINavigationController?
weak var greenVC: GreenVC?
weak var purpleVC: PurpleVC?
weak var peachVC: PeachVC?
func buttonpressed() {
alert(message: "This is message")
print("buttonpressed")
let date = Date()
let calendar = Calendar.current
let hour = calendar.component(.hour, from: date)
let minutes = calendar.component(.minute, from: date)
greenVC?.greenlabel.text = String(hour) + ":" + String(minutes)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "contentSegue" {
let infoNav = segue.destination as! UINavigationController
}
}
}
PURPLEVIEW CONTROLER
class PurpleVC: UIViewController {
var delegate: Purpleprotocol?
#IBAction func butclick(_ sender: UIButton) {
alert(message: "infunction")
delegate?.buttonpressed()
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
Thanks
R
It does depend on the case but to see a few examples:
A) You can connect it through the delegates. Your main view controller has 3 child view controllers to which it should report changes. It should also assign itself as a delegate to all 3 child controllers where it will get all notifications for events. This would look like
func purpleViewController(sender: PVC, selectedItem: Item) {
self.greenViewController.showItem(item: selectedItem)
self.peachVC.showItem(item: selectedItem)
}
func purpleViewController(sender: PVC, shouldSetMenuClosed closed: Bool) {
self.menuConstraint.constant = closed ? targetWidth : 0.0
}
B) You may have a data model which controls the whole screen and has a delegate for each of the children. The model will report any changes to its delegates so they may react accordingly. Main view controller would create an instance of this model when it loads and pass it to all of the children view controllers. The children would then directly manipulate the model:
In green controller:
func onTap() {
mode.menuShown = !mode.menuShown
}
In model:
var menuShown: Bool = true {
didSet {
self.menuDelegate.model(self, changedMenuShownStateTo: menuShown)
}
}
In main view controller:
func model(_ sender: Model, changedMenuShownStateTo shown:Bool) {
self.menuConstraint.constant = shown ? 0.0 : targetWidth
}
C) You can use notifications where any of the controllers may post to notification center a custom notification and other controllers may observe the notifications and act accordingly.
There are many other ways in doing so but these probably most popular. See if any of them fits you...
Delegation.
Your MainViewController will become a delegate to each of the embedded VC's that want to pass back information. From your description you'll need two delegate relationships:
protocol PurpleProtocol {
func selected(row: Int, text: String)
}
protocol GreenProtocol {
func slideButtonPressed()
}
Have MainViewController implement these protocols. Give identifiers to the embed segues. You can find them in the Document Outline view. In prepareForSegue, retain pointers to the embedded VC's and pass your self as the delegate:
class MainViewController: UIViewController, PurpleProtocol, GreenProtocol {
weak var greenVC: GreenViewController?
weak var purpleVC: PurpleViewController?
weak var peachVC: PeachViewController?
func selectedRow(row: Int, text: String) {
// do something useful
}
func slideButtonPressed() {
// slide purple view in or out depending on current state
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "EmbedPurple" {
let dvc = segue.destination as! PurpleViewController
purpleVC = dvc
dvc.delegate = self
}
else if segue.identifier = "EmbedGreen" {
let nav = segue.destination as! UINavigationController
let dvc = nav.topViewController as! GreenViewController
greenVC = dvc
dvc.delegate = self
} else if segue.identifier = "EmbedPeach" {
peachVC = segue.destination as! PeachViewController
}
}
}
In your embedded VC's, add a delegate pointer and call the delegate with the protocol method when it is time:
class GreenViewController: UIViewController {
weak var delegate: GreenProtocol?
#IBAction slideButtonPressed(sender: UIButton) {
delegate?.slideButtonPressed()
}
}
class PurpleViewController: UITableViewController {
weak var delegate: PurpleProtocol?
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
delegate?.selected(row: indexPath.row, text: modelArray[indexPath.row])
}
}

Swift - Delegate through Nav Controller

I'm going to include my full code in this but I will try to give pointers to where the relevant bits are. Basically I am returning to a view controller from an Unwind Segue with some new data. I am using that data successfully in the 'NBARotoHome' VC but I additionally need to pass some of that data through an embedded Nav controller to 'NBARotoTabPager' vc.
I am trying to do this using the 'UpdateChildView' delegate (at the top of the first block of code) and calling its method in 'loadViewData() (in the 'if statement' near the bottom of the first block).
protocol UpdateChildView : class {
func updateView()
func test()
var playerSelected: Player? { get set }
}
class RotoViewRoundCell: UITableViewCell{
#IBOutlet weak var categoryLabel: UILabel!
}
class RotoViewRoundHeader: UITableViewCell{
}
class NBARotoHome: UIViewController{
#IBOutlet weak var posPaidLabel: UILabel!
#IBOutlet weak var progressIndicator: UIProgressView!
#IBOutlet weak var vsLabel: UILabel!
#IBOutlet weak var fantasyFundsAmountLabel: UILabel!
#IBOutlet weak var fantasyFundsLabel: UILabel!
#IBOutlet weak var playerName: UILabel!
#IBOutlet weak var roundIndicator: UILabel!
var selectedPlayer: Player!
var firstNavController: UINavigationController!
weak var updateChildView : UpdateChildView?
override func viewDidLoad() {
super.viewDidLoad()
loadViewData()
firstNavController = self.navigationController
let rightBarButton = UIBarButtonItem(title: "Select", style: UIBarButtonItemStyle.plain, target: self, action: #selector(myRightSideBarButtonItemTapped(_:)))
self.navigationItem.rightBarButtonItem = rightBarButton
self.title = "NBA Roto"
}
func myRightSideBarButtonItemTapped(_ sender:UIBarButtonItem!){
performSegue(withIdentifier: "ShowDraft", sender: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "ShowDraft" {
let navVC = segue.destination as? UINavigationController
let nbaDraftList = navVC?.viewControllers.first as! NBADraftList
nbaDraftList.mainNavController = firstNavController
}
if (segue.identifier == "buyNavControllerChild"){
// let navVC = segue.destination as? UINavigationController
// let buyVC = navVC?.viewControllers.first as! NBARotoTabPager
// buyVC.delegate = self
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
#IBAction func prepareForUnwind(segue: UIStoryboardSegue) {
}
func loadViewData(){
if((selectedPlayer) != nil){
roundIndicator.text = "Upcoming: " + selectedPlayer.game_time
playerName.text = selectedPlayer.Name
vsLabel.text = selectedPlayer.visiting + " # " + selectedPlayer.home
fantasyFundsLabel.text = ""
fantasyFundsAmountLabel.text = ""
updateChildView?.test()
// updateChildView?.playerSelected = selectedPlayer
// updateChildView?.updateView()
}else{
roundIndicator.text = "Select a Player"
playerName.text = "No Player Selected"
vsLabel.text = "--"
fantasyFundsLabel.text = "Fantasy Funds"
fantasyFundsAmountLabel.text = "$10,000"
}
}
}
Because I haven't been able to get the delegate to work, I have been playing around with setting its delegate property in the above 'prepare' method -'buyVC.delegate = self' - but I'm getting 'buyVC has no member delegate' so that has been a dead end.
The next bit of code is the NBARotoTabPager vc which is embedded in the navigation controller. For reasons I'm no longer sure about I decided to make it a subclass of NBARotoHome, but its basically a custom tab pager that uses a segmented control to switch between two additional vcs.
The most important step at this point is just getting the 'test' function to work (which just prints 'test'. Its implemented in the below block of code second from the bottom above updateView).
class NBARotoTabPager: NBARotoHome, UpdateChildView{
#IBOutlet weak var segmentedControl: UISegmentedControl!
#IBOutlet weak var scoreKey: UIBarButtonItem!
#IBOutlet weak var standings: UIBarButtonItem!
var playerSelected: Player?
override func viewDidLoad() {
navigationController?.navigationBar.barTintColor = UIColor(red: 27/255, green: 27/255, blue: 27/255, alpha: 1)
scoreKey.setTitleTextAttributes([NSFontAttributeName: UIFont(name: "Helvetica", size: 13.0)!], for: UIControlState.normal)
scoreKey.tintColor = UIColor.blue
standings.setTitleTextAttributes([NSFontAttributeName: UIFont(name: "Helvetica", size: 13.0)!], for: UIControlState.normal)
standings.tintColor = UIColor.blue
setupView()
}
private func setupView() {
setupSegmentedControl()
updateView()
}
private func setupSegmentedControl() {
// Configure Segmented Control
segmentedControl.removeAllSegments()
segmentedControl.insertSegment(withTitle: "Live", at: 0, animated: false)
segmentedControl.insertSegment(withTitle: "Avg / +", at: 1, animated: false)
segmentedControl.addTarget(self, action: #selector(selectionDidChange(_:)), for: .valueChanged)
segmentedControl.selectedSegmentIndex = 0
}
func selectionDidChange(_ sender: UISegmentedControl) {
updateView()
}
private lazy var viewLiveTab: NBARotoLive = {
// Load Storyboard
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
// Instantiate View Controller
var viewController = storyboard.instantiateViewController(withIdentifier: "NBARotoLive") as! NBARotoLive
if((self.playerSelected) != nil){
viewController.selectedPlayer = self.playerSelected
}
// Add View Controller as Child View Controller
self.add(asChildViewController: viewController)
return viewController
}()
private lazy var viewAvgsTab: NBARotoAvgs = {
// Load Storyboard
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
// Instantiate View Controller
var viewController = storyboard.instantiateViewController(withIdentifier: "NBARotoAvgs") as! NBARotoAvgs
if((self.playerSelected) != nil){
viewController.selectedPlayer = self.playerSelected
}
// Add View Controller as Child View Controller
self.add(asChildViewController: viewController)
return viewController
}()
private func add(asChildViewController viewController: UIViewController) {
// Add Child View Controller
addChildViewController(viewController)
// Add Child View as Subview
view.addSubview(viewController.view)
// Configure Child View
viewController.view.frame = view.bounds
viewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
// Notify Child View Controller
viewController.didMove(toParentViewController: self)
}
private func remove(asChildViewController viewController: UIViewController) {
// Notify Child View Controller
viewController.willMove(toParentViewController: nil)
// Remove Child View From Superview
viewController.view.removeFromSuperview()
// Notify Child View Controller
viewController.removeFromParentViewController()
}
internal func test(){
print("test")
}
internal func updateView() {
if segmentedControl.selectedSegmentIndex == 0 {
let position = viewAvgsTab.tableView.contentOffset.y;
viewLiveTab.tableView.contentOffset = CGPoint(x:0, y:position);
remove(asChildViewController: viewAvgsTab)
add(asChildViewController: viewLiveTab)
} else {
let position = viewLiveTab.tableView.contentOffset.y;
viewAvgsTab.tableView.contentOffset = CGPoint(x:0, y:position);
remove(asChildViewController: viewLiveTab)
add(asChildViewController: viewAvgsTab)
}
}
}
I've looked at a lot of examples but I don't understand the whole 'setting the delegate' thing i.e. theSecondViewController.delegate = self. Sometimes I see examples where you don't need to do this. And other times it seems like my VCs don't even have a delegate property. So I'm not sure if that's my specific problem or not but any direction would be greatly appreciated. Thanks
There are three steps to implement a delegate.
create a protocol.. (you've already done this by creating a updateChildView protocol)
you need to implement this protocol in the class you wish to receive and process this data.. (you've not done this step and thats why you cant set buyVC.delegate = self)
you need to add a property in ViewController2 called "delegate" and make it as a type of your protocol in step 1 (you've not done this step and there is no property called "delegate" in vc2 .. that's why you get this error 'buyVC has no member delegate')
Here's a quick example:
Protocol:
protocol UpdateChildView{ //removed :class
func updateView()
func test()
var playerSelected: Player? { get set }
}
Viewcontroller A:
class NBARotoHome: UIViewController, UpdateChildView { //added conformance to the protocol
//add the methods for conforming to protocol and add your implementation
func updateView() {
//add your implementation
}
func test(){
//add your implementation
}
var playerSelected: Player? {
//add your implementation
}
prepare(for: Segue) {
/** code for passing data **/
let navVC = segue.destination as? UINavigationController
let buyVC = navVC?.viewControllers.first as! NBARotoTabPager
buyVC.delegate = self
//sets the delegate in the new viewcontroller
//remember.. delegate is a property in the next vc
// and the property only accepts any viewcontroller that is implements updatechildview protocol
present(vc2)
}
}
viewcontroller2 :
class viewControllerB: UIViewController {
var delegate: UpdateChildView? //add this
viewdidload {
delegate?.test() //call the func in the previous vc
}
}

How can I do this with one segue?

I want to pass movies's data to another controller also pass another controller when progress is finished.Can I do this with one segue ?
class LoadingScreenViewController: UIViewController {
var movies = [Movie]()
#IBOutlet weak var progress: UIProgressView!
#IBOutlet weak var countLabel: UILabel!
override func viewDidLoad()
{
NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: #selector(LoadingScreenViewController.updateProgress), userInfo: nil, repeats: true)
progress.setProgress(0, animated: true)
}
func updateProgress () {
if progress.progress != 1 {
self.progress.progress += 2 / 10
} else {
UIView.animateWithDuration(0.4, animations: { () -> Void in
})
performSegueWithIdentifier("segue", sender:self)
progress.hidden = true
self.countLabel.hidden = true
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
let controller : SearchViewController = segue.destinationViewController as! SearchViewController
if segue.identifier == "segue"{
controller.model = movies
}
}
}
Do following:-
extension UIViewController {
func addSearchController() {
let searchController = UISearchController(searchResultsController: nil)
self.view.addSubview(searchController.searchBar)
}
}
Just call self.addSearchController() method in viewDidLoad method of required VC. No need to pass SearchController.

Memory usage increases with every segue to modal vc

I have two view controllers, one is the timeline the second one is for the creation. In that second view controller I have a sub view. This sub view is an SKView. Now every time I segue to it, it increases the memory usage by 2mb (on a real device), but the memory usage stays the same when I unwind it.
So it is like this: I start with a usage of 12mb, then it gets 14-15mb. After the unwind it stays around 14-15mb. After the second segue to it, it becomes 17mb... and so on.
This is the code used in the timeline controller:
#IBAction func createButtonAct(sender: AnyObject) {
self.performSegueWithIdentifier("create", sender: self)
}
#IBAction func unwindFromCreation(segue: UIStoryboardSegue) {
}
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "create"{
let vc = segue.destinationViewController as! CreateViewController
if vc.currCountry == nil || vc.currCountry != self.currCountry{
vc.currCountry = self.currCountry
}
}
}
And this is the code in the create View Controller:
class CreateViewController: UIViewController, UITextViewDelegate {
#IBOutlet weak var bubbleView: SKView!
#IBOutlet var arrow: UIButton!
var ref: Firebase!
let categories = CatsAndColors.categories
#IBOutlet var doneButton: UIButton!
#IBOutlet var titleField: UITextField!
#IBOutlet var descriptionView: KMPlaceholderTextView!
var choosedCat: String!
var selectedCats: NSMutableArray!
var currCountry:String!
var tap: UITapGestureRecognizer!
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
UIApplication.sharedApplication().statusBarStyle = .Default
UIView.animateWithDuration(0.5, animations: { () -> Void in
self.arrow.transform = CGAffineTransformMakeRotation(3.14159)
})
titleField.addTarget(self, action: "textFieldDidChange:", forControlEvents: UIControlEvents.EditingChanged)
titleField.addTarget(self, action: "textFieldDidBegin:", forControlEvents: UIControlEvents.EditingDidBegin)
titleField.addTarget(self, action: "textFieldDidEnd:", forControlEvents: UIControlEvents.EditingDidEnd)
// the targets get removed in viewWillDisappear
selectedCats = NSMutableArray()
}
override func viewDidLoad() {
super.viewDidLoad()
ref = Firebase(url: "https://blabber2.firebaseio.com")
self.doneButton.enabled = false
doneButton.setBackgroundImage(UIImage(named: "Done button inactive"), forState: .Disabled)
doneButton.setTitleColor(UIColor(netHex: 0xF6F6F6), forState: .Disabled)
doneButton.setTitleColor(UIColor.whiteColor(), forState: .Normal)
self.setupBubbles()
self.descriptionView.delegate = self
}
func setupBubbles(){
let floatingCollectionScene = ChooseBubblesScene(size: bubbleView.bounds.size)
// floatingCollectionScene.scaleMode = .AspectFit
/*let statusBarHeight = CGRectGetHeight(UIApplication.sharedApplication().statusBarFrame)
let titleLabelHeight = CGRectGetHeight(self.tibleLabel.frame)*/
bubbleView.presentScene(floatingCollectionScene)
for (category, color) in categories {
let node = ChooseBubbleNode.instantiate()
node!.vc = self
node!.fillColor = SKColor(netHex: color)
node!.strokeColor = SKColor(netHex: color)
node!.labelNode.text = category
floatingCollectionScene.addChild(node!)
}
}
...
And the catsAndColors struct looks like this:
struct CatsAndColors{
static var categories = ["Crime":0x5F5068, "Travel":0xFBCB43, "Religion":0xE55555, "Tech":0xAF3151, "Economy":0x955BA5, "Games":0xE76851, "Climate":0x6ED79A, "Books":0xE54242, "History":0x287572, "Clothes":0x515151, "Sports":0x4AB3A7, "Food":0xD87171, "Politics":0x5FA6D6, "Music":0xDD2E63, "Tv-shows":0x77A7FB]
}
Maybe you have created some sort of retain cycle between your view controllers.
If both view controllers hold a reference to each other, then try declaring one of the references as weak.
For more information on the topic read Resolving Strong Reference Cycles Between Class Instances.
I solved the problem, it was strong reference in the sknode file.
Thank you for your answers.

Resources