diff --git a/Harbor.xcodeproj/project.pbxproj b/Harbor.xcodeproj/project.pbxproj index b9d7666..fe774a0 100644 --- a/Harbor.xcodeproj/project.pbxproj +++ b/Harbor.xcodeproj/project.pbxproj @@ -274,6 +274,7 @@ D0610E181A0C952E0056B8A3 /* Project object */ = { isa = PBXProject; attributes = { + LastSwiftUpdateCheck = 0700; LastUpgradeCheck = 0610; ORGANIZATIONNAME = dvm; TargetAttributes = { diff --git a/Harbor/Account.swift b/Harbor/Account.swift index 6fb1eeb..8526acc 100644 --- a/Harbor/Account.swift +++ b/Harbor/Account.swift @@ -12,7 +12,7 @@ class Account : NSObject{ var projects: [Project] = [] override init(){ - println("made an account") + print("made an account") super.init() } diff --git a/Harbor/AppDelegate.swift b/Harbor/AppDelegate.swift index 2a5a2a8..6394105 100644 --- a/Harbor/AppDelegate.swift +++ b/Harbor/AppDelegate.swift @@ -15,17 +15,16 @@ class AppDelegate: NSObject, NSApplicationDelegate { var statusView: StatusView? var projectList: [Project]? let currentRunLoop: NSRunLoop = NSRunLoop.currentRunLoop() - + func applicationDidFinishLaunching(aNotification: NSNotification) { - var aDecoder = NSCoder() self.fetchApiKeys { (projects) -> () in - println(projects.count) + print(projects.count) } preferencesPaneWindow = PreferencesPaneWindow(windowNibName: "PreferencesPaneWindow") preferencesPaneWindow?.prefManagedObjectContext = self.managedObjectContext! - println(self.managedObjectContext!) + print(self.managedObjectContext!) statusView = StatusView() fetchRefreshRate() } @@ -38,52 +37,41 @@ class AppDelegate: NSObject, NSApplicationDelegate { func hidePopover(sender: AnyObject) { statusView!.hidePopover() } - + func applicationWillTerminate(aNotification: NSNotification) { // Insert code here to tear down your application } - - // MARK: CoreData Fetch - + // MARK: CoreData Fetch func fetchRefreshRate() { - var request: NSFetchRequest = NSFetchRequest(entityName: "DMAccount") - + let request: NSFetchRequest = NSFetchRequest(entityName: "DMAccount") request.sortDescriptors = [NSSortDescriptor(key: "accountDescription", ascending: true)] - - var errorPointer: NSErrorPointer = NSErrorPointer() - - var projectArray: [Project] = [] - - if let fetchResults = managedObjectContext!.executeFetchRequest(request, error: errorPointer) as? [DMAccount] { - - if fetchResults.count > 0 { - - if let firstAccountRate = fetchResults.first?.refreshRate? { - setupTimer((firstAccountRate as NSString).doubleValue) - } else { - setupTimer(120) - } + + do { + let account = try managedObjectContext!.executeFetchRequest(request).first as? DMAccount + if let refreshRate = account?.refreshRate { + setupTimer((refreshRate as NSString).doubleValue) + } else { + setupTimer(120) } - } else { - println("fetch error on Popover for refreshRate / no fetchResults") + } catch let error as NSError { + print(error) } } func setupTimer(refreshRate: Double) { - var loopStartTime: NSDate = NSDate(timeIntervalSinceNow: 1.0) - - var timer = NSTimer(timeInterval: refreshRate, target: self, selector:"updateData", userInfo: nil, repeats: true) + + let timer = NSTimer(timeInterval: refreshRate, target: self, selector:"updateData", userInfo: nil, repeats: true) currentRunLoop.addTimer(timer, forMode: NSDefaultRunLoopMode) - - println("refresh rate: \(refreshRate)") + + print("refresh rate: \(refreshRate)") } func updateData(){ fetchApiKeys { (projects) -> () in self.statusView!.updateUI() - println("updateData completion block") + print("updateData completion block") } } @@ -96,17 +84,17 @@ class AppDelegate: NSObject, NSApplicationDelegate { var projectArray: [Project] = [] - if let fetchResults = managedObjectContext!.executeFetchRequest(request, error: errorPointer) as? [DMAccount] { + if let fetchResults = managedObjectContext!.executeFetchRequest(request) as? [DMAccount] { for account in fetchResults { self.retrieveProjectsForAccount(account, completionClosure: { (projects) -> () in projectArray += projects completionClosure(projects: projectArray) }) - println("apiKey: \(account.apiKey)") + print("apiKey: \(account.apiKey)") } } else { - println("fetch error on Popover for apiKey") + print("fetch error on Popover for apiKey") } } @@ -121,51 +109,54 @@ class AppDelegate: NSObject, NSApplicationDelegate { var errorPointer: NSErrorPointer = NSErrorPointer() - let fetchResults = managedObjectContext!.executeFetchRequest(request, error: errorPointer) as? [DMProject] + let fetchResults = managedObjectContext!.executeFetchRequest(request) as? [DMProject] return fetchResults! } func processProject (hash: AnyObject, account: DMAccount) { - var project = Project() - project.id = Int(hash.objectForKey("id") as NSNumber) - project.repositoryName = (hash.objectForKey("repository_name") as String) + let project = Project() + project.id = Int(hash.objectForKey("id") as! NSNumber) + project.repositoryName = (hash.objectForKey("repository_name") as! String) let dmProjectFetchResults = self.fetchProjectsWithID("\(project.id!)") if dmProjectFetchResults.count == 0 { project.active = true; - var dmProject: DMProject = NSEntityDescription.insertNewObjectForEntityForName("DMProject", inManagedObjectContext: self.managedObjectContext!) as DMProject + let dmProject: DMProject = NSEntityDescription.insertNewObjectForEntityForName("DMProject", inManagedObjectContext: self.managedObjectContext!) as! DMProject dmProject.id = "\(project.id!)" dmProject.repositoryName = project.repositoryName! dmProject.account = account dmProject.active = true - var errorPointer: NSErrorPointer = NSErrorPointer() + let errorPointer: NSErrorPointer = NSErrorPointer() - self.managedObjectContext?.save(errorPointer) + do { + try self.managedObjectContext?.save() + } catch var error as NSError { + errorPointer.memory = error + } } else if dmProjectFetchResults.count == 1 { project.active = dmProjectFetchResults.first?.active.boolValue } else { - println("more than one project with ID: \(project.id!)") + print("more than one project with ID: \(project.id!)") } - var projectBuildJson: Array = hash.objectForKey("builds") as Array - var projectBuilds: [Build] = [] - + let projectBuildJson: Array = hash.objectForKey("builds") as! Array +  for buildHash in projectBuildJson { - var build = Build() - build.id = Int(buildHash.objectForKey("id") as NSNumber) - build.uuid = (buildHash.objectForKey("uuid") as String) - build.status = (buildHash.objectForKey("status") as String) - build.commitId = (buildHash.objectForKey("commit_id") as String) - build.message = (buildHash.objectForKey("message") as String) - build.branch = (buildHash.objectForKey("branch") as String) + let build = Build() + build.id = Int(buildHash.objectForKey("id") as! NSNumber) + build.uuid = (buildHash.objectForKey("uuid") as! String) + build.status = (buildHash.objectForKey("status") as! String) + build.commitId = (buildHash.objectForKey("commit_id") as! String) + build.message = (buildHash.objectForKey("message") as! String) + build.branch = (buildHash.objectForKey("branch") as! String) project.builds.append(build) } @@ -174,11 +165,11 @@ class AppDelegate: NSObject, NSApplicationDelegate { self.projectList?.append(project) if project.builds.first!.status == "testing"{ - println("\(project.repositoryName!) & \(project.builds.first!.status!)") + print("\(project.repositoryName!) & \(project.builds.first!.status!)") self.statusView?.hasPendingBuild = false } else if project.builds.first!.status != "success" { - println("\(project.repositoryName!) & \(project.builds.first!.status!)") + print("\(project.repositoryName!) & \(project.builds.first!.status!)") self.statusView!.hasFailedBuild = true } } @@ -189,16 +180,16 @@ class AppDelegate: NSObject, NSApplicationDelegate { func retrieveProjectsForAccount(account: DMAccount, completionClosure: (projects: [Project]) -> ()){ - var urlWithKey = "https://www.codeship.io/api/v1/projects.json?api_key=" + account.apiKey - var urlRequest: NSURLRequest = NSURLRequest(URL: NSURL(string:urlWithKey)!); + let urlWithKey = "https://www.codeship.io/api/v1/projects.json?api_key=" + account.apiKey + let urlRequest: NSURLRequest = NSURLRequest(URL: NSURL(string:urlWithKey)!); - NSURLConnection.sendAsynchronousRequest(urlRequest, queue: NSOperationQueue.mainQueue()) { (urlResponse, data, error) -> Void in + NSURLConnection.sendAsynchronousRequest(urlRequest, queue: NSOperationQueue.mainQueue()) { (urlResponse, data, error) -> Void in - var responseDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments, error: nil) as NSDictionary + let responseDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments) as! NSDictionary self.projectList = [] - var projectsArray: Array = responseDictionary.objectForKey("projects") as Array - + let projectsArray: Array = responseDictionary.objectForKey("projects") as!Array + self.statusView?.hasFailedBuild = false self.statusView?.hasPendingBuild = false @@ -214,29 +205,37 @@ class AppDelegate: NSObject, NSApplicationDelegate { } // MARK: - Core Data stack - + lazy var applicationDocumentsDirectory: NSURL = { // The directory the application uses to store the Core Data store file. This code uses a directory named "ekh.Harbor" in the user's Application Support directory. let urls = NSFileManager.defaultManager().URLsForDirectory(.ApplicationSupportDirectory, inDomains: .UserDomainMask) let appSupportURL = urls[urls.count - 1] as NSURL return appSupportURL.URLByAppendingPathComponent("dvm.Harbor") - }() - + }() + lazy var managedObjectModel: NSManagedObjectModel = { // The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model. let modelURL = NSBundle.mainBundle().URLForResource("Harbor", withExtension: "momd")! return NSManagedObjectModel(contentsOfURL: modelURL)! - }() - + }() + lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = { // The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it. (The directory for the store is created, if necessary.) This property is optional since there are legitimate error conditions that could cause the creation of the store to fail. let fileManager = NSFileManager.defaultManager() var shouldFail = false var error: NSError? = nil var failureReason = "There was an error creating or loading the application's saved data." - + // Make sure the application files directory is there - let propertiesOpt = self.applicationDocumentsDirectory.resourceValuesForKeys([NSURLIsDirectoryKey], error: &error) + let propertiesOpt: [NSObject: AnyObject]? + do { + propertiesOpt = try self.applicationDocumentsDirectory.resourceValuesForKeys([NSURLIsDirectoryKey]) + } catch var error1 as NSError { + error = error1 + propertiesOpt = nil + } catch { + fatalError() + } if let properties = propertiesOpt { if !properties[NSURLIsDirectoryKey]!.boolValue { failureReason = "Expected a folder to store application data, found a file \(self.applicationDocumentsDirectory.path)." @@ -244,7 +243,13 @@ class AppDelegate: NSObject, NSApplicationDelegate { } } else if error!.code == NSFileReadNoSuchFileError { error = nil - fileManager.createDirectoryAtPath(self.applicationDocumentsDirectory.path!, withIntermediateDirectories: true, attributes: nil, error: &error) + do { + dtry fileManager.createDirectoryAtPath(self.applicationDocumentsDirectory.path!, withIntermediateDirectories: true, attributes: nil) + } catch var error1 as NSError { + error = error1 + } catch { + fatalError() + } } // Create the coordinator and store @@ -252,8 +257,13 @@ class AppDelegate: NSObject, NSApplicationDelegate { if !shouldFail && (error == nil) { coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel) let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("Harbor.storedata") - if coordinator!.addPersistentStoreWithType(NSXMLStoreType, configuration: nil, URL: url, options: nil, error: &error) == nil { + do { + try coordinator!.addPersistentStoreWithType(NSXMLStoreType, configuration: nil, URL: url, options: nil) + } catch var error1 as NSError { + error = error1 coordinator = nil + } catch { + fatalError() } } @@ -265,14 +275,14 @@ class AppDelegate: NSObject, NSApplicationDelegate { if error != nil { dict[NSUnderlyingErrorKey] = error } - error = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict) + error = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict as [NSObject : AnyObject]) NSApplication.sharedApplication().presentError(error!) return nil } else { return coordinator } - }() - + }() + lazy var managedObjectContext: NSManagedObjectContext? = { // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail. let coordinator = self.persistentStoreCoordinator @@ -282,10 +292,10 @@ class AppDelegate: NSObject, NSApplicationDelegate { var managedObjectContext = NSManagedObjectContext() managedObjectContext.persistentStoreCoordinator = coordinator return managedObjectContext - }() - + }() + // MARK: - Core Data Saving and Undo support - + @IBAction func saveAction(sender: AnyObject!) { // Performs the save action for the application, which is to send the save: message to the application's managed object context. Any encountered errors are presented to the user. if let moc = self.managedObjectContext { @@ -293,12 +303,12 @@ class AppDelegate: NSObject, NSApplicationDelegate { NSLog("\(NSStringFromClass(self.dynamicType)) unable to commit editing before saving") } var error: NSError? = nil - if moc.hasChanges && !moc.save(&error) { + if moc.hasChanges && !moc.save() { NSApplication.sharedApplication().presentError(error!) } } } - + func windowWillReturnUndoManager(window: NSWindow) -> NSUndoManager? { // Returns the NSUndoManager for the application. In this case, the manager returned is that of the managed object context for the application. if let moc = self.managedObjectContext { @@ -307,7 +317,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { return nil } } - + func applicationShouldTerminate(sender: NSApplication) -> NSApplicationTerminateReply { // Save changes in the application's managed object context before the application terminates. @@ -322,7 +332,10 @@ class AppDelegate: NSObject, NSApplicationDelegate { } var error: NSError? = nil - if !moc.save(&error) { + do { + try moc.save() + } catch var error1 as NSError { + error = error1 // Customize this code block to include application-specific recovery steps. let result = sender.presentError(error!) if (result) { @@ -348,6 +361,6 @@ class AppDelegate: NSObject, NSApplicationDelegate { // If we got here, it is time to quit. return .TerminateNow } - + } diff --git a/Harbor/PopoverViewController.swift b/Harbor/PopoverViewController.swift index 48584fb..2755bd8 100644 --- a/Harbor/PopoverViewController.swift +++ b/Harbor/PopoverViewController.swift @@ -13,7 +13,7 @@ class PopoverViewController: NSViewController, NSTableViewDataSource, NSTableVie dynamic var projectList: [Project]? dynamic var managedObjectContext: NSManagedObjectContext? - let appDelegate: AppDelegate = (NSApplication.sharedApplication().delegate as AppDelegate) + let appDelegate: AppDelegate = (NSApplication.sharedApplication().delegate as! AppDelegate) @IBAction func quitButton(sender: AnyObject) { NSApplication.sharedApplication().terminate(self) @@ -38,13 +38,13 @@ class PopoverViewController: NSViewController, NSTableViewDataSource, NSTableVie super.loadView() projectList = [] - var bariolBold16: NSFont = NSFont (name: "Bariol-Bold", size: 16)! + let bariolBold16: NSFont = NSFont (name: "Bariol-Bold", size: 16)! self.titleLabel.font = bariolBold16 } override func viewDidAppear() { self.refreshTableView() - println("projectlist count at reload data \(projectList!.count)") + print("projectlist count at reload data \(projectList!.count)") } func refreshTableView() { @@ -68,8 +68,8 @@ class PopoverViewController: NSViewController, NSTableViewDataSource, NSTableVie row rowIndex: Int) -> AnyObject! { if !projectList!.isEmpty { - var project: Project = projectList![rowIndex] - var recentBuild: Build = project.builds.first! + let project: Project = projectList![rowIndex] + let recentBuild: Build = project.builds.first! if aTableColumn.identifier == "statusImageColumn" { @@ -89,14 +89,14 @@ class PopoverViewController: NSViewController, NSTableViewDataSource, NSTableVie } else if aTableColumn.identifier == "buildInfoColumn" { - var bariolBold: NSFont = NSFont (name: "Bariol-Bold", size: 13)! - var repoAttrs = [NSFontAttributeName : bariolBold] - var projectBuildSummary = NSMutableAttributedString(string: + let bariolBold: NSFont = NSFont (name: "Bariol-Bold", size: 13)! + let repoAttrs = [NSFontAttributeName : bariolBold] + let projectBuildSummary = NSMutableAttributedString(string: "\(project.repositoryName!.capitalizedString)\n", attributes: repoAttrs) - var bariolLight: NSFont = NSFont (name: "Bariol-Light", size: 11)! - var commitAttrs = [NSFontAttributeName : bariolLight] - var buildMessage = NSMutableAttributedString(string: "\(recentBuild.message!)", attributes: commitAttrs) + let bariolLight: NSFont = NSFont (name: "Bariol-Light", size: 11)! + let commitAttrs = [NSFontAttributeName : bariolLight] + let buildMessage = NSMutableAttributedString(string: "\(recentBuild.message!)", attributes: commitAttrs) projectBuildSummary.appendAttributedString(buildMessage) return projectBuildSummary diff --git a/Harbor/PreferencesPaneWindow.swift b/Harbor/PreferencesPaneWindow.swift index 7fead96..ac20ff5 100644 --- a/Harbor/PreferencesPaneWindow.swift +++ b/Harbor/PreferencesPaneWindow.swift @@ -24,7 +24,7 @@ class PreferencesPaneWindow: NSWindowController, NSWindowDelegate { override func windowDidLoad() { super.windowDidLoad() - var bariolBold: NSFont = NSFont (name: "Bariol-Bold", size: 15)! + let bariolBold: NSFont = NSFont (name: "Bariol-Bold", size: 15)! accountNameLabel.font = bariolBold apiKeyLabel.font = bariolBold refreshRateLabel.font = bariolBold @@ -32,14 +32,19 @@ class PreferencesPaneWindow: NSWindowController, NSWindowDelegate { tableView.sortDescriptors = [sortDescriptor] } - func windowWillClose(notification: NSNotification!) { - let appDelegate = (NSApplication.sharedApplication().delegate as AppDelegate) + func windowWillClose(notification: NSNotification) { + let appDelegate = (NSApplication.sharedApplication().delegate as! AppDelegate) appDelegate.showPopover(self) } + @IBAction func saveButton(sender: AnyObject) { let errorPointer = NSErrorPointer() - prefManagedObjectContext?.save(errorPointer) + do { + try prefManagedObjectContext?.save() + } catch var error as NSError { + errorPointer.memory = error + } self.close() } diff --git a/Harbor/StatusView.swift b/Harbor/StatusView.swift index 999967f..47ec5f1 100644 --- a/Harbor/StatusView.swift +++ b/Harbor/StatusView.swift @@ -13,7 +13,7 @@ class StatusView: NSView, NSMenuDelegate, NSPopoverDelegate { var hasFailedBuild: Bool? var hasPendingBuild: Bool? - let appDelegate: AppDelegate = (NSApplication.sharedApplication().delegate as AppDelegate) + let appDelegate: AppDelegate = (NSApplication.sharedApplication().delegate as! AppDelegate) var managedObjectContext: NSManagedObjectContext? var imageView: NSImageView @@ -23,8 +23,7 @@ class StatusView: NSView, NSMenuDelegate, NSPopoverDelegate { var statusItem: NSStatusItem var statusItemMenu: NSMenu - //so - you have to instantiate all the properties of the class before calling super. - // you can then use the awake from nib like a viewDidLoad to call things on self. + required init(coder aDecoder: (NSCoder!)) { active = false @@ -38,8 +37,6 @@ class StatusView: NSView, NSMenuDelegate, NSPopoverDelegate { statusItemMenu = NSMenu() statusItem.menu = statusItemMenu - super.init() - self.addSubview(imageView) statusItem.view = self self.managedObjectContext = appDelegate.managedObjectContext! @@ -47,7 +44,7 @@ class StatusView: NSView, NSMenuDelegate, NSPopoverDelegate { } - override init() { + convenience init() { active = false hasFailedBuild? = false hasPendingBuild? = false @@ -60,7 +57,7 @@ class StatusView: NSView, NSMenuDelegate, NSPopoverDelegate { statusItemMenu = NSMenu() statusItem.menu = statusItemMenu - super.init(frame: imageView.frame) + self.init(frame: imageView.frame) self.addSubview(imageView) statusItem.view = self @@ -79,7 +76,7 @@ class StatusView: NSView, NSMenuDelegate, NSPopoverDelegate { } - func setActive(isActive: Bool) + func setIsActive(isActive: Bool) { active = isActive; self.updateUI() @@ -87,11 +84,11 @@ class StatusView: NSView, NSMenuDelegate, NSPopoverDelegate { func updateUI() { - if self.hasPendingBuild? == true { + if self.hasPendingBuild == true { self.imageView.image = NSImage(named: "codeshipLogo_black") //add rotation - } else if self.hasFailedBuild? == true { + } else if self.hasFailedBuild == true { self.imageView.image = NSImage(named: "codeshipLogo_red") } else { @@ -135,16 +132,16 @@ class StatusView: NSView, NSMenuDelegate, NSPopoverDelegate { if(!popover!.shown){ popover!.showRelativeToRect(self.frame, ofView: self, preferredEdge: 1) - self.setActive(true) + self.setIsActive(true) } } func hidePopover() { - if (popover? != nil && popover!.shown){ + if (popover != nil && popover!.shown){ popover!.close() - self.setActive(false) + self.setIsActive(false) } }