我在Swift中发现了内存泄漏.它给了我噩梦,因为我的代码到处都是小泄漏,然后我设法将它减少到这个小例子,
import UIKit
enum LeakingEnum {
case
LeakCase,
AnotherLeakCase
}
class Primitive {
var lightingType: LeakingEnum = .LeakCase
var mysub : [Int] = []
init() {
mysub.append(80)
}
}
class ViewController: UIViewController {
var prim: Primitive?
override func viewDidLoad() {
super.viewDidLoad()
prim = Primitive()
}
}
Run Code Online (Sandbox Code Playgroud)
如果您在iPhone上运行此程序并使用仪器配置文件,您会发现此漏洞Array._copyToNewBuffer,
如果我删除了呼叫mysub.append,它将停止泄漏.如果我从中删除枚举Primitive,它也会停止泄漏.我有枚举泄漏的所有类都是这样的.Swift枚举发生了什么?
在iPhone6和iPad Pro上都可以在Swift 3,Xcode 8.2.1和iOS 10.2中重现.无法在模拟器或iOS 9.3.2设备中重现.您可以在此处下载最小样本应用程序:https://github.com/endavid/SwiftLeaks
这是一个已知的错误?有什么工作吗?
编辑:
因为这让我想起了另一个枚举错误,Accessor只在Swift 1.2/2.0 Release版本中提供了错误的值,我试着让enum成为一个@objc Int枚举,但它仍然泄漏.然而,lightingType直接制作Int确实可以解决泄漏...
Edit2: 将我的iPhone更新到10.3并将Xcode更新到8.3之后,泄漏就消失了.这似乎是iOS 10.2的问题......
有没有办法在git中共享存储库的历史记录而无需再次克隆整个文件夹?相当于Mercurial的东西
hg share project project-branch
Run Code Online (Sandbox Code Playgroud)
我正在使用Xcode 4.5.1并在带有iOS6的iPhone5上进行测试.
我正在使用帧捕获功能没有问题,但突然它停止工作.当我按下帧捕获按钮时,似乎帧被捕获,手机切换到空白屏幕,只是突然切换回应用程序屏幕,应用程序继续运行.我仍然可以调试和暂停应用程序,但是没有办法获得帧捕获.我也没有在控制台中看到任何错误.
它停止工作的原因是这段代码.这段代码应该渲染一个rendertexture,但rendertexture似乎是空白的.我想使用帧捕获功能找出错误,但代码本身不会让我捕获...... :(
知道为什么吗?
// ------------- init function -----------------
// Create the framebuffer and bind it
glGenFramebuffers(1, &g_framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, g_framebuffer);
//Create the destination texture, and attach it to the framebuffer’s color attachment point.
glGenTextures(1, &g_texture);
glBindTexture(GL_TEXTURE_2D, g_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, g_texture, 0);
//Test the framebuffer for completeness
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER) ;
if(status != GL_FRAMEBUFFER_COMPLETE) {
NSLog(@"failed to make complete framebuffer object %x", status);
} else {
NSLog(@"SkyPlugin initialized"); …Run Code Online (Sandbox Code Playgroud) 这是我第一次尝试使用模板测试,但我见过一些使用 OpenGL 的示例和一些使用 Metal 的示例,但主要关注深度测试。我了解模板测试背后的理论,但我不知道如何在金属上设置它。
我想画不规则的形状。为了简单起见,让我们考虑以下 2D 多边形:

我希望模板通过重叠三角形数量为奇数的地方,这样我就可以达到这样的效果,其中白色区域是要忽略的区域:

我正在按照确切的顺序执行以下步骤:
设置深度StencilPixelFormat:
mtkView.depthStencilPixelFormat = .stencil8
mtkView.clearStencil = .allZeros
Run Code Online (Sandbox Code Playgroud)
模板附件:
let textureDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: .stencil8, width: drawable.texture.width, height: drawable.texture.height, mipmapped: true)
textureDescriptor.textureType = .type2D
textureDescriptor.storageMode = .private
textureDescriptor.usage = [.renderTarget, .shaderRead, .shaderWrite]
mainPassStencilTexture = device.makeTexture(descriptor: textureDescriptor)
let stencilAttachment = MTLRenderPassStencilAttachmentDescriptor()
stencilAttachment.texture = mainPassStencilTexture
stencilAttachment.clearStencil = 0
stencilAttachment.loadAction = .clear
stencilAttachment.storeAction = .store
renderPassDescriptor.stencilAttachment = stencilAttachment
Run Code Online (Sandbox Code Playgroud)
模板描述符:
stencilDescriptor.depthCompareFunction = MTLCompareFunction.always
stencilDescriptor.isDepthWriteEnabled = true
stencilDescriptor.frontFaceStencil.stencilCompareFunction = MTLCompareFunction.equal
stencilDescriptor.frontFaceStencil.stencilFailureOperation = MTLStencilOperation.keep
stencilDescriptor.frontFaceStencil.depthFailureOperation = MTLStencilOperation.keep
stencilDescriptor.frontFaceStencil.depthStencilPassOperation …Run Code Online (Sandbox Code Playgroud) 你如何在Swift中实现Java的无符号右移运算符?
根据Java的文档,无符号右移运算符">>>"将零移动到最左边的位置,而">>"之后的最左边位置取决于符号扩展.
所以,例如,
long s1 = (-7L >>> 16); // result is 281474976710655L
long s2 = (-7L >> 16); // result is -1
Run Code Online (Sandbox Code Playgroud)
为了在Swift中实现这一点,我会通过执行类似的操作来获取除符号位之外的所有位.
let lsb = Int64.max + negativeNumber + 1
Run Code Online (Sandbox Code Playgroud)
请注意,该数字必须为负数!如果你溢出移位操作符,应用程序崩溃与EXC_BAD_INSTRUCTION,这不是很好......而且,我故意使用Int64.因为没有更大的数据类型,所以执行类似(1 << 63)的操作会溢出Int64并且也会崩溃.因此,我没有在更大的数据类型中执行((1 << 63) - 1 + negativeNumber),而是将其写为Int64.max + negativeNumber - 1.
然后,将该正数与正常逻辑移位相移,并将该符号从符号后第一个左位中的符号移位.
let shifted = (lsb >> bits) | 0x4000000000000000
Run Code Online (Sandbox Code Playgroud)
但是,这并没有给我预期的结果,
((Int64.max - 7 + 1) >> 16) | 0x4000000000000000 // = 4611826755915743231
Run Code Online (Sandbox Code Playgroud)
不确定我做错了什么...另外,是否可以将此运算符命名为">>>"并扩展Int64?
编辑:在这里添加来自OOper的解决方案,
infix operator >>> : BitwiseShiftPrecedence
func >>> (lhs: Int64, …Run Code Online (Sandbox Code Playgroud) 我在大阵列(图像)上做循环,通过仪器我发现主要的瓶颈是Array.subscript.nativePinningMutableAddressor,所以我做了这个单元测试来比较,
// average: 0.461 seconds (iPhone6 iOS 10.2) ~5.8 times slower than native arrays
func testArrayPerformance() {
self.measure {
var array = [Float](repeating: 1, count: 2048 * 2048)
for i in 0..<array.count {
array[(i+1)%array.count] = Float(i)
}
}
}
// average: 0.079 seconds
func testNativeArrayPerformance() {
self.measure {
let count = 2048 * 2048
let array = UnsafeMutablePointer<Float>.allocate(capacity: count)
for i in 0..<count {
array[(i+1)%count] = Float(i)
}
array.deallocate(capacity: count)
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,本机数组要快得多.还有其他方法可以更快地访问阵列吗?"不安全"听起来并不"安全",但在这种情况下你会做些什么呢?是否有其他类型的数组包装本机?
有关更复杂的示例,您可以看到本文中的注释:使用带符号距离字段在Metal中呈现文本 我在Swift中重新实现了该示例,并且原始实现需要52秒才能启动,https:// github …