2015-08-30 12 views
7

Khi tôi xoay ứng dụng hai lần sau khi chọn một vài mục, sự cố đó sẽ bị treo. Tôi đã ghi đè phương thức sendEvent và đó là nơi trình gỡ lỗi dừng lại. Khi tôi cố gắng in loại sự kiện, nó cho tôi thấy một cái gì đó kỳ lạ (Tôi nghĩ rằng đó là một vị trí bộ nhớ không tồn tại):Lỗi ứng dụng trên phương thức sendEvent

Bằng cách nào đó tôi nghĩ điều này liên quan đến cách tôi xoay vòng. Tôi có một ứng dụng kiểu chi tiết chính, sử dụng một loại điều hướng khác cho pad-landscape, pad-portrait và phone. Tôi đã tạo một lớp có tên là NavigationFlowController xử lý tất cả các sự kiện điều hướng và thiết lập các chế độ xem cho phù hợp. Mở quay, nó sẽ vỡ ra cây xem và recomposes chúng với điều hướng đúng

func changeViewHierarchyForDevideAndOrientation(newOrientation:UIInterfaceOrientation? = nil){ 
    print("MA - Calling master layout method") 

    UIApplication.myDelegate().window?.frame = UIScreen.mainScreen().bounds 

    let idiom = UIDevice.currentDevice().userInterfaceIdiom 
    var orientation:UIInterfaceOrientation! 
    if let no = newOrientation{ 
     orientation = no 
    }else{ 
     orientation = UIApplication.sharedApplication().statusBarOrientation 
    } 

    print("MA - Breaking up view tree...") 

    breakupFormerViewTree([sidebarViewController, listViewController, detailViewController, loginViewController]) 

    print("MA - Start init navbackbone") 

    initNavBackboneControllers() 

    guard let _ = UIApplication.myDelegate().currentUser else { 
     if idiom == UIUserInterfaceIdiom.Phone{ 
      currentState = AppState.PHONE 
     }else if idiom == UIUserInterfaceIdiom.Pad && UIInterfaceOrientationIsLandscape(orientation){ 
      currentState = AppState.PAD_LANDSCAPE 
     }else if idiom == UIUserInterfaceIdiom.Pad && UIInterfaceOrientationIsPortrait(orientation){ 
      currentState = AppState.PAD_PORTRAIT 
     } 

     print("MA - Current user is nil - resetting") 

     mainViewController.addChildViewController(loginViewController) 

     return 
    } 

    if idiom == UIUserInterfaceIdiom.Phone{ 
     currentState = AppState.PHONE 

     leftNavigationController?.viewControllers = [listViewController] 

     slideViewController?.rearViewController = sidebarViewController 
     slideViewController?.frontViewController = leftNavigationController 

     slideViewController?.rearViewRevealWidth = 267; 

     mainViewController.addChildViewController(slideViewController!) 
    }else if idiom == UIUserInterfaceIdiom.Pad && UIInterfaceOrientationIsLandscape(orientation){ 
     currentState = AppState.PAD_LANDSCAPE 

     leftNavigationController!.viewControllers = [sidebarViewController, listViewController] 
     rightNavigationController!.viewControllers = [detailViewController] 
     detailViewController.navigationItem.leftBarButtonItems = [] 
     detailViewController.initLayout() 

     print("MA - Init split view controller with VCs") 

     splitViewController!.viewControllers = [leftNavigationController!, rightNavigationController!] 

     mainViewController.addChildViewController(splitViewController!) 

    }else if idiom == UIUserInterfaceIdiom.Pad && UIInterfaceOrientationIsPortrait(orientation){ 
     currentState = AppState.PAD_PORTRAIT 

     leftNavigationController!.pushViewController(sidebarViewController, animated: false) 
     leftNavigationController!.pushViewController(listViewController, animated: false) 

     rightNavigationController!.pushViewController(detailViewController, animated: false) 
     rightNavigationController?.setNavigationBarHidden(false, animated: false) 

     slideViewController!.rearViewController = leftNavigationController 
     slideViewController!.frontViewController = rightNavigationController 

     detailViewController.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "< Documenten", style: UIBarButtonItemStyle.Bordered, target: slideViewController, action: "revealToggle:") 
     detailViewController.initLayout() 
     slideViewController!.rearViewRevealWidth = 350; 

     mainViewController.addChildViewController(slideViewController!) 
    } 

} 

func breakupFormerViewTree(vcs:[UIViewController?]){ 
    for vc in vcs{ 
     if let vcUnwrapped = vc, _ = vcUnwrapped.parentViewController { 
      vcUnwrapped.removeFromParentViewController() 
      vcUnwrapped.view.removeFromSuperview() 
     } 
    } 
} 

func initNavBackboneControllers(){ 
    leftNavigationController = UINavigationController() 
    leftNavigationController?.navigationBar.barTintColor = UIColor(red: 0.25, green: 0.25, blue: 0.25, alpha: 1.0) 
    leftNavigationController?.navigationBar.tintColor = UIColor.whiteColor() 
    leftNavigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.whiteColor()] 
    leftNavigationController?.navigationBar.translucent = false 

    rightNavigationController = UINavigationController() 
    rightNavigationController?.navigationBar.barTintColor = UIColor(red: 0.25, green: 0.25, blue: 0.25, alpha: 1.0) 
    rightNavigationController?.navigationBar.tintColor = UIColor.whiteColor() 
    rightNavigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.whiteColor()] 
    rightNavigationController?.navigationBar.translucent = false 

    slideViewController = SWRevealViewController() 
    slideViewController?.rearViewRevealOverdraw = 0; 
    slideViewController?.bounceBackOnOverdraw = false; 
    slideViewController?.stableDragOnOverdraw = true; 
    slideViewController?.delegate = self 

    if UIDevice.currentDevice().userInterfaceIdiom == UIUserInterfaceIdiom.Pad{ 
     splitViewController = UISplitViewController() 
    } 
} 

EDIT (để đáp lại câu hỏi của Justin):

1) Tôi đã trải qua những vụ tai nạn trên tất cả các mô phỏng iOS8 iPad.

2) Từ một khởi đầu mới, nếu tôi chọn như 6-7 mục và sau đó tôi xoay hai lần, nó bị treo. Nhưng tôi cũng có thể chọn một mục, xoay một vài lần, chọn một số chi tiết và tiếp tục quay và tại một số điểm nó sẽ sụp đổ.

3) Khi một mục được chọn, các mã sau đây được thực hiện:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 
    let document = getInfoForSection(indexPath.section).documents[indexPath.item] 
    if document.canOpen{ 
     openDocument(document) 

     DataManager.sharedInstance.getDocument(document.uri, after: { 
      (document:Document?) ->() in 
      if let documentUnwrapped = document{ 
       let detailVC = NavigationFlowController.sharedInstance.detailViewController; 
       if detailVC.document?.uri == documentUnwrapped.uri{ 
        NavigationFlowController.sharedInstance.detailViewController.documentUpdated(documentUnwrapped) 
       } 
      } 
     }) 
    } 
} 

Và sau đó trong bộ điều khiển xem chi tiết:

func initLayout(){ 
    if viewForCard == nil{ 
     // views not yet initialized, happens when initLayout if called from the document setter before this view has been loaded 
     // just return, the layouting will be done on viewDidLoad with the correct document instead 
     return 
    } 

    self.navigationItem.rightBarButtonItems = [] 

    if document == nil{ 
     // Removed code that handles no document selected 
     ... 
     return 
    } 

    heightForCard.constant = NavigationFlowController.sharedInstance.currentState == AppState.PHONE ? CARD_HEIGHT_PHONE : CARD_HEIGHT_TABLET 

    viewForCard.hidden = false 
    removeAllSubviews(viewForCard) 
    removeAllSubviews(viewForDetails) 

    viewForDetails.translatesAutoresizingMaskIntoConstraints = false 

    self.metaVC?.document = document 
    //self.documentVC?.document = document 
    self.navigationItem.rightBarButtonItems = [] 

    downloadDocumentIfNeeded() 

    if NavigationFlowController.sharedInstance.currentState == AppState.PAD_LANDSCAPE || NavigationFlowController.sharedInstance.currentState == AppState.PAD_PORTRAIT{ 
     self.viewForDetails.backgroundColor = document?.senderStyling?.color 

     addChildViewController(self.metaVC!) 
     addChildViewController(self.documentVC!) 

     let metaView = self.metaVC!.view 
     let documentView:UIView = self.documentVC!.view 

     viewForDetails.addSubview(metaView) 
     viewForDetails.addSubview(documentView) 

     // whole lot of layouting code removed 
     ...    

     let doubleTap = UITapGestureRecognizer(target: self, action: "toggleZoom") 
     documentVC!.view.addGestureRecognizer(doubleTap) 

    }else{ 
     // Phone version code removed 
     ... 
    } 
} 

EDIT2:

func downloadDocumentIfNeeded(){ 
    var tmpPath:NSURL? 
    if let url = document?.contentUrl{ 
     let directoryURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] 

     if let docName = self.document?.name, 
      safeName = disallowedCharacters?.stringByReplacingMatchesInString(docName, options: [], range: NSMakeRange(0, docName.characters.count), withTemplate: "-"){ 
       tmpPath = directoryURL.URLByAppendingPathComponent("\(safeName)_\(DetailViewController.dateFormatter.stringFromDate(self.document!.creationDate!)).pdf") 

     } 


     if let urlString = tmpPath?.path{ 
      if NSFileManager.defaultManager().fileExistsAtPath(urlString) { 
       // File is there, load it 
       loadDocumentInWebview(tmpPath!) 
      }else{ 
       // Download file 
       let destination: (NSURL, NSHTTPURLResponse) -> (NSURL) = { 
        (temporaryURL, response) in 

        if let path = tmpPath{ 
         return path 
        } 

        return temporaryURL 
       } 

       download(.GET, URLString: url, destination: destination).response { 
        (request, response, data, error) in 

        if error != nil && error?.code != 516{ 
         ToastView.showToastInParentView(self.view, withText: "An error has occurred while loading the document", withDuaration: 10) 
        }else if let pathUnwrapped = tmpPath { 
         self.loadDocumentInWebview(pathUnwrapped) 
        } 
       } 
      } 
     } 
    } 
} 

func loadDocumentInWebview(path:NSURL){ 
    if self.navigationItem.rightBarButtonItems == nil{ 
     self.navigationItem.rightBarButtonItems = [] 
    } 

    self.documentVC?.finalPath = path 

    let shareItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Action, target: self, action: "share") 
    shareItem.tag = SHARE_ITEM_TAG 

    addNavItem(shareItem) 

} 

func addNavItem(navItem:UIBarButtonItem){ 
    var addIt = true 
    for item in self.navigationItem.rightBarButtonItems!{ 
     if item.tag == navItem.tag{ 
      addIt = false 
     } 
    } 

    if addIt{ 
     self.navigationItem.rightBarButtonItems?.append(navItem) 
     self.navigationItem.rightBarButtonItems!.sortInPlace({ $0.tag > $1.tag }) 
    } 
} 

EDIT3 : Tôi đã ghi đè phương thức sendEvent để theo dõi xem người dùng có đang chạm vào ứng dụng hay không, nhưng ngay cả khi tôi đưa ra điều này mã, nó vẫn còn treo, và trình gỡ lỗi sau đó phá vỡ trên UIApplicationMain.

override func sendEvent(event: UIEvent) 
{   
    super.sendEvent(event) 

    if event.type == UIEventType.Touches{ 
     if let touches = event.allTouches(){ 
      for item in touches{ 
       if let touch = item as? UITouch{ 
        if touch.phase == UITouchPhase.Began{ 
         touchCounter++ 
        }else if touch.phase == UITouchPhase.Ended || touch.phase == UITouchPhase.Cancelled{ 
         touchCounter-- 
        } 

        if touchCounter == 0{ 
         receiver?.notTouching() 
        } 
       } 
      } 
     } 
    } 
} 
+0

Bạn có thể hiển thị 'downloadDocumentIfNeeded()' không? – anhtu

+0

Chính xác bạn đang làm gì với các sự kiện? Tôi không thấy 'sendEvent' ở đó? – Sulthan

+0

Tôi đã giải thích trong EDIT3 –

Trả lời

6

Khó khăn hơn, thông tin chi tiết hơn về các sự kiện tối đa lỗi này có thể hữu ích.

  1. Liệu nó xảy ra trên mọi thiết bị (nếu không muốn nói, mà các thiết bị cung cấp cho bạn những rắc rối)
  2. Nó xảy ra sau khi "mạnh mẽ cách chọn" mục. Thiết bị của bạn có thay đổi hướng trước đó không. Liệu nó cũng xảy ra trước khi bạn quay một lần?
  3. Bạn làm gì trong mã khi bạn "chọn một mục".

Sau đó, tôi bắt đầu có được dòng chảy của việc xóa con bạn ViewControllers in breakupFormerViewTree() ngay. Dựa trên Apple Documents bạn muốn nói với các con nó đang được gỡ bỏ, trước khi tháo quan điểm và cuối cùng loại bỏ các con từ Phụ Huynh ViewController

https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/CreatingCustomContainerViewControllers/CreatingCustomContainerViewControllers.html

Ở đây nó thực sự nói rằng bạn muốn gọi willMoveToParentViewController (nil) trước khi thực hiện việc xóa. Nó không nói điều gì sẽ xảy ra nếu bạn không làm như vậy, nhưng tôi có thể tưởng tượng hệ điều hành đang thực hiện một số quản lý vòng đời ở đó, ngăn không cho nó gửi các sự kiện tham nhũng vào một thời điểm sau đó.

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/index.html#//apple_ref/occ/instm/UIViewController/willMoveToParentViewController:

EDIT (Sau khi thêm được mã đăng)

tôi không thấy bất cứ điều gì khác trong mã của bạn mà có thể làm sụp đổ. Nó trông giống như một lỗi bộ nhớ như bạn đã nói, nhưng không biết nó đến từ đâu. Hãy thử bật các đối tượng Zombie và Guard Malloc (Scheme> Run> Diagnostics) và có thể bạn sẽ có thêm thông tin về những gì gây ra nó.

Sau đó, tôi chỉ cần bình luận các tải của việc triển khai của bạn, hoán đổi các lớp con với ViewControllers trống cho đến khi nó không xảy ra lần nữa. Bạn có thể xác định phần nào trong quá trình triển khai của mình có liên quan đến việc tạo sự kiện này. Một khi bạn làm điều đó, tốt, xác định nhiều hơn và đánh giá từng dòng mã trong triển khai đó.

Các vấn đề liên quan