2016-08-04 102 views
0

我正在设计一个应用程序,它具有让用户添加自己的pin的功能。最近,我发现我的应用程序存在内存泄漏,标题为“连续阵列存储”。我调试了一下,发现这是我的viewdidload中for循环的问题,但我不知道如何修复泄漏。 这里是我的代码:由于连续阵列存储在Swift应用程序中的内存泄漏

@IBOutlet weak var AppleMap: MKMapView! 

@IBOutlet weak var LogoutOutlet: UIButton! 

@IBOutlet weak var OutletforAddPokemon: UIButton! 

@IBOutlet weak var FindLocationOutlet: UIButton! 

@IBOutlet weak var FilterOutlet: UIButton! 

let locationManager = CLLocationManager() 
let calendar: NSCalendar! = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian) 

var increment:Int = 0 
var currentLoc:CLLocationCoordinate2D? 
var centerMap = true 
let StoringPin = FIRDatabase.database().reference().child("locations") 

var Date = NSDate() 

override func viewDidLoad() { 
    super.viewDidLoad() 

    AppleMap.delegate = self 


    StoringPin.observeEventType(.Value, withBlock: { 
     snapshot in 
     if snapshot.value is NSNull { 
      return 
     } 
     let val = snapshot.value as! [String : [String : AnyObject]] 



     for key in val.keys { 

      let latitudedata = val[key]!["latitude"] as! Double 
      let longitudedata = val[key]!["longitude"] as! Double 
      let namedata = val[key]!["name"] as! String 
      let Username = val[key]!["Username"] 
       as! String 

      let DATE = val[key]!["Date"] 
       as! String 

      let NumberOflikesforuser = val[key]!["Likes"] as! Int 


      let NumberOfDislikesforuser = val[key]!["Dislikes"] as! Int 

      let coord = CLLocationCoordinate2D(latitude: latitudedata, longitude: longitudedata) 

      let artwork = Capital(title: "\(namedata)", coordinate: coord, info: "HI", username: Username, NumofLikes: NumberOflikesforuser,NumofDisLikes: NumberOfDislikesforuser, UIDSTring: UID, date: DATE, color: MKPinAnnotationColor.Green) 
      artwork.subtitle = DATE 

      print("k") 





      let permastringforemail:String = Username 

      print(++self.increment) 
      print(UID) 
      print(permastringforemail) 

      stringforemail = permastringforemail 

      Arrayforpins.append(artwork) 

      self.AppleMap.addAnnotation(Arrayforpins[Arrayforpins.count - 1]) 






      for Capital in Arrayforpins { 
       self.AppleMap.addAnnotation(Capital) 


      } 


     } 


    }) 







    print(LogoutOutlet) 
    LogoutOutlet.layer.cornerRadius = 4 

    FindLocationOutlet.layer.cornerRadius = 4 
    OutletforAddPokemon.layer.cornerRadius = 4 
    //FilterOutlet.layer.cornerRadius = 4 

    self.locationManager.requestAlwaysAuthorization() 
    self.locationManager.requestWhenInUseAuthorization() 

    if CLLocationManager.locationServicesEnabled() { 
     locationManager.delegate = self 
     locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters 
     locationManager.startUpdatingLocation() 
    } 


    let annotationView = MKAnnotationView() 
    let detailButton: UIButton = UIButton.init(type: .DetailDisclosure) as UIButton 
    annotationView.rightCalloutAccessoryView = detailButton 



} 
let regionRadius: CLLocationDistance = 1000 



func centerMapOnLocation(location: CLLocation) { 
    let coordinateRegion = MKCoordinateRegionMakeWithDistance(location.coordinate, 
                   regionRadius * 2.0, regionRadius * 2.0) 
    AppleMap.setRegion(coordinateRegion, animated: true) 
} 

override func didReceiveMemoryWarning() { 
    super.didReceiveMemoryWarning() 
    // Dispose of any resources that can be recreated. 
} 


func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { 
    let locValue:CLLocationCoordinate2D = manager.location!.coordinate 

    if CLLocationManager.authorizationStatus() == .AuthorizedWhenInUse { 
     AppleMap.showsUserLocation = true 
    } else { 
     locationManager.requestWhenInUseAuthorization() 
    } 

    print("update") 

    currentLoc = locValue 

    if centerMap { 
     centerMap = false 
     centerMapOnLocation(CLLocation(latitude: currentLoc!.latitude, longitude: currentLoc!.longitude)) 
    } 

} 


@IBAction func SendtoSelector(sender: AnyObject) { 

    self.performSegueWithIdentifier("SeguetoSelector", sender: self) 

} 


@IBAction func FilterFunc(sender: AnyObject) { 
    self.performSegueWithIdentifier("SeguetoFilter", sender: self) 
} 


@IBAction func FindLocation(sender: AnyObject) { 
    centerMapOnLocation(CLLocation(latitude: currentLoc!.latitude, longitude: currentLoc!.longitude)) 


} 

@IBAction func Logout(sender: AnyObject) { 
    LO = true 
    self.performSegueWithIdentifier("BacktoLoginScreen", sender: self) 
} 



override func viewDidAppear(animated: Bool) { 
    super.viewDidAppear(animated) 
    locationManager 
    if IndexBoolean == true{ 
     //let annotationView = MKPinAnnotationView() 
     print("Hi") 
     let artwork = Capital(title: "\(pickerDataSource[chosenindex])", coordinate: CLLocationCoordinate2D(latitude: currentLoc!.latitude, longitude: currentLoc!.longitude), info: "HEY", username: stringforemail, NumofLikes: NumberOfLikes, NumofDisLikes: NumberOfDislike, UIDSTring: UID, date: stringfordate2, color: MKPinAnnotationColor.Green) 

     //print(now) 
     print(chosenindex) 
     artwork.title = "\(pickerDataSource[chosenindex])" 
     //artwork.subtitle = stringfordate 
     AppleMap.addAnnotation(artwork) 
     //annotationView.pinColor = artwork.Green 

      Arrayforpins.append(artwork) 
     print(stringforemail) 


    AppleMap.addAnnotation(Arrayforpins[Arrayforpins.count - 1]) 

     for Capital in Arrayforpins{ 
     AppleMap.addAnnotation(Capital) 

     } 
     IndexBoolean = false 

     var formatter = NSDateFormatter() 
     formatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ" 
     formatter.timeZone = NSTimeZone(abbreviation: "Central Time") 
     var utcTimeZoneSTR = formatter.stringFromDate(Date) 


     stringfordate = "\(utcTimeZoneSTR)" 

     let uid = NSUUID().UUIDString 
     UID = uid 
     StoringPin.child(uid).setValue(["name" : pickerDataSource[chosenindex], 
      "latitude" : currentLoc!.latitude, 
      "longitude" : currentLoc!.longitude,"Array Position" : chosenindex,"Username": stringforemail, "Likes": NumberOfLikes2, "Dislikes": 
      NumberOfDislike, "UID": UID, "Date": stringfordate]) 


     if FilterBoolean == true { 
      print("b") 
      if FilterDataSource[Intforfilter] != stringforname { 
       print("k") 
       //self.AppleMap.viewForAnnotation(artwork)?.hidden = true 
       FilterBoolean == false 

      } 

      //else { 
      //     print("m") 
      //     self.AppleMap.removeAnnotation(artwork) 
      // 
      //    } 

      FilterBoolean == false 

     } 


    } 

} 

func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? { 

    let identifier = "Capital" 
    print(++increment) 

    if annotation.isKindOfClass(Capital.self) { 
     print("CAPITAL") 
     if let annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier) { 
      annotationView.annotation = annotation 
      return annotationView 
     } else { 
      let annotationView = MKPinAnnotationView(annotation:annotation, reuseIdentifier:identifier) 
      annotationView.enabled = true 
      annotationView.canShowCallout = true 
      //annotationView.pinColor = MKPinAnnotationColor.Green 
      let btn = UIButton(type: .DetailDisclosure) 

      annotationView.rightCalloutAccessoryView = btn 
      return annotationView 
     } 
    } 

    return nil 
} 

func mapView(mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) { 
    let capital = view.annotation as! Capital 
    let placeName = capital.title 
    let placeInfo = capital.info 
    let UserName = capital.username 

    stringforname = view.annotation!.title!! 
    coords = view.annotation!.coordinate 
    stringforemail = capital.username 
    stringfordate2 = capital.date 

    NumberOfLikes2 = capital.NumofLikes 

    UID = capital.UIDSTring 

    print(stringforname) 
    print(UID) 

    self.performSegueWithIdentifier("SegueToInfo", sender: self) 



} 

回答

0

我注意到你没有照顾到指定如何捕获你的闭合self。当处于一次性对象上下文(一个UIViewController)和一个异步封闭时,您总是需要担心这一点。您需要将其捕获为weakunowned。你熟悉闭包捕获列表吗?

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html#//apple_ref/doc/uid/TP40014097-CH20-ID56

我使用的图案是捕获self弱然后保释如果self已成为零,例如UIViewController已被解雇和收获。如果它仍在附近,我会用guard...let声明中的局部变量强烈地捕获它。

withBlock: { [weak self] (snapshot) in 
    guard let s = self else { 
     print("Callback called after view unloaded") 
     return 
    } 
    // now use 's' instead of 'self' 
    ... 
} 

不能说这是唯一的问题,因为我们没有你的助手类的声明。例如,我们不知道什么是恶作剧Capital

顺便说一句,只要清楚,你的for循环确实不是viewDidLoad()运行。您只注册一个回调,该回调仅在StoringPin对象上发生.Value事件时发生反应。