幻影EXC_BAD_ACCESS
每隔BAD_ACCESS我是以前通常是一个快速错字修复,但是这一次是非常混乱幻影EXC_BAD_ACCESS
此代码应该下载的.ics谷歌日历文件,然后将它传递到解析器功能,即将返回的事件对象(这里不包括在内)的阵列
的问题是,当一个物理iOS装置上进行测试,loadEventIntoCalendar()的每3〜4运行的EXC_BAD_ACCESS是当该行被称为
抛出tempHold = calendarString.substring(with: tempRange)
在event()函数的while循环中。
我试着用很多不同的技术解决这个问题。 僵尸对象不会在日志中打印任何东西。 我试着分析仪器的运行,但我没有发现任何有用的。我尝试在参数中传递一个单独的String文件副本,但是这并没有改变任何东西。
我认为这个问题与calendarString有关,或者至少是指向的值。我试着通过Xcode分析内存块,但是我找不到任何变量,这会指向导致错误的内存位置。
我敢肯定,RAM不会超载为整个应用程序只占用约70兆字节的最高(经过与仪器)
事件()被认为是一个单独的静态函数。
这里有两个功能
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)
}
这必须相对快地完成,所以快速反应,将不胜感激。
在此先感谢!
其实,我落得这样做是完全重写的算法。它的工作方式有点不同,现在实际上缩短了20行,速度更快。
感谢您的关注!感谢帮助:)
据我所知,字符串搜索方法不保证结果范围的长度为0
。如果您更换两个范围检查会发生什么?
if range.location == NSNotFound { ... }
代替
if NSEqualRanges(range, NSMakeRange(NSNotFound, 0)) { ... }
据我所知,NSNotFound是一个数字,而不是一个范围,所以我不认为这条线将工作,但无论如何感谢。 – sketch204
你有没有尝试在行上放置一个断点'tempHold = calendarString.substring(with:tempRange)'或记录'tempRange'和'calendarString'就在它之前? –
问题在于内存中的某些组件在运行过程中中途遭到破坏,所以除了一个点上的完全活动变量和下一个损坏的断点之外,断点不会显示太多内容。不显示我的错误来源 – sketch204