如何在辅助功能智能反转模式下为App跳过特定颜色?
Great question—you’re absolutely right that accessibilityIgnoresInvertColors only works at the view or object level, which doesn’t solve your need to target a single color (like blue) to exclude from inversion. Let’s break down solutions for both native UI elements (like labels/buttons) and images with mixed black/blue text to get the behavior you want:
1. Handling Native UI Elements (e.g., UILabel, UIButton Text)
For UI components where you set colors directly in code, you can listen for system invert status changes and adjust colors dynamically:
- First, register to get notified when Smart Invert is toggled:
NotificationCenter.default.addObserver( self, selector: #selector(handleInvertStatusUpdate), name: UIAccessibility.invertColorsStatusDidChangeNotification, object: nil )
- Then, in the callback, check if inversion is active and adjust colors to keep blue untouched:
// Store your original colors somewhere to revert later private let originalLabelColor: UIColor = .black private let targetBlue: UIColor = UIColor(red: 0, green: 0.478, blue: 1, alpha: 1) // Adjust to your exact blue @objc private func handleInvertStatusUpdate() { let isInvertEnabled = UIAccessibility.isInvertColorsEnabled if isInvertEnabled { // For non-blue colors: apply inversion; for blue: keep original label.textColor = label.textColor == targetBlue ? targetBlue : invertedColor(for: label.textColor) } else { // Revert to original colors when inversion is off label.textColor = originalLabelColor } } // Helper to calculate inverted color (matches classic invert behavior) private func invertedColor(for color: UIColor) -> UIColor { var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0 color.getRed(&red, green: &green, blue: &blue, alpha: &alpha) return UIColor(red: 1 - red, green: 1 - green, blue: 1 - blue, alpha: alpha) }
This approach requires you to track original colors for elements you want to adjust, but it’s straightforward for controlled UI.
2. Handling Images with Mixed Black/Blue Text
For images, you can’t use accessibilityIgnoresInvertColors (it would skip the whole image), so we’ll use Core Image filters to invert everything except the blue regions:
- Create a helper function to process the image:
func processImageForSmartInvert(_ originalImage: UIImage, targetBlue: UIColor) -> UIImage? { guard let ciImage = CIImage(image: originalImage) else { return nil } let blueCIColor = CIColor(color: targetBlue) // Step 1: Create a mask of the blue regions in the image let maskFilter = CIFilter(name: "CIColorThreshold")! maskFilter.setValue(ciImage, forKey: kCIInputImageKey) maskFilter.setValue( CIVector(x: blueCIColor.red, y: blueCIColor.green, z: blueCIColor.blue), forKey: "inputColor" ) // Step 2: Invert the entire image let invertFilter = CIFilter(name: "CIColorInvert")! invertFilter.setValue(ciImage, forKey: kCIInputImageKey) guard let invertedImage = invertFilter.outputImage else { return nil } // Step 3: Combine the inverted image with the original, using the mask to keep blue intact let compositeFilter = CIFilter(name: "CIBlendWithMask")! compositeFilter.setValue(invertedImage, forKey: kCIInputImageKey) compositeFilter.setValue(ciImage, forKey: kCIInputBackgroundImageKey) compositeFilter.setValue(maskFilter.outputImage, forKey: kCIInputMaskImageKey) // Convert back to UIImage guard let outputCIImage = compositeFilter.outputImage else { return nil } let context = CIContext(options: [.useSoftwareRenderer: false]) guard let cgImage = context.createCGImage(outputCIImage, from: outputCIImage.extent) else { return nil } return UIImage(cgImage: cgImage) }
- Then, use the same invert status notification to swap the processed image in/out:
private let originalImage: UIImage = UIImage(named: "your-image-name")! @objc private func handleInvertStatusUpdate() { let isInvertEnabled = UIAccessibility.isInvertColorsEnabled let targetBlue = UIColor(red: 0, green: 0.478, blue: 1, alpha: 1) imageView.image = isInvertEnabled ? processImageForSmartInvert(originalImage, targetBlue: targetBlue) : originalImage }
3. Global App-Wide Approach (Optional)
If you want this behavior across your entire app, you can:
- Create a
UIColorextension that overridesresolvedColor(with:)to return the original blue (and inverted colors for others) when inversion is active. - Subclass
UIImageViewto automatically apply the image processing logic above.
Just be cautious with global overrides—test thoroughly to avoid breaking third-party or system UI components.
Note: System Smart Invert uses a more nuanced algorithm than simple RGB inversion (it preserves certain UI elements like images by default). If you need perfect alignment with Smart Invert’s behavior, you may need to adjust the color inversion logic to match Apple’s implementation.
内容的提问来源于stack exchange,提问作者Preeti Rani

