diff --git src/bp-core/bp-core-buddybar.php src/bp-core/bp-core-buddybar.php
index ca87d9a..e64e960 100644
--- src/bp-core/bp-core-buddybar.php
+++ src/bp-core/bp-core-buddybar.php
@@ -50,28 +50,29 @@ function bp_core_new_nav_item( $args = '' ) {
 	);
 
 	$r = wp_parse_args( $args, $defaults );
-	extract( $r, EXTR_SKIP );
 
 	// If we don't have the required info we need, don't create this subnav item
-	if ( empty( $name ) || empty( $slug ) )
+	if ( empty( $r['name'] ) || empty( $r['slug'] ) ) {
 		return false;
+	}
 
 	// If this is for site admins only and the user is not one, don't create the subnav item
-	if ( !empty( $site_admin_only ) && !bp_current_user_can( 'bp_moderate' ) )
+	if ( ! empty( $r['site_admin_only'] ) && ! bp_current_user_can( 'bp_moderate' ) ) {
 		return false;
+	}
 
-	if ( empty( $item_css_id ) )
-		$item_css_id = $slug;
-
-	$bp->bp_nav[$slug] = array(
-		'name'                    => $name,
-		'slug'                    => $slug,
-		'link'                    => trailingslashit( bp_loggedin_user_domain() . $slug ),
-		'css_id'                  => $item_css_id,
-		'show_for_displayed_user' => $show_for_displayed_user,
-		'position'                => $position,
-		'screen_function'         => &$screen_function,
-		'default_subnav_slug'	  => $default_subnav_slug
+	if ( empty( $r['item_css_id'] ) )
+		$r['item_css_id'] = $r['slug'];
+
+	$bp->bp_nav[$r['slug']] = array(
+		'name'                    => $r['name'],
+		'slug'                    => $r['slug'],
+		'link'                    => trailingslashit( bp_loggedin_user_domain() . $r['slug'] ),
+		'css_id'                  => $r['item_css_id'],
+		'show_for_displayed_user' => $r['show_for_displayed_user'],
+		'position'                => $r['position'],
+		'screen_function'         => &$r['screen_function'],
+		'default_subnav_slug'	  => $r['default_subnav_slug']
 	);
 
  	/**
@@ -79,33 +80,34 @@ function bp_core_new_nav_item( $args = '' ) {
 	 * the logged in user is not the displayed user
 	 * looking at their own profile, don't create the nav item.
 	 */
-	if ( empty( $show_for_displayed_user ) && !bp_user_has_access() )
+	if ( empty( $r['show_for_displayed_user'] ) && ! bp_user_has_access() ) {
 		return false;
+	}
 
 	/**
  	 * If the nav item is visible, we are not viewing a user, and this is a root
 	 * component, don't attach the default subnav function so we can display a
 	 * directory or something else.
  	 */
-	if ( ( -1 != $position ) && bp_is_root_component( $slug ) && !bp_displayed_user_id() )
+	if ( ( -1 != $r['position'] ) && bp_is_root_component( $r['slug'] ) && ! bp_displayed_user_id() )
 		return;
 
 	// Look for current component
-	if ( bp_is_current_component( $slug ) || bp_is_current_item( $slug ) ) {
+	if ( bp_is_current_component( $r['slug'] ) || bp_is_current_item( $r['slug'] ) ) {
 
 		// The requested URL has explicitly included the default subnav
 		// (eg: http://example.com/members/membername/activity/just-me/)
 		// The canonical version will not contain this subnav slug.
-		if ( !empty( $default_subnav_slug ) && bp_is_current_action( $default_subnav_slug ) && !bp_action_variable( 0 ) ) {
+		if ( ! empty( $r['default_subnav_slug'] ) && bp_is_current_action( $r['default_subnav_slug'] ) && !bp_action_variable( 0 ) ) {
 			unset( $bp->canonical_stack['action'] );
 		} elseif ( ! bp_current_action() ) {
 
 			// Add our screen hook if screen function is callable
-			if ( is_callable( $screen_function ) ) {
-				add_action( 'bp_screens', $screen_function, 3 );
+			if ( is_callable( $r['screen_function'] ) ) {
+				add_action( 'bp_screens', $r['screen_function'], 3 );
 			}
 
-			if ( !empty( $default_subnav_slug ) ) {
+			if ( ! empty( $r['default_subnav_slug'] ) ) {
 
 				/**
 				 * Filters the default component subnav item.
@@ -116,7 +118,7 @@ function bp_core_new_nav_item( $args = '' ) {
 				 *                                    to select when clicked.
 				 * @param array  $r                   Parsed arguments for the nav item.
 				 */
-				$bp->current_action = apply_filters( 'bp_default_component_subnav', $default_subnav_slug, $r );
+				$bp->current_action = apply_filters( 'bp_default_component_subnav', $r['default_subnav_slug'], $r );
 			}
 		}
 	}
@@ -154,43 +156,42 @@ function bp_core_new_nav_default( $args = '' ) {
 	);
 
 	$r = wp_parse_args( $args, $defaults );
-	extract( $r, EXTR_SKIP );
 
-	if ( $function = $bp->bp_nav[$parent_slug]['screen_function'] ) {
+	if ( $function = $bp->bp_nav[$r['parent_slug']]['screen_function'] ) {
 		// Remove our screen hook if screen function is callable
 		if ( is_callable( $function ) ) {
 			remove_action( 'bp_screens', $function, 3 );
 		}
 	}
 
-	$bp->bp_nav[$parent_slug]['screen_function'] = &$screen_function;
+	$bp->bp_nav[$r['parent_slug']]['screen_function'] = &$r['screen_function'];
 
-	if ( bp_is_current_component( $parent_slug ) ) {
+	if ( bp_is_current_component( $r['parent_slug'] ) ) {
 
 		// The only way to tell whether to set the subnav is to peek at the unfiltered_uri
 		// Find the component
-		$component_uri_key = array_search( $parent_slug, $bp->unfiltered_uri );
+		$component_uri_key = array_search( $r['parent_slug'], $bp->unfiltered_uri );
 
 		if ( false !== $component_uri_key ) {
-			if ( !empty( $bp->unfiltered_uri[$component_uri_key + 1] ) ) {
+			if ( ! empty( $bp->unfiltered_uri[$component_uri_key + 1] ) ) {
 				$unfiltered_action = $bp->unfiltered_uri[$component_uri_key + 1];
 			}
 		}
 
 		// No subnav item has been requested in the URL, so set a new nav default
 		if ( empty( $unfiltered_action ) ) {
-			if ( !bp_is_current_action( $subnav_slug ) ) {
-				if ( is_callable( $screen_function ) ) {
-					add_action( 'bp_screens', $screen_function, 3 );
+			if ( ! bp_is_current_action( $r['subnav_slug'] ) ) {
+				if ( is_callable( $r['screen_function'] ) ) {
+					add_action( 'bp_screens', $r['screen_function'], 3 );
 				}
 
-				$bp->current_action = $subnav_slug;
+				$bp->current_action = $r['subnav_slug'];
 				unset( $bp->canonical_stack['action'] );
 			}
 
 		// The URL is explicitly requesting the new subnav item, but should be
 		// directed to the canonical URL
-		} elseif ( $unfiltered_action == $subnav_slug ) {
+		} elseif ( $unfiltered_action == $r['subnav_slug'] ) {
 			unset( $bp->canonical_stack['action'] );
 
 		// In all other cases (including the case where the original subnav item
@@ -359,6 +360,171 @@ function bp_core_new_subnav_item( $args = '' ) {
 }
 
 /**
+ * Add a subnav link to the BuddyPress navigation.
+ *
+ * @param array $args {
+ *     Array describing the new subnav item.
+ *     @type string $name Display name for the subnav item.
+ *     @type string $slug Unique URL slug for the subnav item.
+ *     @type string $parent_slug Slug of the top-level nav item under which the
+ *           new subnav item should be added.
+ *     @type string $parent_url URL of the parent nav item.
+ *     @type bool|string $item_css_id Optional. 'id' attribute for the nav
+ *           item. Default: the value of $slug.
+ *     @type bool $user_has_access Optional. True if the logged-in user has
+ *           access to the subnav item, otherwise false. Can be set dynamically
+ *           when registering the subnav; eg, use bp_is_my_profile() to restrict
+ *           access to profile owners only. Default: true.
+ *     @type bool $site_admin_only Optional. Whether the nav item should be
+ *           visible only to site admins (those with the 'bp_moderate' cap).
+ *           Default: false.
+ *     @type int $position Optional. Numerical index specifying where the item
+ *           should appear in the subnav array. Default: 90.
+ *     @type callable $screen_function The callback function that will run
+ *           when the nav item is clicked.
+ *     @type string $link Optional. The URL that the subnav item should point
+ *           to. Defaults to a value generated from the $parent_url + $slug.
+ *     @type bool $show_in_admin_bar Optional. Whether the nav item should be
+ *           added into the group's "Edit" Admin Bar menu for group admins.
+ *           Default: false.
+ * }
+ * @return bool|null Returns false on failure.
+ */
+function bp_core_create_subnav_link( $args = '' ) {
+	$bp = buddypress();
+
+	$r = wp_parse_args( $args, array(
+		'name'              => false, // Display name for the nav item
+		'slug'              => false, // URL slug for the nav item
+		'parent_slug'       => false, // URL slug of the parent nav item
+		'parent_url'        => false, // URL of the parent item
+		'item_css_id'       => false, // The CSS ID to apply to the HTML of the nav item
+		'user_has_access'   => true,  // Can the logged in user see this nav item?
+		'no_access_url'     => '',
+		'site_admin_only'   => false, // Can only site admins see this nav item?
+		'position'          => 90,    // Index of where this nav item should be positioned
+		'screen_function'   => false, // The name of the function to run when clicked
+		'link'              => '',    // The link for the subnav item; optional, not usually required.
+		'show_in_admin_bar' => false, // Show the Manage link in the current group's "Edit" Admin Bar menu
+	) );
+
+	// If we don't have the required info we need, don't create this subnav item
+	if ( empty( $r['name'] ) || empty( $r['slug'] ) || empty( $r['parent_slug'] ) || empty( $r['parent_url'] ) || empty( $r['screen_function'] ) )
+		return false;
+
+	// Link was not forced, so create one
+	if ( empty( $r['link'] ) ) {
+		$r['link'] = trailingslashit( $r['parent_url'] . $r['slug'] );
+
+		// If this sub item is the default for its parent, skip the slug
+		if ( ! empty( $bp->bp_nav[$r['parent_slug']]['default_subnav_slug'] ) && $r['slug'] == $bp->bp_nav[$r['parent_slug']]['default_subnav_slug'] ) {
+			$r['link'] = trailingslashit( $r['parent_url'] );
+		}
+	}
+
+	// If this is for site admins only and the user is not one, don't create the subnav item
+	if ( ! empty( $r['site_admin_only'] ) && ! bp_current_user_can( 'bp_moderate' ) ) {
+		return false;
+	}
+
+	if ( empty( $r['item_css_id'] ) ) {
+		$r['item_css_id'] = $r['slug'];
+	}
+
+	$subnav_item = array(
+		'name'              => $r['name'],
+		'link'              => $r['link'],
+		'slug'              => $r['slug'],
+		'css_id'            => $r['item_css_id'],
+		'position'          => $r['position'],
+		'user_has_access'   => $r['user_has_access'],
+		'no_access_url'     => $r['no_access_url'],
+		'screen_function'   => &$r['screen_function'],
+		'show_in_admin_bar' => (bool) $r['show_in_admin_bar'],
+	);
+
+	$bp->bp_options_nav[$r['parent_slug']][$r['slug']] = $subnav_item;
+}
+
+/**
+ * Register a screen function, whether or not a related subnav link exists.
+ *
+ * @param array $args {
+ *     Array describing the new subnav item.
+ *     @type string $slug Unique URL slug for the subnav item.
+ *     @type string $parent_slug Slug of the top-level nav item under which the
+ *           new subnav item should be added.
+ *     @type string $parent_url URL of the parent nav item.
+ *     @type bool $user_has_access Optional. True if the logged-in user has
+ *           access to the subnav item, otherwise false. Can be set dynamically
+ *           when registering the subnav; eg, use bp_is_my_profile() to restrict
+ *           access to profile owners only. Default: true.
+ *     @type bool $site_admin_only Optional. Whether the nav item should be
+ *           visible only to site admins (those with the 'bp_moderate' cap).
+ *           Default: false.
+ *     @type int $position Optional. Numerical index specifying where the item
+ *           should appear in the subnav array. Default: 90.
+ *     @type callable $screen_function The callback function that will run
+ *           when the nav item is clicked.
+ *     @type string $link Optional. The URL that the subnav item should point
+ *           to. Defaults to a value generated from the $parent_url + $slug.
+ *     @type bool $show_in_admin_bar Optional. Whether the nav item should be
+ *           added into the group's "Edit" Admin Bar menu for group admins.
+ *           Default: false.
+ * }
+ * @return bool|null Returns false on failure.
+ */
+function bp_core_register_subnav_screen_function( $args = '' ) {
+	$r = wp_parse_args( $args, array(
+		'slug'              => false, // URL slug for the screen
+		'parent_slug'       => false, // URL slug of the parent screen
+		'user_has_access'   => true,  // Can the user visit this screen?
+		'no_access_url'     => '',
+		'site_admin_only'   => false, // Can only site admins visit this screen?
+		'screen_function'   => false, // The name of the function to run when clicked
+	) );
+
+	/**
+	 * Hook the screen function for the added subnav item. But this only needs to
+	 * be done if this subnav item is the current view, and the user has access to the
+	 * subnav item. We figure out whether we're currently viewing this subnav by
+	 * checking the following two conditions:
+	 *   (1) Either:
+	 *	     (a) the parent slug matches the current_component, or
+	 *	     (b) the parent slug matches the current_item
+	 *   (2) And either:
+	 *	     (a) the current_action matches $slug, or
+	 *       (b) there is no current_action (ie, this is the default subnav for the parent nav)
+	 *	     and this subnav item is the default for the parent item (which we check by
+	 *	     comparing this subnav item's screen function with the screen function of the
+	 *	     parent nav item in $bp->bp_nav). This condition only arises when viewing a
+	 *	     user, since groups should always have an action set.
+	 */
+
+	// If we *don't* meet condition (1), return
+	if ( ! bp_is_current_component( $r['parent_slug'] ) && ! bp_is_current_item( $r['parent_slug'] ) ) {
+		return;
+	}
+
+	// If we *do* meet condition (2), then the added subnav item is currently being requested
+	if ( ( bp_current_action() && bp_is_current_action( $r['slug'] ) ) || ( bp_is_user() && ! bp_current_action() && ( $r['screen_function'] == $bp->bp_nav[$parent_slug]['screen_function'] ) ) ) {
+
+		// If this is for site admins only and the user is not one, don't create the subnav item
+		if ( ! empty( $r['site_admin_only'] ) && ! bp_current_user_can( 'bp_moderate' ) ) {
+			return false;
+		}
+
+		$hooked = bp_core_maybe_hook_new_subnav_screen_function( $r );
+
+		// If redirect args have been returned, perform the redirect now
+		if ( ! empty( $hooked['status'] ) && 'failure' === $hooked['status'] && isset( $hooked['redirect_args'] ) ) {
+			bp_core_no_access( $hooked['redirect_args'] );
+		}
+	}
+
+}
+
+/**
  * For a given subnav item, either hook the screen function or generate redirect arguments, as necessary.
  *
  * @since BuddyPress (2.1.0)
@@ -372,8 +538,14 @@ function bp_core_maybe_hook_new_subnav_screen_function( $subnav_item ) {
 		'status' => '',
 	);
 
+	// Is this accessible by site admins only?
+	$site_admin_restricted = false;
+	if ( ! empty( $subnav_item['site_admin_only'] ) && ! bp_current_user_can( 'bp_moderate' ) ) {
+		$site_admin_restricted = true;
+	}
+
 	// User has access, so let's try to hook the display callback
-	if ( ! empty( $subnav_item['user_has_access'] ) ) {
+	if ( ! empty( $subnav_item['user_has_access'] ) && ! $site_admin_restricted ) {
 
 		// Screen function is invalid
 		if ( ! is_callable( $subnav_item['screen_function'] ) ) {
diff --git src/bp-core/bp-core-component.php src/bp-core/bp-core-component.php
index a24de99..6775cb7 100644
--- src/bp-core/bp-core-component.php
+++ src/bp-core/bp-core-component.php
@@ -469,7 +469,8 @@ class BP_Component {
 			// Sub nav items are not required
 			if ( !empty( $sub_nav ) ) {
 				foreach( (array) $sub_nav as $nav ) {
-					bp_core_new_subnav_item( $nav );
+					bp_core_create_subnav_link( $nav );
+					bp_core_register_subnav_screen_function( $nav );
 				}
 			}
 		}
diff --git src/bp-groups/classes/class-bp-group-extension.php src/bp-groups/classes/class-bp-group-extension.php
index 02374dd..8f36af6 100644
--- src/bp-groups/classes/class-bp-group-extension.php
+++ src/bp-groups/classes/class-bp-group-extension.php
@@ -735,12 +735,13 @@ class BP_Group_Extension {
 			return;
 		}
 
+		// If the user can see the nav item, we create it.
 		$user_can_see_nav_item = $this->user_can_see_nav_item();
 
 		if ( $user_can_see_nav_item ) {
 			$group_permalink = bp_get_group_permalink( groups_get_current_group() );
 
-			bp_core_new_subnav_item( array(
+			bp_core_create_subnav_link( array(
 				'name'            => ! $this->nav_item_name ? $this->name : $this->nav_item_name,
 				'slug'            => $this->slug,
 				'parent_slug'     => bp_get_current_group_slug(),
@@ -751,6 +752,21 @@ class BP_Group_Extension {
 				'user_has_access' => $user_can_see_nav_item,
 				'no_access_url'   => $group_permalink,
 			) );
+		}
+
+		// If the user can visit the screen, we register it.
+		$user_can_visit = $this->user_can_visit();
+
+		if ( $user_can_visit ) {
+			$group_permalink = bp_get_group_permalink( groups_get_current_group() );
+
+			bp_core_register_subnav_screen_function( array(
+				'slug'            => $this->slug,
+				'parent_slug'     => bp_get_current_group_slug(),
+				'screen_function' => array( &$this, '_display_hook' ),
+				'user_has_access' => $user_can_visit,
+				'no_access_url'   => $group_permalink,
+			) );
 
 			// When we are viewing the extension display page, set the title and options title
 			if ( bp_is_current_action( $this->slug ) ) {
diff --git src/bp-xprofile/bp-xprofile-loader.php src/bp-xprofile/bp-xprofile-loader.php
index a38b21b..b9f9dac 100644
--- src/bp-xprofile/bp-xprofile-loader.php
+++ src/bp-xprofile/bp-xprofile-loader.php
@@ -260,7 +260,7 @@ class BP_XProfile_Component extends BP_Component {
 		// Get the settings slug
 		$settings_slug = bp_get_settings_slug();
 
-		bp_core_new_subnav_item( array(
+		$nav_args = array(
 			'name'            => _x( 'Profile Visibility', 'Profile settings sub nav', 'buddypress' ),
 			'slug'            => 'profile',
 			'parent_url'      => trailingslashit( $user_domain . $settings_slug ),
@@ -268,7 +268,10 @@ class BP_XProfile_Component extends BP_Component {
 			'screen_function' => 'bp_xprofile_screen_settings',
 			'position'        => 30,
 			'user_has_access' => bp_core_can_edit_settings()
-		) );
+		);
+
+		bp_core_create_subnav_link( $nav_args );
+		bp_core_register_subnav_screen_function( $nav_args );
 	}
 
 	/**
