Application runs with a "println" method, but crashes with EXC_BAD_ACCESS when it's removed - ios

I have the following applicationWillEnterForeground method code, with the next println method: println("nextUpdate unwrapped"). If this print exists then the application runs without issues, as soon as I remove/comment out this println method the application crashes with EXC_BAD_ACCESS but the location of the error is not specified in the console, so I have no idea what is crashing my app.
func applicationWillEnterForeground(application: UIApplication!) {
// Called as part of the transition from the background to the
// inactive state; here you can undo many of the changes made on
// entering the background.
countForWill++
var timeIntervalSince1970: NSTimeInterval!
Logger.printLogToConsole(TAG, aMethodName: __FUNCTION__, aMessage: "Runs for the \(countForWill) time")
var lastUpdateTimeStamp: AnyObject? = NSUserDefaults.standardUserDefaults().doubleForKey(KiboConstants.UserDefaultsStrings.USER_DEF_LAST_UPDATE_TIME_STAMP)
var nextUpdate: AnyObject? = NSUserDefaults.standardUserDefaults().doubleForKey(KiboConstants.UserDefaultsStrings.USER_DEF_NEXT_UPDATE)
if let lastUpdateTimeStampUnwrapped: AnyObject = lastUpdateTimeStamp {
if let nextUpdateUnwrapped: AnyObject = nextUpdate {
println("nextUpdate unwrapped")
let lastUpdateTimeStampUnwrappedDouble: Double = lastUpdateTimeStampUnwrapped as Double
var nextUpdateUnwrappedDouble: Double = nextUpdateUnwrapped as Double
nextUpdateUnwrappedDouble = nextUpdateUnwrappedDouble * 60
//var nextUpdateTimeStamp: Double = (lastUpdateTimeStampUnwrapped as Double) + (nextUpdateUnwrapped as Double * 60)
var nextUpdateTimeStamp: Double = lastUpdateTimeStampUnwrappedDouble + nextUpdateUnwrappedDouble
timeIntervalSince1970 = NSDate().timeIntervalSince1970
if (nextUpdateTimeStamp < timeIntervalSince1970) {
checkForNewSources()
} else {
let updatedNextUpdate = nextUpdateTimeStamp - NSDate().timeIntervalSince1970
setTimeWithNextUpdateValue(updatedNextUpdate)
}
} else {
var nextUpdateTimeStamp: Double = (lastUpdateTimeStampUnwrapped as Double) + (DEFAULT_NEXT_UPDATE_VAL * 60)
timeIntervalSince1970 = NSDate().timeIntervalSince1970
if (nextUpdateTimeStamp < timeIntervalSince1970) {
checkForNewSources()
} else {
let updatedNextUpdate = nextUpdateTimeStamp - timeIntervalSince1970
setTimeWithNextUpdateValue(updatedNextUpdate)
}
}
} else {
checkForNewSources()
}
let topViewController = self.IndexNavigationController.topViewController
if topViewController is HelloViewController {
var found: Bool = false
found = SystemUtils.CommonTasks.isKiboKeyboardEnabled()
if found {
let activateViewController = ActivateViewController()
self.IndexNavigationController.pushViewController(activateViewController, animated: false)
}
}
}
Now, obviously this is a timing bug, but I'm just started to develop for the iOS and I have no idea how to debug and fix this issue.

Related

Swift code nested If statement is very slow?

I have a code that looks like this:
var fullJSON = "["
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Job")
do {
if let jobs = try coreDataContext().fetch(fetchRequest) as? [Job] {
// let jobs: [Job] = fetchCoreData(entity: "Job")
for job in jobs {
if let json = job.toJSON() {
/*if (fullJSON.count > 1) {
//print( "size of values is : \(fullJSON)" )
//fullJSON += ",\n "
}*/
fullJSON += json
//print( "size of values is : \(fullJSON)" )
} else {
print("COULDN'T JSON \(job.name ?? "")")
callback("Error decoding \(job.name ?? "")")
return
}
}
fullJSON += "]"
API.sync(json: fullJSON) { (result) in
DispatchQueue.main.async {
if !result.success {
callback("Network error: " + result.error)
return
}
guard let jsonJobs = result.payload?["jobs"] as? [NSDictionary] else {
callback("Error parsing result"); return
}
//delete existing
let existing: [Job] = self.fetchCoreData(entity: "Job")
for item in existing {
self.coreDataContext().delete(item)
}
for job in jsonJobs {
let newJob = Job.init(context: self.coreDataContext())
newJob.load(job, context: self.coreDataContext())
}
try? self.coreDataContext().save()
callback(nil)
}
}
} else {
callback("Error getting jobs")
}
}
When I run this code, it is very slow!
I've pin pointed the issue to this code:
if (fullJSON.count > 1) {
fullJSON += ",\n "
}
If I remove that code, everything is fast again!
I have no idea why that small part of the code makes everything so slow!
Can someone please advice on this?
Valid comments regarding better approaches to your task, however...
Pretty certain the speed difference is in the use of:
if (fullJSON.count > 1) {
that .count is a very expensive operation.
Try adding this to a view controller. Each time you tap anywhere, we'll simulate your json activity by appending "ABC" to the string var.
The first loop uses your fullJSON.count to decide to add the ",\n"
The second loop uses a Bool variable to append the ",\n" only after the first time through.
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
var fullJSON: String = ""
var length1: Int = 0
var length2: Int = 0
var st1 = CFAbsoluteTimeGetCurrent()
var st2 = CFAbsoluteTimeGetCurrent()
var ed1 = CFAbsoluteTimeGetCurrent()
var ed2 = CFAbsoluteTimeGetCurrent()
st1 = CFAbsoluteTimeGetCurrent()
fullJSON = "["
for _ in 1...5000 {
if fullJSON.count > 1 {
fullJSON += ",\n"
}
fullJSON += "ABC"
}
ed1 = CFAbsoluteTimeGetCurrent()
length1 = fullJSON.count
var b: Bool = false
st2 = CFAbsoluteTimeGetCurrent()
fullJSON = "["
for _ in 1...5000 {
if b {
fullJSON += ",\n"
}
fullJSON += "ABC"
// we've gone through once
b = true
}
ed2 = CFAbsoluteTimeGetCurrent()
length2 = fullJSON.count
print("Timing:", ed1 - st1, ed2 - st2)
// to confirm we get same resulting string lengths
print("Lengths:", length1, length2)
print()
}
Here's what I get on 5 runs:
Timing: 0.5321569442749023 0.002187013626098633
Lengths: 24999 24999
Timing: 0.5368150472640991 0.0024269819259643555
Lengths: 24999 24999
Timing: 0.5297999382019043 0.002218961715698242
Lengths: 24999 24999
Timing: 0.5305029153823853 0.002167940139770508
Lengths: 24999 24999
Timing: 0.5307689905166626 0.0022219419479370117
Lengths: 24999 24999
This is, of course, not the ideal way to profile code, but we can easily see the big difference here.

An array of a value not being properly displayed in the label

I am using xcode 8 and swift 3. I have made a mini game where you have to answer questions as fast as you can. You are timed by a stopwatch. I have the code to actually store the times(eg 23 seconds) but instead of storing the time, it replaces it with "Label". My stopwatch label is called down and the label that displays the values is called resultLabel I have been told the problem is when i set the text of the label. Any ideas on where i need to fix it. An example is ["Label", "Label", "Label"]
Stopwatch code:
if timerSecond != nil {
timerSecond?.invalidate()
timerSecond = nil
} else {
timerSecond = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
self.currentTime += 1
let minutePortion = String(format: "%02d", self.currentTime / 60 )
let secondsPortion = String(format: "%02d", self.currentTime % 60 )
self.down.text = "\(minutePortion):\(secondsPortion)"
}
}
extension for User Defaults:
extension UserDefaults {
var timesSecond: [String] {
get {
if let times = UserDefaults.standard.object(forKey: "times") as? [String] {
return times
} else {
return []
}
}
set {
UserDefaults.standard.set(newValue, forKey: "times")
}
}
}
Button code to display the array of values:
let arrayOfTimes = UserDefaults.standard.timesSecond
resultLabel.text = "\(arrayOfTimes)"
code for storing the data:
UserDefaults.standard.timesSecond.append(resultLabel.text!)

Getting EXC_BAD_ACCESS while the object exists

I'm developing a music sequencer with a standard piano roll type UI.
It was working well until I made some changes in the model side but it suddenly started to report EXC_BAD_ACCESS at (seemingly) unrelated part.
What's strange is all the necessary variables have their values properly and actually I can print values with po.
In my understanding, EXC_BAD_ACCESS happens when an object doesn't exist, so this seems quite strange.
My question is:
Is it common to EXC_BAD_ACCESS even the values are there?
If that's the case what is the possible situation to cause that?
Any suggestion is helpful. Thanks
[Below are the codes]
In my subclass of UICollectionViewLayout:
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
// note cells
let cv = self.collectionView as! YMPianoRollCollectionView;
let pianoRoll = cv.pianoRollViewController;
// Call the below func to get the indexes of the Note Objects included in the specified rect
let indexArray: Array<Int> = pianoRoll!.getNoteIndexes(inRect:rect, useOnlyStartTime: false);
var retArray : [UICollectionViewLayoutAttributes] = []
for i in indexArray {
if let _ = pianoRoll?.pattern.eventSequence[i] as? YMPatternEventNoteOn {
retArray.append( self.layoutAttributesForPatternEventInfo(i) )
}
}
return retArray
}
In my "piano roll" class which contains UICollectionView
func getNoteIndexes(inRect rect:CGRect, useOnlyStartTime: Bool) -> Array<Int> {
//
// Transform given values into musical values
//
let musicRange :YMMusicalValueRange = screenInfo.getMusicalRange(rect);
let startTime = musicRange.origin.time;
let endTime = musicRange.origin.time + musicRange.size.timeLength;
let lowNoteU = musicRange.origin.noteNumber;
let highNoteU = musicRange.origin.noteNumber + musicRange.size.numberOfNotes;
var retArray : [Int] = []
for i in 0..<pattern.eventSequence.count {
if let e = pattern.eventSequence[i] as? YMPatternEventNoteOn {
//
// Prepare ranges
//
let noteNo = e.noteNo; //<- App Crashes Here with BAD_ACCESS
let noteStTime = e.time;
let noteEnTime = e.time + e.duration;
let targetNoteRange = Range<Int>(uncheckedBounds: (lowNoteU, highNoteU));
let targetTimeRange = Range<Int64>(uncheckedBounds: (startTime, endTime))
let noteTimeRange = Range<Int64>(uncheckedBounds: (noteStTime, noteEnTime))
//
// Check the match
//
let noteMatches = targetNoteRange.contains(noteNo);
let timeMatches = useOnlyStartTime ? targetTimeRange.contains(noteStTime)
: targetTimeRange.overlaps(noteTimeRange)
if noteMatches && timeMatches {
retArray.append( i );
NSLog("XXX Found: note \(noteNo) at \(e.time)");
}
}
}
return retArray;
}
Error:- The object states when it crashed
EDIT
Here's the YMPatternEventNoteOn declaration
class YMPatternEvent : Codable, CustomDebugStringConvertible {
var time : YMSequenceTime = 0
// Some utility funcs follow
// ...
}
class YMPatternEventNoteOn : YMPatternEvent {
var noteNo : Int = 64
var velocity : Int = 127
var duration : YMSequenceTime = 480
var tempBendId : Int = 0;
var tempVibratoId : Int = 0;
var tempArpeggioId : Int = 0;
convenience init(time :YMSequenceTime, noteNo : Int, velocity: Int, duration: YMSequenceTime) {
self.init();
self.time = time;
self.noteNo = noteNo;
self.velocity = velocity;
self.duration = duration;
}
// Other methods follow
// ...
}
EDIT2
Note event is created by the user's action
//
// In YMPattern object
//
func insertNote(time:YMSequenceTime, noteNo:Int, velocity:Int, duration:YMSequenceTime) -> Int
{
let onEvent = YMPatternEventNoteOn(time: time, noteNo: noteNo, velocity: velocity, duration: duration);
let retIndex = insertEvent(onEvent);
return retIndex;
}
func insertEvent(_ event: YMPatternEvent) -> Int {
let atTime = event.time;
var retIndex : Int = 0;
if(eventSequence.count<1){
// If it's the first event just add it
eventSequence.append(event);
retIndex = 0;
} else {
// If any event already exists, insert with time order in consideration
var i : Int = 0;
while( atTime > eventSequence[i].time ){
i += 1;
if( i >= eventSequence.count ){
break;
}
}
retIndex = i;
eventSequence.insert(event, at: i)
}
}
//
// In pianoroll view controller
//
func actionButtonReleased(afterDragging: Bool) {
let values:YMMusicalValuePoint = screenInfo.getMusicalPosition(cursorPosition);
// insert new event with default velocity and duration
let _ = pattern.insertNote(time: values.time, noteNo: values.noteNumber, velocity: 127, duration: screenInfo.timeTicsPerDivision());
collectionView.reloadData();
}
I've solved it in a way.
By setting the optimization level to "Whole Module Optimization" it stopped reporting the error.
I don't know what is happening internally but if someone is having the same issue, this might work as a quick fix.

Swift display annotations in mapView in another thread

This code does not add annotations to mapView. I saw in one answer that mapView function is called every time addAnotation is called so where's the problem? But when I move map they show up.
func addPlacesMarkers(location:CLLocation) {
self.communication.getJsonData(self.getPubsNearByCreator(location)) { (finalData, error) -> Void in
if error != nil {
print(error)
} else {
if let row: NSArray = finalData {
for var i = 0; i < row.count; i++ {
let lat = row[i]["lat"] as! String
let lng = row[i]["lng"] as! String
let title = row[i]["name"] as! String
let id = row[i]["id"] as! String
let point = CustomizedAnotation(id: Int(id)!, name: title)
point.title = title
point.coordinate.latitude = Double(lat)!
point.coordinate.longitude = Double(lng)!
let keyExists = self.places[Int(id)!] != nil
if keyExists == false {
self.places.updateValue(point, forKey: Int(id)!)
}
}
var finalPlaces :[MKPointAnnotation] = []
for place in self.places.values {
finalPlaces.append(place)
}
self.mView.addAnnotations(finalPlaces)
self.mView.showsPointsOfInterest = false
}
}
}
}
You can't modify the UI in a thread different from the main.
You should put your UI modification code inside a dispatch_async block like this:
dispatch_async(dispatch_get_main_queue()) {
//Your code that modify the UI
self.mView.addAnnotations(finalPlaces)
}

array element cannot be bridged to Objective-C after migration to Swift 1.2

Yesterday I have switched my IOS Swift project to the new XCode 6.3 and Swift 1.2. I have so far got everything to build nicely, but at one point the app crashes with the error message "fatal error: array element cannot be bridged to Objective-C" at a line that looks like this:
let services = services as! [ServiceObject]
I have read that the error is because I have Objective C objects as members in the Swift Array which is now not automatically bridged to NSArray anymore, so I would have to either make my objects of type ServiceObject non-Obj-C or declare "services" as an NSArray. The strange thing is that ServiceObject is not an Objective-C object. This is the declaration of the class:
class ServiceObject: MonitoringObject {
let serviceDescription: String
let host: HostObject
var duration = 0
var plugin_output = ""
var active_checks_enabled = 0
var display_name = ""
var has_been_checked = 0
var acknowledged = 0
var acknowledgement_type = 0
var scheduled_downtime_depth = 0
var is_flapping = 0
var state = ServiceState.OK
var name: String {
return serviceDescription
}
init(serviceDescription: String, host: HostObject) {
self.host = host
self.serviceDescription = serviceDescription
}
var durationText: String {
if duration == -1 || duration == 0{
return "N/A"
} else if duration > 86400 {
let days = Int(floor(Float(duration) / 86400))
let hours = Int(floor(Float(duration % 86400) / 3600))
return "\(days)d, \(hours)h"
} else if duration > 3600 {
let hours = Int(floor(Float(duration) / 3600))
let minutes = Int(floor(Float(duration) % 3600 / 60))
return "\(hours)h, \(minutes)m"
} else if duration > 60 {
let minutes = Int(floor(Float(duration) / 60))
let seconds = duration % 60
return "\(minutes)m, \(seconds)s"
} else {
return "\(duration)s"
}
}
}
Also, the protocol "MonitoringObject" which ServiceObject conforms to is not Obj-C:
protocol MonitoringObject {
var name: String { get }
}
Does anybody have any clue where the error and the crash come from?
Edit: this is the whole method where the line that fails is contained, to make the context more clear:
private func buildHostServicesIndex(services: [MonitoringObject]) -> [HostServicesEntry] {
//typealias HostServicesEntry = (HostObject, [ServiceObject])
let services = services as! [ServiceObject]
let hosts = services.map {
(service) -> HostObject in
service.host
}
let distinctHosts = Helpers.distinct(hosts)
return distinctHosts.map {
(host) -> HostServicesEntry in
return (host, services.filter {
(service) -> Bool in
service.host == host
})
}
}

Resources