メモリリークを解消した時など少しずつsampleを書いて行こうという感じのものです。
ちなみに、書いている本人としてリークがあるコードを否定したい訳ではないです(。・ω・。)
大量になればなるほどや、色々な原因でリークは発生するし、リークでもこれは別にいいんじゃないのとかもあると思うので、ただ、もしこのリーク無くしたらみたいなことがある時の参考になれば嬉しいと書いています。
ちなみに、判断はxcodeのinstrumentsでの判断結果です。
ちなみにinstrumentsでのチェックは直したコードを一回ビルドしてからあの赤いポチョを押さないと前の残っていたものでチェックされてしまいます。
リーク発生code
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
weak var nc: UINavigationController?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
nc = UINavigationController(rootViewController: firstViewController())
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = nc
return true
}
リーク解消code
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
weak var nc: UINavigationController?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
nc = UINavigationController(rootViewController: firstViewController())
self.window?.rootViewController = nc
return true
}
補足:windowをインスタンス化したことによりこれが残ってしまいメモリリークとなっていたっぽい?
リーク発生code
override func viewDidLoad() {
super.viewDidLoad()
sampleImageView.frame = self.view.frame
let imgURL = URL(string: "https://www.???.jpg")!
let session = URLSession(configuration: .default)
let download = session.dataTask(with: imgURL) { (data, response, error) in
if (response as? HTTPURLResponse) != nil{
if let imageData = data {
DispatchQueue.main.async {
let imageimage = UIImage(data: imageData)
self.sampleImageView.image = imageimage
}
}
}
}
download.resume()
self.view.addSubview(self.sampleImageView)
リーク解消code
var sampleImageView = UIImageView()
override func viewDidLoad() {
super.viewDidLoad()
sampleImageView.frame = self.view.frame
let imgURL = URL(string: "https://www.???.jpg")!
let session = URLSession(configuration: .default)
let download = session.dataTask(with: imgURL) { (data, response, error) in
if (response as? HTTPURLResponse) != nil{
if let imageData = data {
DispatchQueue.main.async {
let imageimage = UIImage(data: imageData)
self.sampleImageView.image = imageimage
}
}
}
}
session.invalidateAndCancel()
download.resume()
self.view.addSubview(self.sampleImageView)
補足:session.invalidateAndCancel()があるかないかなのですが、場所はここが適切かはちょっとわかっていないです。
リーク発生(画面を閉じる際にdeinitが呼ばれない。 XcodeのInstrumentsでもリークが発生)
動作としては以下のようなもの(モーダルで遷移、Button押した時にはログが出ます。)
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
@IBAction func gosampleViewController(_ sender: UIButton) {
self.present(sampleViewController(), animated: true, completion: nil)
}
}
import UIKit
class sampleViewController: UIViewController {
var sample:sampleclass!
override func viewDidLoad() {
super.viewDidLoad()
sample = sampleclass()
sample.action = {
self.log()
}
}
deinit {
print("sampleViewController deinit")
}
func log(){
print("ボタンが押されました。")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
@IBAction func tap(_ sender: Any) {
sample.action!()
}
@IBAction func back(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
}
}
import UIKit
class sampleclass: NSObject {
var action:(()->())?
}
リーク解消
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
@IBAction func gosampleViewController(_ sender: UIButton) {
self.present(sampleViewController(), animated: true, completion: nil)
}
}
import UIKit
class sampleViewController: UIViewController, sampleprotocol{
var sample:sampleclass!
override func viewDidLoad() {
super.viewDidLoad()
sample = sampleclass()
sample.delegate = self
}
deinit {
print("sampleViewController deinit")
}
func log(){
print("ボタンが押されました。")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
@IBAction func tap(_ sender: Any) {
sample.delegate?.action()
}
@IBAction func back(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
}
//sampledelegate
func action() {
self.log()
}
}
import UIKit
protocol sampleprotocol:class{
func action()
}
class sampleclass: NSObject {
weak var delegate:sampleprotocol?
}
補足:
sample.action = {
self.log()
}
の部分がリークの原因でした。
コードまだ書いていないけどこう言う時あるよ的なもの以下
・protocole使っている時!使う型がわからないとなるので,以下のようにclassですよを指定していないとほぼリーくする気がしています。ちなみに宣言する時はvar でなく weak var にしないとリークします。
protocol sample:class{
func a()
}