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

Objective-C转Swift:UnsafeMutableRawPointer指针偏移赋值报错求助

Fixing UnsafeMutableRawPointer Offset Issue When Porting RGB Array to UIImage from Objective-C to Swift

Let's break down what's going wrong here and fix it step by step.

The Core Problem

In your Objective-C code, pixels is a UInt32 * pointer—when you do pixels + i * width + j, the pointer advances by (i*width +j) elements of UInt32 (each 4 bytes). But in your Swift code, you're using UnsafeMutableRawPointer, which treats advanced(by:) as a byte offset. So your current code is shifting the pointer by way too few bytes (1 byte per step instead of 4), leading to corrupted memory and invalid pixel data.

The Fix

Instead of working with raw pointers directly, bind your allocated memory to a UInt32 typed pointer. This matches the behavior of your Objective-C code and makes pointer operations safe and intuitive.

Here's the corrected Swift code:

// First, make sure your RGBMake function returns UInt32 (matches OC's RGBAMake)
func RGBMake(r: Int, g: Int, b: Int, a: Int) -> UInt32 {
    return UInt32(a) << 24 | UInt32(b) << 16 | UInt32(g) << 8 | UInt32(r)
}

func imageWithGrayArray(_ orArr: [[Int]]) -> UIImage {
    let width = 512
    let height = 512
    let bytesPerPixel = 4
    let bytesPerRow = bytesPerPixel * width
    let bitsPerComponent = 8
    
    // Allocate memory and bind to UInt32 pointer (matches OC's UInt32* pixels)
    let pixelCount = width * height
    let pixelBytes = pixelCount * MemoryLayout<UInt32>.stride
    guard let pixels = malloc(pixelBytes)?.bindMemory(to: UInt32.self, capacity: pixelCount) else {
        fatalError("Failed to allocate pixel memory")
    }
    memset(pixels, 0, pixelBytes)
    
    for i in 0 ..< orArr.count {
        let subArray = orArr[i]
        for j in 0 ..< subArray.count {
            // Now we can access pixels like a typed array, just like OC
            let grayValue = subArray[j]
            pixels[i * width + j] = RGBMake(r: grayValue, g: grayValue, b: grayValue, a: 255)
        }
    }
    
    let colorSpace = CGColorSpaceCreateDeviceRGB()
    guard let context = CGContext(
        data: pixels,
        width: width,
        height: height,
        bitsPerComponent: bitsPerComponent,
        bytesPerRow: bytesPerRow,
        space: colorSpace,
        bitmapInfo: CGImageAlphaInfo.last.rawValue | CGImageByteOrderInfo.order32Big.rawValue
    ) else {
        free(pixels)
        fatalError("Failed to create bitmap context")
    }
    
    guard let cgImage = context.makeImage() else {
        free(pixels)
        fatalError("Failed to create CGImage")
    }
    
    let image = UIImage(cgImage: cgImage)
    free(pixels)
    return image
}

Key Changes Explained

  1. Typed Pointer Binding: bindMemory(to: UInt32.self, capacity: pixelCount) converts the raw pointer to a UnsafeMutablePointer<UInt32>. Now, when you do pixels[index], it automatically accesses the correct 4-byte UInt32 element—exactly like your Objective-C code.
  2. Correct Offset Calculation: i * width + j works as a direct index into the typed pointer, no manual byte math needed.
  3. Proper Type for RGB Value: The RGBMake function returns UInt32, matching the type expected by the pixel buffer (and OC's RGBAMake).
  4. Safety Improvements: Added guard clauses to handle memory allocation/context creation failures, and ensured we always free the allocated memory even if something goes wrong.
  5. Consistent Bytes Per Row: Used width instead of hardcoding 512 for bytesPerRow to keep the code maintainable.

Why Your Original Swift Code Failed

  • advanced(by: i * width + j) on UnsafeMutableRawPointer moves the pointer by i*width +j bytes, not elements. Since each pixel is 4 bytes, you needed to multiply by MemoryLayout<UInt32>.stride (which is 4) to get the correct offset.
  • storeBytes(of: ..., as: Int.self) was writing an Int (8 bytes on 64-bit systems) into a 4-byte UInt32 slot, causing memory overwrites and corruption.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:03:55