Я имею дело с приложением, созданным другим разработчиком.Это законченное приложение, в котором есть много viewControllers, переменных и выходов.
Я получаю сбой после того, как загружаю слишком много изображений с сервера (например, 200).Я получаю только это сообщение в «области печати»: «Приложение закрыто из-за проблемы с памятью».
Я использую библиотеку "SDWebImage" для загрузки изображений.И я попытался найти утечку памяти, используя Распределение инструментов и Утечки.Я также использовал Memory Graph Debugger, и ни один из них не показывает утечки в моем приложении.
Тем не менее, когда я открываю View Controller (DetailVC), он никогда не запускает метод deinit, где я помещаю сообщение для печати, когда это происходит..
Я много искал, чтобы не пропасть.Я смотрел на них в Stackoverflow:
Расширение приложения "Завершено из-за проблемы с памятью"
Приложение завершено из-за проблемы с памятью
В ходе моего поиска я неоднократно получал ответ, что на контроллер представления должен ссылаться другой контроллер представления, а этот контроллер представления (DetailVC) строго ссылается на другой.
Я не мог найти это какслучай, хотя файл для контроллера представления слишком велик, и я, возможно, пропустил вещи.
Трудно пройти приложение и найти сильные и слабые ссылки, так как файл действительно огромен.
существует простой способ (или трудный в этом отношении) найти виновника ирешить мою проблему.
Спасибо
код огромен (95000 символов) и содержит конфиденциальную информацию, поэтому размещать его здесь неуместно.хотя я могу опубликовать его часть, если вы попросите об этом.
вот код для DetailVC viewDidLoad:
import UIKit
import FTIndicator
import Cosmos
import Firebase
import MapKit
import YouTubePlayer
//MARK:- Gallery Collection Cell
class GalleryCollectionCell:UICollectionViewCell
{
@IBOutlet weak var imgViewShop: UIImageView!
override func awakeFromNib()
{
super.awakeFromNib()
}
}
//MARK:- Service Collection Cell
class ServiceCollectionCell:UICollectionViewCell
{
@IBOutlet weak var imgViewService: UIImageView!
@IBOutlet weak var lblService: UILabel!
override func awakeFromNib()
{
super.awakeFromNib()
}
}
@IBAction func btnBackAction(_ sender: Any)
{
self.navigationController?.popViewController(animated: true)
SDImageCache.shared().clearMemory()
SDImageCache.shared().clearDisk()
}
//MARK:- Detail Main Class
class DetailVC: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout,UITableViewDataSource, UITableViewDelegate,RateFinalDelegate, PhotoDicDelegate
{
//MARK:- Outlets
@IBOutlet weak var tblViewRate: UITableView!
@IBOutlet weak var tblViewService: UITableView!
@IBOutlet weak var lblServices: UILabel!
@IBOutlet weak var collViewGallery: UICollectionView!
//@IBOutlet weak var collViewService: UICollectionView!
@IBOutlet weak var constTableViewHeight: NSLayoutConstraint!
@IBOutlet weak var constTlbViewServiceHeight: NSLayoutConstraint!
@IBOutlet weak var imgViewShop: UIImageView!
@IBOutlet weak var lblShopName: UILabel!
//@IBOutlet weak var lblShopNameDetail: UILabel!
@IBOutlet weak var btnFavourites: UIButton!
@IBOutlet weak var viewStar: CosmosView!
@IBOutlet weak var lblReviewCount: UILabel!
@IBOutlet weak var btnShopStatus: UIButton!
@IBOutlet weak var lblShopOnline: UILabel!
// @IBOutlet weak var lblDetailText: UILabel!
@IBOutlet weak var btnShopRate: UIButton!
@IBOutlet weak var lblShopAddress: UILabel!
@IBOutlet weak var lblShopWebsite: UILabel!
@IBOutlet weak var lblShopView: UILabel!
@IBOutlet weak var lblShopOpenStatus: UILabel!
//@IBOutlet weak var lblPhone1: UILabel!
@IBOutlet weak var lblShopDetail: UILabel!
// @IBOutlet weak var btnFacebook: UIButton!
// @IBOutlet weak var btnSnapchat: UIButton!
// @IBOutlet weak var btnInstagram: UIButton!
// @IBOutlet weak var btnTwitter: UIButton!
// @IBOutlet weak var btnYoutube: UIButton!
// @IBOutlet weak var btnVivo: UIButton!
// @IBOutlet weak var btnGoogle: UIButton!
@IBOutlet weak var lblSat: UILabel!
@IBOutlet weak var lblSun: UILabel!
@IBOutlet weak var lblMon: UILabel!
@IBOutlet weak var lblTues: UILabel!
@IBOutlet weak var lblWed: UILabel!
@IBOutlet weak var lblThru: UILabel!
@IBOutlet weak var lblFri: UILabel!
@IBOutlet weak var lblSatText: UILabel!
@IBOutlet weak var lblSunText: UILabel!
@IBOutlet weak var lblMonText: UILabel!
@IBOutlet weak var lblTuesText: UILabel!
@IBOutlet weak var lblWedText: UILabel!
@IBOutlet weak var lblThruText: UILabel!
@IBOutlet weak var lblFriText: UILabel!
@IBOutlet weak var lblworkingHour: UILabel!
@IBOutlet weak var lblGallery: UILabel!
@IBOutlet weak var lblReviews: UILabel!
@IBOutlet weak var btnSeeMore: UIButton!
@IBOutlet weak var btnBack: UIButton!
@IBOutlet weak var viewMain: UIView!
@IBOutlet weak var viewSuper: UIView!
@IBOutlet weak var viewService: UIView!
@IBOutlet weak var btnWebsite: UIButton!
@IBOutlet weak var btnPhone1: UIButton!
@IBOutlet weak var btnPhone2: UIButton!
@IBOutlet weak var btnPhone3: UIButton!
@IBOutlet weak var constPhone1Height: NSLayoutConstraint!
@IBOutlet weak var constPhone2Height: NSLayoutConstraint!
@IBOutlet weak var constPhone3Height: NSLayoutConstraint!
@IBOutlet weak var constPhoneViewHeight: NSLayoutConstraint!
@IBOutlet weak var constViewScrollHeight: NSLayoutConstraint!
@IBOutlet weak var scrollSocial: UIScrollView!
// @IBOutlet weak var btnSocialLink: UIButton!
@IBOutlet weak var btnGallery: UIButton!
@IBOutlet weak var constViewServiceHeight: NSLayoutConstraint!
//For Photo Class
@IBOutlet weak var tblViewHeader: UITableView!
@IBOutlet weak var switchGallery: UISwitch!
@IBOutlet weak var constTableViewGalleryHeight: NSLayoutConstraint!
var albumListArray = [AlbumListData]()
//For Video Class
@IBOutlet weak var collectionViewVideos: UICollectionView!
@IBOutlet weak var constCollViewVideoHeight: NSLayoutConstraint!
var videoDataArray = [VideoListData]()
var switchStatus = Bool()
//MARK:- Variables
let globalConstants = GlobalConstants()
var UserData = UserDataValue()
var reviewDataArray = [Review]()
var galleryDataArray = [Gallery]()
var serviceDataArray = [Service]()
var ShopId = String()
var favStatus = String()
var ShopStatus = String()
var Latitude = String()
var Longitude = String()
var strFacebook = String()
var strInstagram = String()
var NotifyId = String()
var strTwitter = String()
var strSnapchat = String()
var strYoutube = String()
var strGoogle = String()
var strVimeo = String()
var chatStatus = Bool()
var isfirstTime = Bool()
var receiverId = ""
var receiverImage = ""
var receiverName = ""
var strWebsite = ""
var shopOwnerId = ""
var ShopUnqueId = ""
var HideChatStatus = ""
var IsChatCreateScreen = ""
var strPhone1Number = String()
var strPhone2Number = String()
var strPhone3Number = String()
var RateText = Bool()
var ShopDeliveryServiceItself = Bool()
var CitySelectedId = String()
var OneToOneChatUserData : NSDictionary = [:]
var ShopString = "1159,1160,1162,1166,1167,1176,1178,1179,1180,1182,1184,1185,1186,1187,1188,1189,1190,1191,1192,1193,1194,1199,1202,1203,1206,1208,1209,1210,1214,1216,1217,1218,1224,1225,1227,1230,1232,1233,1234,1235,1236,1238,1239,1240,1242,1243,1244,1245,1246,1247,1248,1250,1252,1253,1255,1258,1259,1263,1264,1265,1266,1269,1270,1272,1275,1276,1277,1278,1279,1280,1281,1282,1283,1285,1298,1299,1302";
//MARK:- View Life Cycle
override func viewDidLoad()
{
super.viewDidLoad()
// collViewGallery.dataSource = self
// collViewGallery.delegate = self
// collViewService.dataSource = self
// collViewService.delegate = self
btnShopStatus.setTitle(" CHAT".localiz(), for: .normal)
btnSeeMore.setTitle("See More".localiz(), for: .normal)
btnShopRate.setTitle("RATE".localiz(), for: .normal)
btnGallery.setTitle("Gallery".localiz(), for: .normal)
lblworkingHour.text = "Working Hours:".localiz()
lblServices.text = "Services".localiz()
lblGallery.text = "Gallery".localiz()
lblReviews.text = "REVIEWS".localiz()
//lblDetailText.text = "DETAILS".localiz()
lblSatText.text = "Saturday".localiz()
lblSunText.text = "Sunday".localiz()
lblMonText.text = "Monday".localiz()
lblTuesText.text = "Tuesday".localiz()
lblWedText.text = "Wednesday".localiz()
lblThruText.text = "Thursday".localiz()
lblFriText.text = "Friday".localiz()
viewStar.settings.fillMode = .precise
self.navigationItem.title = globalConstants.detailText
tblViewRate.register(UINib(nibName: "RateTableVCell", bundle: nil), forCellReuseIdentifier: "RateTableVCell")
tblViewService.register(UINib(nibName: "ServiceTableCell", bundle: nil), forCellReuseIdentifier: "ServiceTableCell")
tblViewHeader.register(UINib(nibName: "SubCatHeaderTVC", bundle: nil), forCellReuseIdentifier: "SubCatHeaderTVC")
tblViewHeader.dataSource = self
tblViewHeader.delegate = self
tblViewHeader.estimatedRowHeight = 120
tblViewHeader.rowHeight = UITableViewAutomaticDimension
tblViewService.dataSource = self
tblViewService.delegate = self
tblViewService.estimatedRowHeight = 50
tblViewService.rowHeight = UITableViewAutomaticDimension
self.constTlbViewServiceHeight.constant = 20
collectionViewVideos.register(UINib(nibName: "VideoCollViewCell", bundle: nil), forCellWithReuseIdentifier: "VideoCollViewCell")
collectionViewVideos.dataSource = self
collectionViewVideos.delegate = self
collectionViewVideos.reloadData()
switchStatus = false
switchGallery.setOn(false, animated: true)
//self.constViewServiceHeight.constant = 20
tblViewRate.dataSource = self
tblViewRate.delegate = self
tblViewRate.estimatedRowHeight = 100
tblViewRate.rowHeight = UITableViewAutomaticDimension
//self.constTableViewGalleryHeight.constant = 20
self.constTableViewHeight.constant = 20
// self.tblViewHeader.isHidden = false
// self.collectionViewVideos.isHidden = true
// self.constCollectionViewHeight.constant = 30
ShopStatus = ""
self.addBackButton()
UserDefaults.standard.set(ShopId, forKey: "ShopValueId")
UserDefaults.standard.synchronize()
isfirstTime = true
viewSuper.backgroundColor = UIColor.lightGray
viewMain.isHidden = true
if LanguageManger.shared.currentLanguage == .en
{
lblServices.textAlignment = .left
btnBack.setImage(UIImage(named:"back"), for: .normal)
}
else
{
lblServices.textAlignment = .right
btnBack.setImage(UIImage(named:"ReverseBack"), for: .normal)
}
// if KAppDelegate.isUserLoggedIn()
// {
// let userDic = UserDefaults.standard.value(forKey: "UserData") as! [String:Any]
// self.UserData = UserDataValue.init(fromDictionary: userDic)
// UserId = self.UserData.id!
// UserName = self.UserData.name!
// }
if KAppDelegate.isUserLoggedIn()
{
let userDic = UserDefaults.standard.value(forKey: "UserData") as! [String:Any]
self.UserData = UserDataValue.init(fromDictionary: userDic)
CitySelectedId = self.UserData.city!
}
else
{
if UserDefaults.standard.value(forKey: "CitySelectedId") != nil
{
CitySelectedId = UserDefaults.standard.value(forKey: "CitySelectedId") as! String
}
else
{
CitySelectedId = "1"
}
}
ShopDetailAPIMethod()
}
override func viewWillAppear(_ animated: Bool)
{
self.navigationController?.navigationBar.isHidden = true
}
override func viewWillDisappear(_ animated: Bool)
{
self.IsChatCreateScreen = ""
self.navigationController?.navigationBar.isHidden = false
}
// override var preferredStatusBarStyle: UIStatusBarStyle
// {
// return .default
// }
//MARK:- Photo Dic Delegate Method
//MARK:- CreateNewChat Method
}
и вот как создается экземпляр DetailVC:
@objc func methodOfNotification(notification: Notification)
{
if UserDefaults.standard.value(forKey: "ShopValueId") != nil
{
let detailVC = self.storyboard?.instantiateViewController(withIdentifier: "DetailVC") as! DetailVC
detailVC.ShopId = UserDefaults.standard.value(forKey: "ShopValueId") as! String
self.navigationController?.pushViewController(detailVC, animated: true)
}
}
Вот сценарий:
Я нахожусь в subCategoryVC Я нажимаю на ячейку collectionView, это создает экземпляр DetailVC.в DetailVC я нажимаю кнопку seeAll, чтобы загрузить изображения в виде коллекции (это делается с помощью SDWebImage, используя этот метод:
l
let imageStringURL = ShopDetailData.coverImage!
imgViewShop.sd_setShowActivityIndicatorView(true)
imgViewShop.sd_setIndicatorStyle(.gray)
imgViewShop.sd_setImage(with: NSURL(string:imageStringURL)! as URL, placeholderImage:UIImage(named:"noimage") , options: .refreshCached, completed: nil)
, когда я нажимаю на btnBack (кнопка «Назад»), и я выдвигаю контроллер вида, используя navigationContrller.popViewController()
, именно здесь сообщение «deinit» должно быть напечатано в «области печати», но этого не происходит.кнопка seeAll, приложение вылетает, и в «области печати» отображается
«приложение прервано из-за проблемы с памятью».
Я просто использовал инструменты для проверки утечки памяти.одна утечка, как выясняется, и с этими деталями:
утечка объекта = _swiftStringStorage<UInt16>
ответственная библиотека = libswiftCore.dylib
ответственный кадр = swift_slowAlloc