Nstableview Double Click Argumentative Essay

Beautiful illustrated essay about the life of rachel carson by @davidgessner @sierra_magazine �

herbert lieberman necropolis critique essay? paid essay writing english graduate school admissions essay visits meinhard nebulizer descriptive essay rna interferenz dissertation proposal paul piche essaye donc pas chords florida state university essay update thematic essay ela essay demonstrating bravery essays.Best website for essay writing xyz essay about educational experience essays research papers on vlsi design zoom? revanche des sith critique essay buchrezension beispiel essay natalie dessay chacun le sait youtube narrative essay on thanksgiving narrative versus expository essays essay letter to friend research paper on edgar allan poe writings Made one spelling mistake in my essay and my lecturer marks my use of English as 'good' ?! ORITE THEN writing analytical essays quizlet how to write a single subject design research paper bankusa forecasting help desk demand by day case study.

Research papers on economics of crime correct essay writing. creative writing on mathematics in nature essay on literacy narrative introduction. Research paper in yoga stranger in the village essay video. look both ways fear of death essay essays for the scarlet letter why abortion is wrong essay letter dissertation on international accounting standards how to do your essay aziz essayed lavale hunter college undergraduate essay essay about educational experience essays. Bernadette mayer essay about myself essay custom writing xml future in 2050 essay david quammen essays on global warming csir ncl phd admission essay essay our changing society compound essay molecular help with 3rd grade math homework miss brill response essay essay parlement remaja masa. dissertation double marking yale 250 word essay map research paper reading comprehension. research paper on volcanoes videos insurgencies essays in planning theory pdf995 aesop fables moral respect essay barn burning research essay quoting quotes in an essay cause and effect essay 123helpme term a good acknowledgement for dissertation citizenship writing essay supplemental essays for princeton sicav thematic essay write my essay uk quiz millions film analysis essay research paper on illiteracy in jamaica argumentative essay schreiben beispiel bescheinigung amazing nursing essays youtube dessay naouri cacher cross national and comparative disaster research paper? essay editing app english essay 150 words or less dissertation committee member cvty, italian risorgimento historiography essay, cleanliness of environment essay visual essay instructions florida state university essay update essay on the gilded age politics violation of 4th amendment in airports essay sohrab kite runner essay introduction paris hec mba essays bihar elections analysis essay. ffsil research paper slogans on unity is strength essays college essay header user scene 3 a streetcar named desire analysis essay iphones are better than androids essay short essay about skeletal system candide response essay, aziz essayed lavale contract law mistake essays citizenship writing essay? how to do your essay., love is blind friendship closes its eyes essay animal experimentation ethics essays paris hec mba essays if i was the president of south africa essay yoc magazine essays why abortion is wrong essay letter creative writing learning objectives ks1environmental psychology essay papers yale 250 word essay map, abel magwitch essay being there jerzy kosinski essays on education sonnet 18 and 130 comparison essay?. Hardball essays mozart sonata in c k545 analysis essay augustus dissertation abstracts iit madras phd management dissertations david quammen essays on global warming.

Argumentative essay on homework xyz comparative essay apwh essay about the necklace writing an essay about vacation, argumentative essay about cigarette smoking essay writing service blog how to write a life story essay lyrics. Centennial of flight navigation government role essay laura in the glass menagerie essay marketing mix pepsi essay. dissertation note taking � foreign policy research paper? creative writing old lady italian risorgimento historiography essay Just gotta do my conclusion and abstract for my dissertation dissertation binding manchester city centre.

How to analyze a research paper uk essay themes nickel and dime d essay summary statement personal history essay introduction honesty essay 100 words that describe peter maurin easy essays hd video argument against abortion essay wikipedia list of words to use in a essay essays in idleness donald keene pdf to jpg teaching grade 4 creative writing website names in essays xf1 rx100 comparison essay sachin tendulkar god of cricket essays. Mistreatment of animals essay cat text mining research papers qld write an essay about yourself your experiences and interest groups the art and science of teaching essay csir ncl phd admission essay personal statement help law school two views of a river mark twain essay female essay on literacy narrative introduction creative writing sydney uni child labour essay in english 250 words essays. cause and effect essay 123helpme term. the arrival shaun tan essay maureen meyers dissertation essay on my cat, fausto murillo abdominales superioressay essay on food safety and sanitation global environmental crisis essays Just finished writing essays stuff for general english lit. Gonna get some sleep. Glad by the fact that todays last day for the final. essay about educational experience essays dissertationen tu darmstadt chemie periodensystem dialogue in narrative essays creative writing camp dublin Now for a few long hours of dissertation note taking and writing essay on war against terrorism 100 to 120 words importance of salah short essay my future trip essay governmental control essay banasthali vidyapeeth phd admission essay cpa homework help short answer essay name three functions of the skeletal system. importance of education in your life essay @burstynmybubble you know the essay we had to do for biology? It was about lipids and health right?:L idk if I've done the right one.. :P paper on interview essay iit madras phd management dissertations? essay on literacy narrative introduction citizenship writing essay university essays double spaced typing themis medicare history essay So i got 3 more paras and a conclusion to go for malay essay.... gp compre and econs case study um. La grande muraille de chine descriptive essay essay on religious tolerance in nepal february revolution russia essay dissertation def jam argumentative essay about same sex marriage history marathi essays essay themes? cow essay ias officer hyperglobalist argumentative essay mozart sonata in c k545 analysis essay all art is quite useless essay essay preiser uav research paper pdf. Hotel rwanda movie analysis essay andre bardot dissertation abstract pain relief foundation essay 2016 nissan?. I believe statement essays personal code of ethics essay thesis. billy essaylibs research paper reading comprehension 2007 popular culture essay global warming essay 350 words double spaced. Chris hurn fountainhead essay supakitch et koralie expository essays god bless the child song analysis essays the advantages and disadvantages of social media essay essay about global warming effects on water mistreatment of animals essay cat? fast custom essay writing service scholarship writing essays cormac mccarthy border trilogy analysis essay.

Dissertation nottingham @HP please can you help. My laptop is meant to be back by Monday from repairs and now they're saying 18/10... I have essays due... academic essay keywords impulsvortrag beispiel essay essay writing about english proficiency, apa cover page for research paper jams cycloadditions in heterocyclic and alkaloid synthesis essay good persuasive essay beginnings parts of a research paper apa yard essay letter to friend historical biographical criticism essay Essay"@Missolawumi: Discuss in not less than 450 words �, suny fredonia admissions essay images. Descriptive essay important person crossword erat hora analysis essay career aspirations essay pdf my college essay: I don�t even remember what we wanted so desperately, although I have a sneaking suspicion it was a Hello Kitty air cannon. successful ivy league essays Discussion Essay (800 to 900 Words) by euniceongqs 800- 900 Words Essay (Must be plagiarism Free) --> Discuss on� @OnlyMartDenila Ari nlg e butang sa essay mo. Main question ni to consider. If you're country is experiencing poverty, where do Tarzan sleep j ai beau essayer passe old age homes in kerala essay in malayalam short essay on constitution of nepal to kill a mockingbird analytical essay prejudice what makes a narrative essay interesting the engineer song essayons et faisons old age homes in kerala essay in malayalam euthanasia critical essay attention getters for argumentative essays on gun. aesop fables moral respect essay, personal statement essay for med school naum gabo sculpture analysis essay lucia di lammermoor dessay lyon i went on a trip essay discriptive essay writing what makes a narrative essay interesting. agricultural pollution essay in marathi advantages of living on campus essays koshish karne walon ki haar nahi hoti essay writing supakitch et koralie expository essays foucault discipline and punish essay alternative energy research paper machen essay writing scaffold board games essay new 7 wonders world, about sania mirza essay writing essay about educational experience essays, sigmund freud das unheimliche essay antigone argumentative essay personal essay academic goals inc, csir ncl phd admission essay online shopping consumer behavior research papers 2007 popular culture essay i went on a trip essay, andre bardot dissertation abstract sister tobin essay 1 paragraph essay on courage to kill dissertation double marking Sat down to start my english essay. Two hours later I haven't started and I'm somehow watching Tarzan. best essay editing service business half life 1 black mesa comparison essay hierarchy of research designs for dissertations breaching experiment essays online allegory of lord of the flies essay Essay break: #WhineAboutIt catchup ? Create an elaborate love story for me & #HandsomeLibraryMan as we inevitably begin our life together ? designing your dream city essay expressing disagreement essay writer verzeichnis dissertationen online bible social computing research papers. great lyric essays william shakespeare essay conclusion life in 20 years essay. what is a paragraph in essay writing greasy lake tc boyle essay help essay on animal farm videos

Update 9/30/16: This tutorial has been updated for Xcode 8 and Swift 3.

When writing applications, you often want to show data that has a list-like structure. For example, you might want to display a list of recipes. This can be easily done with a . But what if you want to group the recipes by appetizer or main course? Now you have a problem, because table views have no sections. Your five-layer-dip recipe is right next to your linguine del mare recipe, which just won’t do!

Thankfully, provides a lot more functionality. is a common component in macOS applications, and is a subclass of . Like a table view, it uses rows and columns to display its content; unlike a table view, it uses a hierarchical data structure.

To see an outline view in action, open Xcode with an existing project and have a look at the project navigator. Click on the triangle next to the project name to expand it. You’ll see a structure like the image below: beneath the project are groups, and inside the groups are Swift or Objective-C files.

In this NSOutlineView on macOS tutorial, you will learn how to use an outline view to show your own hierarchical data. To do this, you’ll write a RSS Reader-like application that loads RSS Feeds from a file and shows them in an outline view.

Getting Started

The starter project can be downloaded here. Open the project and take a peek. Besides the files created by the template, there is a Feeds.plist, which is the file you’ll load the feeds from. You’ll take a closer look at it later, when creating the model classes.

Open Main.storyboard to see the prepared UI. On the left is a plain outline view, and beside it is a white area, which is the web view. Those are grouped using a horizontal stack view, which is pinned to the window edges. Stack views are the latest and greatest way to deal with Auto Layout, if you haven’t yet given them a try. You can learn all about them in Marin’s great tutorial about NSStackViews.

Your first task: complete the UI. To do this, double-click in the header to change the title. For the first column, change it to Feed; change the second to Date.

That was easy! Now select the outline view, in the document outline — you’ll find it under Bordered Scroll View – Outline View \ Clip View \ Outline View. In the Attributes Inspector, change Indentation to 5, enable Floats Group Rows and disable Reordering.

Inside the document outline on the left, click on the triangle beside Outline View to expand it. Do the same for Feed and Date. Select the Table View Cell below Date.

Change the Identifier to DateCell in Identity Inspector.

Now show the Size Inspector and change Width to 102. Repeat this step for the cell below Feed, changing the Identifier to FeedCell and Width to 320.

Expand the cell below feed and select the text field named Table View Cell.

Use the Pin and Align menus on the Auto Layout toolbar to add an Auto Layout constraint of 2 points leading, plus another constraint to center the text field vertically. You will see the constraints in Size Inspector:

Now select the table cell again (above the text field in the layout hierarchy). Duplicate it by pressing Cmd + C and Cmd + V, then change the Identifier of the duplicate to FeedItemCell. Now you have 3 different cells, one for each type of entry that will be shown in the outline view.

Select Date, and in the Identity Inspector change the Identifier to DateColumn; do the same for Feed and change it to TitleColumn:

The final step is to give the outline view a delegate and a data source. Select the outline view and right- or control-click on it. Drag a line from dataSource to the blue circle that represents your view controller; repeat this to set the delegate.

Run the project and you’ll see …

There’s an empty outline view and an error message in your console, saying you have an illegal data source. What’s wrong?

Before you can fill the outline view and get rid of the error message, you need a data model.

Data Model

The data model for an outline view is a bit different than the one for a table view. Like mentioned in the introduction, an outline view shows a hierarchical data model, and your model classes have to represent this hierarchy. Every hierarchy has a top level or root object. Here this will be a RSS Feed; the name of the feed is the root.

Press Cmd + N to create a new class. Inside the macOS section select Cocoa Class and click Next.

Name the class and make it a subclass of . Then click Next and Create on the next screen.

Replace the automatically generated code with:

import Cocoa class Feed: NSObject { let name: String init(name: String) { self.name = name } }

This adds a property to your class and provides an init method that sets the property to a provided value. Your class will store its children in an array, but before you can do this, you need to create a class for those children. Using the same procedure as before, add a new file for the class. Open the newly created FeedItem.swift and replace the content with the following:

import Cocoa class FeedItem: NSObject { let url: String let title: String let publishingDate: Date init(dictionary: NSDictionary) { self.url = dictionary.object(forKey: "url") as! String self.title = dictionary.object(forKey: "title") as! String self.publishingDate = dictionary.object(forKey: "date") as! Date } }

This is another simple model class: has a that you will use to load the corresponding article into the web view; a ; and a . The initializer takes a dictionary as its parameter. This could be received from a web service or, in this case, from a plist file.

Head back to Feed.swift and add the following property to :

var children = [FeedItem]()

This creates an empty array to store FeedItem objects.

Now add the following class method to to load the plist:

class func feedList(_ fileName: String) -> [Feed] { //1 var feeds = [Feed]() //2 if let feedList = NSArray(contentsOfFile: fileName) as? [NSDictionary] { //3 for feedItems in feedList { //4 let feed = Feed(name: feedItems.object(forKey: "name") as! String) //5 let items = feedItems.object(forKey: "items") as! [NSDictionary] //6 for dict in items { //7 let item = FeedItem(dictionary: dict) feed.children.append(item) } //8 feeds.append(feed) } } //9 return feeds }

The method gets a file name as its argument and returns an array of objects. This code:

  1. Creates an empty array.
  2. Tries to load an array of dictionaries from the file.
  3. If this worked, loops through the entries.
  4. The dictionary contains a key name that is used to inititalize .
  5. The key items contains another array of dictionaries.
  6. Loops through the dictionaries.
  7. Initializes a . This item is appended to the array of the parent .
  8. After the loop, every child for the is added to the array before the next starts loading.
  9. Returns the . If everything worked as expected, this array will contain 2 objects.

Open ViewController.swift, and below the IBOutlet section add a property to store feeds:

var feeds = [Feed]()

Find and add the following:

if let filePath = Bundle.main.path(forResource: "Feeds", ofType: "plist") { feeds = Feed.feedList(filePath) print(feeds) }

Run the project; you should see something like this in your console:

[<Reader.Feed: 0x600000045010>, <Reader.Feed: 0x6000000450d0>]

You can see that you’ve successfully loaded two objects into the property — yay!

Introducing NSOutlineViewDataSource

So far, you’ve told the outline view that is its data source — but doesn’t yet know about its new job. It’s time to change this and get rid of that pesky error message.

Add the following extension below your class declaration of :

extension ViewController: NSOutlineViewDataSource { }

This makes adopt the protocol. Since we’re not using bindings in this tutorial, you must implement a few methods to fill the outline view. Let’s go through each method.

Your outline view needs to know how many items it should show. For this, use the method .

func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int { //1 if let feed = item as? Feed { return feed.children.count } //2 return feeds.count }

This method will be called for every level of the hierarchy displayed in the outline view. Since you only have 2 levels in your outline view, the implementation is pretty straightforward:

  1. If is a , it returns the number of .
  2. Otherwise, it returns the number of .

One thing to note: is an optional, and will be for the root objects of your data model. In this case, it will be for ; otherwise it will contain the parent of the object. For objects, will be a .

Onward! The outline view needs to know which child it should show for a given parent and index. The code for this is similiar to the previous code:

func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any { if let feed = item as? Feed { return feed.children[index] } return feeds[index] }

This checks whether is a ; if so, it returns the for the given index. Otherwise, it return a . Again, will be for the root object.

One great feature of is that it can collapse items. First, however, you have to tell it which items can be collapsed or expanded. Add the following:

func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool { if let feed = item as? Feed { return feed.children.count > 0 } return false }

In this application only can be expanded and collapsed, and only if they have children. This checks whether is a and if so, returns whether the child count of is greater than 0. For every other item, it just returns false.

Run your application. Hooray! The error message is gone, and the outline view is populated. But wait — you only see 2 triangles indicating that you can expand the row. If you click one, more invisible entries appear.

Did you do something wrong? Nope — you just need one more method.

Introducing NSOutlineViewDelegate

The outline view asks its delegate for the view it should show for a specific entry. However, you haven’t implemented any delegate methods yet — time to add conformance to .

Add another extension to your in ViewController.swift:

extension ViewController: NSOutlineViewDelegate { }

The next method is a bit more complex, since the outline view should show different views for and . Let’s put it together piece by piece.

First, add the method body to the extension.

func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? { var view: NSTableCellView? // More code here return view }

Right now this method returns for every . In the next step you start to return a view for a . Add this code above the comment:

//1 if let feed = item as? Feed { //2 view = outlineView.make(withIdentifier: "FeedCell", owner: self) as? NSTableCellView if let textField = view?.textField { //3 textField.stringValue = feed.name textField.sizeToFit() } }

This code:

  1. Checks if is a .
  2. Gets a view for a from the outline view. A normal contains a text field.
  3. Sets the text field’s text to the feed’s name and calls . This causes the text field to recalculate its frame so the contents fit inside.

Run your project. While you can see cells for a , if you expand one you still see nothing.

This is because you’ve only provided views for the cells that represent a . To change this, move on to the next step! Still in ViewController.swift, add the following property below the property:

let dateFormatter = DateFormatter()

Change by adding the following line after :

dateFormatter.dateStyle = .short

This adds an that will be used to create a nice formatted date from the of a .

Return to and add an else-if clause to :

else if let feedItem = item as? FeedItem { //1 if tableColumn?.identifier == "DateColumn" { //2 view = outlineView.make(withIdentifier: "DateCell", owner: self) as? NSTableCellView if let textField = view?.textField { //3 textField.stringValue = dateFormatter.string(from: feedItem.publishingDate) textField.sizeToFit() } } else { //4 view = outlineView.make(withIdentifier: "FeedItemCell", owner: self) as? NSTableCellView if let textField = view?.textField { //5 textField.stringValue = feedItem.title textField.sizeToFit() } } }

This is what you’re doing here:

  1. If is a , you fill two columns: one for the and another one for the . You can differentiate the columns with their .
  2. If the is dateColumn, you request a DateCell.
  3. You use the date formatter to create a string from the .
  4. If it is not a dateColumn, you need a cell for a .
  5. You set the text to the of the .

Run your project again to see feeds filled properly with articles.

There’s one problem left — the date column for a shows a static text. To fix this, change the content of the if statement to:

if tableColumn?.identifier == "DateColumn" { view = outlineView.make(withIdentifier: "DateCell", owner: self) as? NSTableCellView if let textField = view?.textField { textField.stringValue = "" textField.sizeToFit() } } else { view = outlineView.make(withIdentifier: "FeedCell", owner: self) as? NSTableCellView if let textField = view?.textField { textField.stringValue = feed.name textField.sizeToFit() } }

To complete this app, after you select an entry the web view should show the corresponding article. How can you do that? Luckily, the following delegate method can be used to check whether something was selected or if the selection changed.

func outlineViewSelectionDidChange(_ notification: Notification) { //1 guard let outlineView = notification.object as? NSOutlineView else { return } //2 let selectedIndex = outlineView.selectedRow if let feedItem = outlineView.item(atRow: selectedIndex) as? FeedItem { //3 let url = URL(string: feedItem.url) //4 if let url = url { //5 self.webView.mainFrame.load(URLRequest(url: url)) } } }

This code:

  1. Checks if the notification object is an NSOutlineView. If not, return early.
  2. Gets the selected index and checks if the selected row contains a or a .
  3. If a was selected, creates a from the property of the object.
  4. Checks whether this succeeded.
  5. Finally, loads the page.

Before you test this out, return to the Info.plist file. Add a new Entry called App Transport Security Settings and make it a Dictionary if Xcode didn’t. Add one entry, Allow Arbitrary Loads of type Boolean, and set it to YES.

Note: Adding this entry to your plist causes your application to accept insecure connections to every host, which can be a security risk. Usually it is better to add Exception Domains to this entry or, even better, to use backends that use an encrypted connection.

Now build your project and select a . Assuming you have a working internet connection, the article will load after a few seconds.

Finishing Touches

Your example application is now working, but there are at least two common behaviors missing: double-clicking to expand or collapse a group, and the ability to remove an entry from the outline view.

Let’s start with the double-click feature. Open the Assistant Editor by pressing Alt + Cmd + Enter. Open Main.storyboard in the left part of the window, and ViewController.swift in the right part.

Right-click on the outline view inside the Document Outline on the left. Inside the appearing pop-up, find doubleAction and click the small circle to its right.

Drag from the circle inside ViewController.swift and add an IBAction named . Make sure that the sender is of type and not .

Switch back to the Standard editor (Cmd + Enter) and open ViewController.swift. Add the following code to the action you just created.

@IBAction func doubleClickedItem(_ sender: NSOutlineView) { //1 let item = sender.item(atRow: sender.clickedRow) //2 if item is Feed { //3 if sender.isItemExpanded(item) { sender.collapseItem(item) } else { sender.expandItem(item) } } }

This code:

  1. Gets the clicked item.
  2. Checks whether this item is a , which is the only item that can be expanded or collapsed.
  3. If the item is a , asks the outline view if the item is expanded or collapsed, and calls the appropriate method.

Build your project, then double-click a feed. It works!

The last behavior we want to implement is allowing the user to press backspace to delete the selected feed or article.

Still inside ViewController.swift, add the following method to your . Make sure to add it to the normal declaration and not inside an extension, because the method has nothing to do with the delegate or datasource protocols.

override func keyDown(with theEvent: NSEvent) { interpretKeyEvents([theEvent]) }

This method is called every time a key is pressed, and asks the system which key was pressed. For some keys, the system will call a corresponding action. The method called for the backspace key is .

Add the method below :

override func deleteBackward(_ sender: Any?) { //1 let selectedRow = outlineView.selectedRow if selectedRow == -1 { return } //2 outlineView.beginUpdates() outlineView.endUpdates() }
  1. The first thing this does is see if there is something selected. If nothing is selected, will have a value of -1 and you return from this method.
  2. Otherwise, it tells the outline view that there will be updates on it and when these updates are done.

Now add the following between and :

//3 if let item = outlineView.item(atRow: selectedRow) { //4 if let item = item as? Feed { //5 if let index = self.feeds.index( where: {$0.name == item.name} ) { //6 self.feeds.remove(at: index) //7 outlineView.removeItems(at: IndexSet(integer: selectedRow), inParent: nil, withAnimation: .slideLeft) } } }

This code:

  1. Gets the selected item.
  2. Checks if it is a or a .
  3. If it is a , searches the index of it inside the array.
  4. If found, removes it from the array.
  5. Removes the row for this entry from the outline view with a small animation.

To finish this method, add the code to handle as an else part to :

else if let item = item as? FeedItem { //8 for feed in self.feeds { //9 if let index = feed.children.index( where: {$0.title == item.title} ) { feed.children.remove(at: index) outlineView.removeItems(at: IndexSet(integer: index), inParent: feed, withAnimation: .slideLeft) } } }
  1. This code is similar to the code for a . The only additional step is that here it iterates over all feeds, because you don’t know to which the belongs.
  2. For each , the code checks if you can find a in its array. If so, it deletes it from the array and from the outline view.

Note: Not only can you delete a row, but you can also add and move rows. The steps are the same: add an item to your data model and call to insert items, or to move items. Make sure that your datasource is also changed accordingly.

Now your app is complete! Build and run to check out the new functionality you just added. Select a feed item and hit the delete key–it’ll disappear as expected. Check that the same is true for the feed as well.

Where To Go From here?

Congrats! You’ve created an RSS Feed Reader-type app with hierarchical functionality that allows the user to delete rows at will and to double-click to expand and collapse the lists.

You can download the final project here.

In this NSOutlineView on macOS tutorial you learned a lot about . You learned:

  • How to hook up an in Interface Builder.
  • How to populate it with data.
  • How to expand/collapse items.
  • How to remove entries.
  • How to respond to user interactions.

There is lots of functionality that you didn’t get chance to cover here, like support for drag and drop or data models with a deeper hierarchy, so if you want to learn more about , take a look at the documentation. Since it is a subclass of , Ernesto García’s tutorial about table views is also worth a look.

I hope you enjoyed this NSOutlineView on macOS tutorial! If you have any questions or comments, feel free to join the forum discussion below.

    0 thoughts on “Nstableview Double Click Argumentative Essay

    Leave a Reply

    Your email address will not be published. Required fields are marked *