2016-11-26 1 views
0

는 내가 가진 모든 다른 BAD_ACCESS 전에 일반적으로 빠른 오타 수정했다, 그러나 이것은 매우 혼란팬텀 EXC_BAD_ACCESS

이 코드는 있다고하는 .ics 인 구글 캘린더 파일을 다운로드 한 후 파서 함수에 전달할 예정이다

(하지 여기에 포함 된) 이벤트 객체의 배열을 반환합니다

물리적 iOS 장비에서 테스트 할 때이 라인이

를 호출 할 때 문제는, loadEventIntoCalendar()의 모든 3 - 4 실행가 EXC_BAD_ACCESS가 발생한다 tempHold = calendarString.substring(with: tempRange)

은 event() 함수의 while 루프에 있습니다.

많은 다른 기술로이 문제를 해결하려고했습니다. 좀비 오브젝트가 똑바로 나오면 로그에 아무것도 인쇄되지 않습니다. 인스트루먼트으로 실행 분석을 시도했지만 유용하지 않은 항목을 찾지 못했습니다. 인수에 전달 된 String 파일의 별도 복사본을 만들려고했으나 아무 것도 변경하지 않았습니다.

나는이 문제가 calendarString과 관련이 있거나 적어도 가리키는 값과 관련이 있다고 확신한다. Xcode를 통해 메모리 블록을 분석해 보았습니다. 그러나 오류를 일으키는 메모리 위치를 가리키는 변수를 찾을 수 없었습니다.

나는 단지 싱글 정적 기능이 있어야하는데

이벤트() ( 계기와 검사) 약 70 메가 바이트 최대를 차지 RAM 전체 응용 프로그램으로 과부하가되지 않을 것이라고 확신 해요. 여기

이 상대적으로 빨리 완료 할 수있는 두 가지 기능

func loadEventsIntoCalendar() { 
    // The link from which the calendar is downloaded 
    let url = URL (string: "https://calendar.google.com/calendar/ical/wlmacci%40gmail.com/public/basic.ics")! 


    // The process of downloading and parsing the calendar 
    let task = URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in 
     // The following is simply a declaration and will not execute without the line 'task.resume()' 
     if let URLContent = data { // If Data has been loaded 
      // If you got to this point then you've downloaded the calendar so... 
      // Calendar File parsing starts here!!! 
      // The string that holds the contents of the calendar's events 
      var webContent:String = String(data: URLContent, encoding:String.Encoding.utf8)! 
      self.events(forCalendarFile: &webContent, inCalendar: Calendar(identifier: Calendar.Identifier.gregorian)) 
     } 
    }) 
    task.resume() 
} 

// Calendar Parser for this VC 
func events(forCalendarFile webContent:inout String, inCalendar calendar:Calendar) { 
    // The reason for this complication is, i thought copying the object might solve the issue, it did not :(
    let NSWebContent = NSString(string: webContent) 
    let calendarString = NSWebContent.copy() as! NSString 

    // An array of flags used for locating the event fields 
    // [h][0] - The flag that marks the begining of a field, [h][1] - The flag that marks the end of a field 
    let searchTitles:[[String]] = [["SUMMARY:", "TRANSP:"], ["DESCRIPTION:", "LAST-MODIFIED:"], ["DTSTART", "DTEND"], ["DTEND", "DTSTAMP"], ["LOCATION:", "SEQUENCE:"]] 

    // The range of "webContent's" content that is to be scanned 
    // Must be decreased after each event is scanned 
    var range:NSRange = NSMakeRange(0, calendarString.length - 1) 
    // Inside function that will be used to determine the 'difference' range between the begining and end flag ranges. 
    let findDifference:(NSRange, NSRange) -> NSRange = {(first:NSRange, second:NSRange) -> NSRange in 
     let location = first.location + first.length, length = second.location - location // Determine the start position and length of our new range 
     return NSMakeRange(location, length)            // Create and return the new range 
    } 
    // Inside function that will be used to move the searching range to the next event 
    // Returns an NSNotFound range (NSNotFound, 0) if there are no more events 
    let updateRange:(NSRange) -> NSRange = {(oldRange:NSRange) -> NSRange in 
     let beginingDeclaration = calendarString.range(of: "BEGIN:VEVENT", options: NSString.CompareOptions.literal, range: oldRange) 
     // If the "BEGIN:VEVENT" was not found in webContent (no more events) 
     if NSEqualRanges(beginingDeclaration, NSMakeRange(NSNotFound, 0)) { 
      return beginingDeclaration // Return an 'NSNotFound' range (Named it myself;) 
     } 
     // Calculate the index of the last character of 'beginingDeclaration' flag 
     let endOfBeginingDeclaration = beginingDeclaration.location + beginingDeclaration.length 
     // Calculate the length of the new range 
     let length = oldRange.length - endOfBeginingDeclaration + oldRange.location 
     // Calculate the starting location of the new range 
     let location = endOfBeginingDeclaration 
     // Create and return the new range 
     return NSMakeRange(location, length) 
    } 

    // A holder for the begining and end flags for each event field 
    var fieldBoundaries:[NSRange] 
    // The actual parsing of each event 
    repeat { 
     range = updateRange(range) // Move our searching range to the next event 
     if NSEqualRanges(range, NSMakeRange(NSNotFound, 0)) { // If there are no more events in the searching range 
      break;            // Then no more shall be added (break from the loop) 
     } 

     var tempHold:String! 
     // Record each field into our event database 
     for h in 0...searchTitles.count-1 { 
      fieldBoundaries = [NSRange]() // Clear the fieldBoundaries for the new search 
      fieldBoundaries.append(calendarString.range(of: searchTitles[h][0], options: NSString.CompareOptions.literal, range: range)) // Find the begining flag 
      fieldBoundaries.append(calendarString.range(of: searchTitles[h][1], options: NSString.CompareOptions.literal, range: range)) // Find the ending flag 
      let tempRange = findDifference(fieldBoundaries[0], fieldBoundaries[1]) 
      print ("Isolating event content") 
      tempHold = calendarString.substring(with: tempRange)       // Create a new string from whatever is in between the two flags. This will be the current field of the event 
      print ("Event content isolated") 
      tempHold = tempHold.trimmingCharacters(in: CharacterSet.newlines)           // Remove all /r /n and other 'new line' characters from the event field 
      tempHold = tempHold.replacingOccurrences(of: "\u{005C}", with: "", options: .literal, range: nil)   // Replace all backslashes from the event field 
     } 
    } while (true) 
} 

, 그래서 빠른 응답이 크게 이해할 수있을 것이다.

미리 감사드립니다.

+0

'tempHold = calendarString.substring (with : tempRange)'또는 중단 직전에'tempRange' 및'calendarString'을 로깅 해 본 적이 있습니까? –

+0

문제는 메모리 내부의 구성 요소 중 일부가 실행 과정 중 절반 이상이 손상 되었기 때문에 중단 점이 한 지점에서 완전히 활성 변수가 있고 다음 지점에서 손상된 부분을 제외하고는 많이 표시하지 않을 것이라는 점입니다. 내가 오류의 원인을 표시하지 않습니다 – sketch204

답변

0

if range.location == NSNotFound { ... } 

. 그것은 약간 다른 방식으로 작동하고 실제로 20 줄 더 짧고 훨씬 빨라졌습니다.

관심을 가져 주셔서 감사합니다. 도움을 감사하십시오 :)

0

내가 아는 한, 문자열 검색 방법은 결과 범위의 길이를 0으로 보장하지 않습니다. 두 가지 범위 검사를 대체하면 어떻게됩니까? 대신에 나는 완전히 알고리즘을 재 작성되는 일을 결국 어떤 사실

if NSEqualRanges(range, NSMakeRange(NSNotFound, 0)) { ... } 
+0

NSNotFound는 숫자가 아닌 범위이므로, 그 행은 작동한다고 생각하지 않지만 어쨌든 고마워요. – sketch204