6
\$\begingroup\$

I am working on a project called neoCode that takes a users input URL and turns it into HTML or Machine Code. I am so close to pushing this to TestFlight for beta testing but I have a pretty bad performance issue that I can't figure out.

Let me first start by explaining what the app does and then at the end I will leave a dropbox link if you want to look at the entire project in Xcode 6.

The greyViewController is where the user inputs the URL. The user can go to either the pinkViewController (HTML) or blueViewController (Machine) to see the output code. The pinkViewController has a simple function to take the globalHttpUrl variable and process it for output. I haven't seen any issues with this View Controller. The blueViewController has a more complicated function hexStringFromData that takes the same globalHttpUrl and translates it into machine code. I have this function running through Grand Central Dispatch in small chunks to keep the CPU from spiking to 100% and hanging the UI.

Problem:

The initial setting of globalHttpUrl on both ViewControllers works as advertised. When the user re-enters another URL and goes to the BlueViewController, then back to either the PinkViewController or GreyViewController, the UI tends to hang and it is very slow for entering a 3rd URL, from then on the entire updating of the Pink and Blue Controllers is VERY slow. What am I missing? Is there any way I can break the hexStringFromData function to even smaller bits? Would this even help?

Dropbox Link to Xcode 6 project https://www.dropbox.com/sh/logt6igz9ds7kqq/AADnfbADxhxZekcnW8yIFN-Fa?dl=0

Code:

import Foundation
import UIKit
var aurl = NSString(string: "http://")
var globalHttpUrl: NSURL!

var url: NSURL{
get {
   return NSURL(string: "\(aurl)\(globalHttpUrl)")
  }
}

class SneakyViewController : UIViewController {

 override func viewWillAppear(animated: Bool) {

    super.viewWillAppear(animated)
    println(self.title)

   }
}


class PinkViewController : SneakyViewController {

@IBOutlet weak var machineCode: UITextView!

 override func viewDidLoad() {
    super.viewDidLoad()

    let task = NSURLSession.sharedSession().dataTaskWithURL(url) {(data, response, error) in

        var myText = NSString(data: data, encoding: NSASCIIStringEncoding)

        dispatch_async(dispatch_get_main_queue()) {

            self.machineCode.text = myText

        }
    }

    //NSASCIIStringEncoding
    task.resume()

   }

    override func viewWillAppear(animated: Bool) {

    let task = NSURLSession.sharedSession().dataTaskWithURL(url) {(data, response, error) in

        var myText = NSString(data: data, encoding: NSASCIIStringEncoding)

        dispatch_async(dispatch_get_main_queue()) {

            self.machineCode.text = myText

        }
     }

    //NSASCIIStringEncoding
    task.resume()

   }


 }

class GreyViewController : SneakyViewController, UITextFieldDelegate {

@IBOutlet var neoCodeView: UIView!

@IBOutlet weak var userInput: UITextField!

 //var burl = NSString(string: "http://")

 @IBAction func buttonPressed(sender: AnyObject) {
  }

  override func viewDidLoad() {
    super.viewDidLoad()

  userInput.clearsOnBeginEditing.description
  userInput.clearButtonMode = UITextFieldViewMode.WhileEditing


   }

   @IBAction func goToPinkViewController(sender: AnyObject) {

    globalHttpUrl = NSURL(string: self.userInput.text)


   }

  override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {

    self.view.endEditing(true)

   }

   func textFieldShouldReturn(textField: UITextField) -> Bool {
   userInput.resignFirstResponder()
    return true 
   }


   override func viewWillAppear(animated: Bool) {

    func touchesBegan(touches: NSSet, withEvent event: UIEvent) {

        self.view.endEditing(true)

     }

     func textFieldShouldReturn(textField: UITextField) -> Bool {
        userInput.resignFirstResponder()
        return true
     }

      userInput.clearsOnBeginEditing.description
      userInput.clearButtonMode = UITextFieldViewMode.WhileEditing




   }

}

class BlueViewController : SneakyViewController {

@IBOutlet weak var humanCode: UITextView!

 func hexStringFromData(data: NSData) -> String {
    var hexString = NSMutableString()
    var buffer = [UInt8](count:data.length, repeatedValue:0)
    data.getBytes(&buffer, length:data.length)
    for var i=0; i<buffer.count; i++ {
        if i % 4 == 0 && i != 0 {
            hexString.appendString(" ")
        }
        hexString.appendFormat("%02x", buffer[i])
      }
      return hexString
   }




    override func viewDidLoad() {
     super.viewDidLoad()

    let task = NSURLSession.sharedSession().dataTaskWithURL(url) {(data, response, error) in
        var length = data.length
        var chunkSize = 1024 * 10
        var offset = 0

        while offset < length {
            var currentChunkSize = length - offset>chunkSize ? chunkSize : length - offset
            var chunk = NSData(bytes: data.bytes + offset, length:currentChunkSize)
            offset += currentChunkSize
            var string = self.hexStringFromData(chunk)
            dispatch_sync(dispatch_get_main_queue()) {
                self.humanCode.text = self.humanCode.text + string
            }
        }
     }


    task.resume()

  }

  override func viewWillAppear(animated: Bool) {



    let task = NSURLSession.sharedSession().dataTaskWithURL(url) {(data, response, error) in
        var length = data.length
        var chunkSize = 1024 * 10
        var offset = 0

        while offset < length {
            var currentChunkSize = length - offset>chunkSize ? chunkSize : length - offset
            var chunk = NSData(bytes: data.bytes + offset, length:currentChunkSize)
            offset += currentChunkSize
            var string = self.hexStringFromData(chunk)
            dispatch_sync(dispatch_get_main_queue()) {
                self.humanCode.text = self.humanCode.text + string
            }
        }
     }


    task.resume()

  }

}
\$\endgroup\$
  • 2
    \$\begingroup\$ You should try to make the title describe what your code does - this will attract more reviewers. Right now, it sounds like you're asking for help fixing broken code, while you're actually asking for ways to improve the code. \$\endgroup\$ – Ivo Coumans Sep 23 '14 at 13:42
4
\$\begingroup\$

Your whitespace, both vertical and horizontal, is arbitrary and distracting and needs a lot of work. Xcode automatically inserts 4 spaces when you push tab. It also automatically indents virtually everything for you. Rarely is there ever a need to argue with Xcode's spacing (and Xcode is the only Swift IDE), so just let Xcode do its thing, and then become more consistent with your blank lines.

As to the speed issue, the real problem here is most likely purely to do with Swift's poor optimizations. Specifically, accessing arrays in loops is terrible with the default optimization levels.

There's a very good discussion of Swift's current array index problems in this StackOverflow post. It's definitely worth a read.

For right now, at the end of the day, if you need something that will perform fast, use Objective-C or C. If you need something that you can write fast, supposedly Swift, once you're comfortable with it, would be the choice. And in theory, eventually, Swift will actually be faster than Objective-C, because it's not doing the message sending that Objective-C does... but there are still some kinks to be worked out of Swift, and this is one of the big ones.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.