You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过代码统计Storyboard中UIViewController关联的Segue数量

Hey there! I've got a couple of solid approaches to count the number of segues linked to a specific UIViewController in a Storyboard. Let's break them down based on your use case:

方案1:解析Storyboard的XML结构(最通用、无依赖)

Storyboards are just XML files under the hood, so we can parse them directly using standard XML tools. Here's a Swift implementation that works on macOS or iOS (if you're building an internal tool):

import Foundation

func countSeguesForViewController(in storyboardPath: String, viewControllerID: String) -> Int {
    // Load the storyboard XML data
    guard let xmlData = try? Data(contentsOf: URL(fileURLWithPath: storyboardPath)),
          let xmlDoc = try? XMLDocument(data: xmlData, options: [.nodePreserveWhitespace]) else {
        print("Failed to load or parse storyboard file")
        return 0
    }
    
    // Locate the target view controller's parent scene node using its storyboard ID
    let sceneXPathQuery = "//scene[@sceneID]/objects/viewController[@storyboardIdentifier='\(viewControllerID)']/../.."
    guard let targetScene = xmlDoc.nodes(forXPath: sceneXPathQuery).first else {
        print("No view controller found with ID: \(viewControllerID)")
        return 0
    }
    
    // Extract the unique scene ID associated with the view controller
    guard let sceneID = targetScene.attribute(forName: "sceneID")?.stringValue else {
        print("Could not retrieve scene ID for target view controller")
        return 0
    }
    
    // Count all segues where the source matches our target scene ID
    let segueXPathQuery = "//segue[@source='\(sceneID)']"
    guard let segues = try? xmlDoc.nodes(forXPath: segueXPathQuery) else {
        return 0
    }
    
    return segues.count
}

// Example usage
let storyboardPath = "/Users/you/Projects/YourApp/Base.lproj/Main.storyboard"
let targetVCID = "ProfileViewController"
let segueCount = countSeguesForViewController(in: storyboardPath, viewControllerID: targetVCID)
print("Total segues linked to \(targetVCID): \(segueCount)")

How this works:

  • Each view controller in a Storyboard lives inside a <scene> node with a unique sceneID
  • Segues have a source attribute that references the sceneID of their originating view controller
  • We use XPath queries to first find the target scene, then count all segues pointing back to it

方案2:Command-Line Script with xmllint(快速验证)

If you just need a one-off count without writing a full program, use xmllint (preinstalled on macOS) to parse the XML directly from terminal:

# Replace these values with your own
STORYBOARD_PATH="/Users/you/Projects/YourApp/Base.lproj/Main.storyboard"
TARGET_VC_ID="SettingsViewController"

# Step 1: Get the scene ID of the target view controller
SCENE_ID=$(xmllint --xpath "//scene[@sceneID]/objects/viewController[@storyboardIdentifier='$TARGET_VC_ID']/../@sceneID" "$STORYBOARD_PATH" | grep -o 'sceneID="[^"]*"' | cut -d'"' -f2)

# Step 2: Count all segues originating from that scene
SEGUE_COUNT=$(xmllint --xpath "count(//segue[@source='$SCENE_ID'])" "$STORYBOARD_PATH")

echo "Segue count for $TARGET_VC_ID: $SEGUE_COUNT"

Pro Tip:

If your view controller doesn't have a storyboard ID, you can use its custom class name instead. Replace the first XPath query with:

SCENE_ID=$(xmllint --xpath "//scene[@sceneID]/objects/viewController[@customClass='$TARGET_VC_CLASS']/../@sceneID" "$STORYBOARD_PATH" | grep -o 'sceneID="[^"]*"' | cut -d'"' -f2)

方案3:Xcode Private API(仅限内部调试工具)

If you're building a tool for your team (not for the App Store), you can use Xcode's private frameworks to directly load and inspect the Storyboard. Note: This API is unsupported and may break with Xcode updates.

Here's an Objective-C example:

#import <Foundation/Foundation.h>
#import <IBFoundation/IBFoundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSString *storyboardPath = @"/Users/you/Projects/YourApp/Base.lproj/Main.storyboard";
        NSString *targetVCID = @"HomeViewController";
        
        // Load the storyboard using Xcode's private IBStoryboard class
        IBStoryboard *storyboard = [[IBStoryboard alloc] initWithContentsOfFile:storyboardPath error:nil];
        if (!storyboard) {
            NSLog(@"Failed to load storyboard");
            return 1;
        }
        
        // Find the target view controller by its ID
        IBObjectContainer *container = storyboard.objectContainer;
        IBUIViewController *targetVC = nil;
        for (IBUIViewController *vc in [container objectsOfClass:[IBUIViewController class]]) {
            if ([vc.storyboardIdentifier isEqualToString:targetVCID]) {
                targetVC = vc;
                break;
            }
        }
        
        // Count outgoing segues
        if (targetVC) {
            NSLog(@"Segue count: %lu", (unsigned long)[targetVC.outgoingSegues count]);
        } else {
            NSLog(@"View controller not found");
        }
    }
    return 0;
}

To compile this, you need to link against Xcode's private framework:

clang -o segueCounter segueCounter.m -framework Foundation -framework IBFoundation -F/Applications/Xcode.app/Contents/SharedFrameworks/

Key Notes:

  • For nested view controllers (e.g., inside a UINavigationController), make sure your XPath or API query targets the correct child view controller node
  • Always prefer the XML parsing approach for production tools since it's stable and doesn't rely on private APIs

内容的提问来源于stack exchange,提问作者Reimond Hill

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:22:13