I have been working through a large project recently, with a lot of different views. I ran into some rather large memory leaks, and had to dig for some answers. I did not see any general category on the subject, and wanted to put down some ideas. I apologize if these are obvious.
Whenever possible create pointers inside routines or in the @Interface portion. They should never be declared in the @Implementation area. Declarations in @Implementation are not deallocated when the view goes away. While not global, they also exist beyond the life of the view.
Images.xcassets should only be used for very small images. It appears images located here, are loaded when used, but remain in memory for the life of the app. I had some screen sized images identified here, and once used, they stayed in memory. For larger images, add the PNG file to the Supporting Files area, and load it into a UIImage. Much lower memory use to start, and once loaded into the view, the UIImage pointer can be set to nil.
Timers must be invalidated and any pointers set to nil or the view will not deallocate and all memory associated with the view will stay resident. (this is documented well on the site)
Model segue and Unwinds work pretty well, assuming the above is handled well. If memory is not freed on unwind from a view, look for a pointer still referencing a part of the view or structure in the view.
Be mindful of item 1 if using the SKScene as constructed by XCode for a new game project. The 'scene' variable is declared in the @Implementation section of the GameViewController. If you run this as a recurring view, you will lose about 10 MB per load of the view.
Watch the size of your images. I had a couple images that were 3500x3100, which is much larger than needed for the screen. Make sure your image sizes match the intended screen sizes and no larger. You will need to load the image and place it on the screen, so in some areas the OS will have a few copies of the image at the same time, in order to display it.
From my main view, I had pointers to the sub views defined in @Interface. This also was not good. Those pointers stick around, so the sub views would not deallocate when not in use. It is cleaner to keep it very local to the prepareForSegue routine, but if you do need them later, make sure to set them to nil, when you are done with the view.
Again, I apologize for the obvious, but it helps me to get this all in one location. There are a lot of tools available for watching memory, such as instruments, but the easiest to watch is just the memory level in debug. Existing a sub view should get you back to the same level as you went in. If you gain every time you open a sub view, look for a pointer that remains active.