I'm trying to create a pipeline state in swift and the app crashes with SIGABRT. I've put the call to newRenderPipelineStateWithDescriptor within a try catch block. Why is it not caching it?
Here's the code,
let defaultLibrary = device.newDefaultLibrary()!
let fragmentProgram = defaultLibrary.newFunctionWithName("passThroughFragment")!
let vertexProgram = defaultLibrary.newFunctionWithName("passGeometry")!
// check TexturedVertex
let vertexDesc = MTLVertexDescriptor()
vertexDesc.attributes[0].format = .Float3
vertexDesc.attributes[0].offset = 0
vertexDesc.attributes[0].bufferIndex = 0
vertexDesc.attributes[1].format = .Float3
vertexDesc.attributes[0].offset = sizeof(Vec3)
vertexDesc.attributes[0].bufferIndex = 0
vertexDesc.attributes[2].format = .Float2
vertexDesc.attributes[0].offset = sizeof(Vec3) * 2
vertexDesc.attributes[0].bufferIndex = 0
vertexDesc.layouts[0].stepFunction = .PerVertex
vertexDesc.layouts[0].stride = sizeof(TexturedVertex)
let pipelineStateDescriptor = MTLRenderPipelineDescriptor()
pipelineStateDescriptor.vertexFunction = vertexProgram
pipelineStateDescriptor.fragmentFunction = fragmentProgram
//pipelineStateDescriptor.vertexDescriptor = vertexDesc
pipelineStateDescriptor.colorAttachments[0].pixelFormat = view.colorPixelFormat
pipelineStateDescriptor.colorAttachments[0].blendingEnabled = false
pipelineStateDescriptor.sampleCount = view.sampleCount
do {
// SIGABRT will happen here when enabling .vertexDescriptor = vertexDesc
try pipelineState = device.newRenderPipelineStateWithDescriptor(pipelineStateDescriptor)
} catch let error {
print("Failed to create pipeline state, error \(error)")
}
The code above doesn't crash, until I enable this line,
pipelineStateDescriptor.vertexDescriptor = vertexDesc
To give a bit of background, my vertex shader used to receive a packed_float4 buffer as input but I'm trying to update it to a struct, as defined in the MTLVertexDescriptor above.
The frustrating thing is that the app just crashes without giving any hints of what's wrong.
Is there any way of get error messages when calling device.newRenderPipelineStateWithDescriptor?
Edit:
This fixes the crash,
vertexDesc.attributes[0].format = .Float3
vertexDesc.attributes[0].offset = 0
vertexDesc.attributes[0].bufferIndex = 0
vertexDesc.attributes[1].format = .Float3
vertexDesc.attributes[1].offset = sizeof(Vec3)
vertexDesc.attributes[1].bufferIndex = 0
vertexDesc.attributes[2].format = .Float2
vertexDesc.attributes[2].offset = sizeof(Vec3) * 2
vertexDesc.attributes[2].bufferIndex = 0
But apparently there's no way to make newRenderPipelineStateWithDescriptor to throw an exception because of that at the moment.
Related
I am new to swift.
I have my dictionary as
monthData =
{
"2018-08-10" = {
accuracy = 71;
attempted = 7;
correct = 5;
reward = Bronze;
};
"2018-08-12" = {
accuracy = 13;
attempted = 15;
correct = 2;
reward = "";
};
"2018-08-13" = {
accuracy = 33;
attempted = 15;
correct = 5;
reward = "";
};
"2018-08-14" = {
accuracy = 100;
attempted = 15;
correct = 15;
reward = Gold;
};
"2018-08-16" = {
accuracy = 73;
attempted = 15;
correct = 11;
reward = Silver;
};
"2018-08-21" = {
accuracy = 26;
attempted = 15;
correct = 4;
reward = "";
};
"2018-08-23" = {
accuracy = 46;
attempted = 15;
correct = 7;
reward = "";
};
}
I want to get all the dates for which reward is Gold
Can anyone please help me do that?
What I have tried 'till now is:
for (key,value) in monthData{
let temp = monthData.value(forKey: key as! String) as! NSDictionary
for (key1,value1) in temp{
if((value1 as! String) == "Gold"){
print("keyFINAL \(key)")
}
}
but it outputs the error Could not cast value of type '__NSCFNumber' to 'NSString'
The error occurs because when you are iterating the dictionary you force cast the Int values to String which is not possible
The (highly) recommended Swift way is to use the filter function. This is much more efficient than a loop.
In the closure $0.1 represents the value of the current dictionary ($0.0 would be the key). The result is an array of the date strings.
let data : [String:Any] = ["monthData" : ["2018-08-10": ["accuracy" : 71, "attempted" ... ]]]
if let monthData = data["monthData"] as? [String:[String:Any]] {
let goldData = monthData.filter { $0.1["reward"] as? String == "Gold" }
let allDates = Array(goldData.keys)
print(allDates)
}
The code safely unwraps all optionals.
However if there is only one Gold entry the first function is still more efficient than filter
if let monthData = data["monthData"] as? [String:[String : Any]] {
if let goldData = monthData.first( where: {$0.1["reward"] as? String == "Gold" }) {
let goldDate = goldData.key
print(goldDate)
}
}
In Swift avoid the ObjC runtime (value(forKey:)) and Foundation collection types (NSDictionary) as much as possible.
From the first for in loop, you are getting the NSDictionary in temp variable
"2018-08-16" = {
accuracy = 73;
attempted = 15;
correct = 11;
reward = Silver;
};
So, you should directly check .value(forKey:) on temp and get the value for reward.
You should try it like this
for (key,value) in monthData {
let temp = monthData.value(forKey: key as! String) as! NSDictionary
if(((temp.value(forKey: "reward")) as! String) == "Gold"){
print("keyFINAL \(key)")
}
}
Try and share results
EDIT
Please checkout the answer from vadian for in-depth explanation and pure swift approach to achieve the same.
Thanks
I am trying to update an item in my dynamoDB noSQL database. Having some troubles implementing this in swift as there is no swift documentation yet.
I was able to create an item in the database successfully, updating an item seems to be a whole other monster.
Swift Code:
var updatedValue: AWSDynamoDBAttributeValue = AWSDynamoDBAttributeValue()
updatedValue.s = self.UserID
let dynamo: AWSDynamoDB = AWSDynamoDB()
let AddToHistory = Users()
AddToHistory?._campany = self.CompanyTextBox.text!
AddToHistory?._personalSite = self.PersonalTitleTextBox.text!
AddToHistory?._facebook = self.FacebookTextBox.text!
AddToHistory?._linkedIn = self.LinkedInTextBox.text!
AddToHistory?._title = self.TitleTextBox.text!
AddToHistory?._bio = self.BioTextBox.text!
let updateInput: AWSDynamoDBUpdateItemInput = AWSDynamoDBUpdateItemInput()
updateInput.tableName = "myTableName"
updateInput.key = ["_userId": updatedValue]
let updatedCompany = AWSDynamoDBAttributeValue()
updatedCompany?.s = AddToHistory?._campany
let updatedFacebook = AWSDynamoDBAttributeValue()
updatedFacebook?.s = AddToHistory?._facebook
let updatedLinkedIn = AWSDynamoDBAttributeValue()
updatedLinkedIn?.s = AddToHistory?._linkedIn
let updatedPersonalSite = AWSDynamoDBAttributeValue()
updatedPersonalSite?.s = AddToHistory?._personalSite
let updatedTitle = AWSDynamoDBAttributeValue()
updatedTitle?.s = AddToHistory?._title
let updatedBio = AWSDynamoDBAttributeValue()
updatedBio?.s = AddToHistory?._bio
updateInput.expressionAttributeValues = [
"_campany" : updatedCompany!,
"_facebook" : updatedFacebook!,
"_linkedIn" : updatedLinkedIn!,
"_personalSite" : updatedPersonalSite!,
"_title" : updatedTitle!,
"_bio" : updatedBio!,
]
updateInput.returnValues = AWSDynamoDBReturnValue.updatedNew
dynamo.updateItem(updateInput).continueOnSuccessWith(block: { (task:AWSTask!) -> AnyObject! in
if (task.error == nil) {
}
return nil
}
)
Not getting any warnings or errors in the editor, however when I run the app and press the button which runs this code, I get this exception thrown:
Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason: '- init is not a valid
initializer. Use + defaultDynamoDB or + DynamoDBForKey: instead.'
Not sure what I am missing here, it must be something to do with the way I am initializing the dynamoDB object. Tried accessing a default method for init, but there is no such method. :(
Any help would be greatly appreciated, thanks in advance!
Thanks to Jake.lange's comment, I realized I could have used the object mapper that i used to create items to update them as well. Heres the code incase others run into this problem :)
//db connection mapper
let objectMapper = AWSDynamoDBObjectMapper.default()
//new instancer of User class
let itemToUpdate:CheckaraUsers = CheckaraUsers()
//populate
itemToUpdate._userId = UserID
itemToUpdate._firstName = FirstName
itemToUpdate._lastName = LastName
itemToUpdate._campany = AddToHistory?._campany
itemToUpdate._facebook = AddToHistory?._facebook
itemToUpdate._linkedIn = AddToHistory?._linkedIn
itemToUpdate._personalSite = AddToHistory?._personalSite
itemToUpdate._title = AddToHistory?._title
itemToUpdate._bio = AddToHistory?._bio
//save to dynamoDB
objectMapper.save(itemToUpdate, completionHandler:{(error: Error?) -> Void in
if let error = error {
print("Amazon DynamoDB Save Error: \(error)")
}
print("Saved Information!!!")
})
Your definition was wrong.
Change this:
let dynamo: AWSDynamoDB = AWSDynamoDB()
to:
let dynamo: AWSDynamoDB = AWSDynamoDB.default()
I have this code in Swift 3 and my output is 0.0 zeros most of the time and rarely I see very small numbers to the e^-50
The fileURL is a recording.caf with sound in it.
Does anyone know what's up?
func readBuff(_ fileURL:CFURL) {
var fileRef:ExtAudioFileRef? = nil
let openStatus = ExtAudioFileOpenURL(fileURL , &fileRef)
guard openStatus == noErr else {
print("Failed to open audio file '\(fileURL)' with error \(openStatus)")
return
}
var audioFormat2 = AudioStreamBasicDescription()
audioFormat2.mSampleRate = 44100; // GIVE YOUR SAMPLING RATE
audioFormat2.mFormatID = kAudioFormatLinearPCM;
audioFormat2.mFormatFlags = kLinearPCMFormatFlagIsFloat;
audioFormat2.mBitsPerChannel = UInt32(MemoryLayout<Float32>.size) * 8
audioFormat2.mChannelsPerFrame = 1; // Mono
audioFormat2.mBytesPerFrame = audioFormat2.mChannelsPerFrame * UInt32(MemoryLayout<Float32>.size); // == sizeof(Float32)
audioFormat2.mFramesPerPacket = 1;
audioFormat2.mBytesPerPacket = audioFormat2.mFramesPerPacket * audioFormat2.mBytesPerFrame; // = sizeof(Float32)
//apply audioFormat2 to the extended audio file
ExtAudioFileSetProperty(fileRef!, kExtAudioFileProperty_ClientDataFormat,UInt32(MemoryLayout<AudioStreamBasicDescription>.size),&audioFormat2)
let numSamples = 1024 //How many samples to read in at a startTime
let sizePerPacket:UInt32 = audioFormat2.mBytesPerPacket // sizeof(Float32) = 32 byts
let packetsPerBuffer:UInt32 = UInt32(numSamples)
let outputBufferSize:UInt32 = packetsPerBuffer * sizePerPacket //4096
//so the 1 value of outputbuffer is a the memory location where we have reserved space
let outputbuffer = UnsafeMutablePointer<UInt8>.allocate(capacity: MemoryLayout<UInt8>.size * Int(outputBufferSize))
var convertedData = AudioBufferList()
convertedData.mNumberBuffers = 1 //set this for Mono
convertedData.mBuffers.mNumberChannels = audioFormat2.mChannelsPerFrame // also = 1
convertedData.mBuffers.mDataByteSize = outputBufferSize
convertedData.mBuffers.mData = UnsafeMutableRawPointer(outputbuffer)
var frameCount:UInt32 = UInt32(numSamples)
while (frameCount > 0) {
Utility.check(ExtAudioFileRead(fileRef!,
&frameCount,
&convertedData),
operation: "Couldn't read from input file")
if frameCount == 0 {
Swift.print("done reading from file")
return
}
var arrayFloats:[Float] = []
let ptr = convertedData.mBuffers.mData?.assumingMemoryBound(to: Float.self)
var j = 0
var floatDataArray:[Double] = [882000]// SPECIFY YOUR DATA LIMIT MINE WAS 882000 , SHOULD BE EQUAL TO OR MORE THAN DATA LIMIT
if(frameCount > 0){
var audioBuffer:AudioBuffer = convertedData.mBuffers
let floatArr = UnsafeBufferPointer(start: audioBuffer.mData?.assumingMemoryBound(to: Float.self), count: 882000)
for i in 0...1024{
//floatDataArray[j] = Double(floatArr[i]) //put your data into float array
// print("\(floatDataArray[j])")
floatDataArray.append(Double(floatArr[i]))
print(Float((ptr?[i])!))
j += 1
}
// print(floatDataArray)
}
}
}
I'm reading from
guard let fileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, "./output.caf" as CFString!, .cfurlposixPathStyle, false) else {
// unable to create file
exit(-1)
}
steps after recording:
Swift.print("Recording, press <return> to stop:\n")
// wait for a key to be pressed
getchar()
// end recording
Swift.print("* recording done *\n")
recorder.running = false
// stop the Queue
Utility.check(AudioQueueStop(queue!, true),
operation: "AudioQueueStop failed")
// a codec may update its magic cookie at the end of an encoding session
// so reapply it to the file now
Utility.applyEncoderCookie(fromQueue: queue!, toFile: recorder.recordFile!)
// cleanup
AudioQueueDispose(queue!, true)
AudioFileClose(recorder.recordFile!)
readBuff(fileURL)
You're setting up your ExtAudioFile and its client format, but you're not actually reading from it (with ExtAudioFileRead), so your "output" is actually uninitialised, and in your case, very small.
I can perform a simple Get request on a singular table within AWS dynamoDB however when I expand it to a Batch Request across multiple tables I continue to get a error
validation error detected: Value null at 'requestItems.rip.member.keys' failed to satisfy constraint
I understand this as the values not being passed correctly but I can't see what the issue is with my code
//Create Request Values
AWSDynamoDBGetItemInput *getItem = [AWSDynamoDBGetItemInput new];
AWSDynamoDBAttributeValue *hashValue = [AWSDynamoDBAttributeValue new];
hashValue.S = #"User Test";
getItem.key = #{#"ripId": hashValue};
//Create Request Values 2
AWSDynamoDBGetItemInput *getItem2 = [AWSDynamoDBGetItemInput new];
AWSDynamoDBAttributeValue *hashValue2 = [AWSDynamoDBAttributeValue new];
hashValue2.S = #"User Test";
getItem2.key = #{#"chat": hashValue2};
//Combine to Batch Request
AWSDynamoDBBatchGetItemInput * batchFetch = [AWSDynamoDBBatchGetItemInput new];
batchFetch.requestItems = #{ #"rip": getItem,
#"chat": getItem,};
[[dynamoDB batchGetItem:batchFetch] continueWithBlock:^id(BFTask *task) {
if (!task.error) {
NSLog(#"BOY SUCCES");
} else {
NSLog(#" NO BOY SUCCESS %#",task.error);
}
return nil;
}];
Searched the internet high and low but cannot see a working example of a batch request using iOS Objective C (or swift for that matter).
I have tested both variables on a single Get request and they both work.
You forgot to wrap around AWSDynamoDBAttributeValue in AWSDynamoDBKeysAndAttributes. Here is a simple example from AWSDynamoDBTests.m:
AWSDynamoDBKeysAndAttributes *keysAndAttributes = [AWSDynamoDBKeysAndAttributes new];
keysAndAttributes.keys = #[#{#"hashKey" : attributeValue1},
#{#"hashKey" : attributeValue2}];
keysAndAttributes.consistentRead = #YES;
AWSDynamoDBBatchGetItemInput *batchGetItemInput = [AWSDynamoDBBatchGetItemInput new];
batchGetItemInput.requestItems = #{table1Name: keysAndAttributes};
Since the batch get doesn't map to a class I solved it by doing this instead.
I solved it by doing this,
let dynamoDBObjectMapper = AWSDynamoDBObjectMapper.defaultDynamoDBObjectMapper()
let task1 = dynamoDBObjectMapper.load(User.self, hashKey: "rtP1oQ5DJG", rangeKey: nil)
let task2 = dynamoDBObjectMapper.load(User.self, hashKey: "dbqb1zyUq1", rangeKey: nil)
AWSTask.init(forCompletionOfAllTasksWithResults: [task1, task2]).continueWithBlock { (task) -> AnyObject? in
if let users = task.result as? [User] {
print(users.count)
print(users[0].firstName)
print(users[1].firstName)
}
else if let error = task.error {
print(error.localizedDescription)
}
return nil
}
Swift 3
I was able to get the BatchGet request work with the following code. Hope this helps someone else who's struggling with the lack of Swift Docs.
This code assumes that you've configured your AWSServiceConfiguration in the AppDelegate application didFinishLaunchingWithOptions method.
let DynamoDB = AWSDynamoDB.default()
// define your primary hash keys
let hashAttribute1 = AWSDynamoDBAttributeValue()
hashAttribute1?.s = "NDlFRTdDODEtQzNCOC00QUI5LUFFMzUtRkIyNTJFNERFOTBF"
let hashAttribute2 = AWSDynamoDBAttributeValue()
hashAttribute2?.s = "MjVCNzU3MUQtMEM0NC00NEJELTk5M0YtRTM0QjVDQ0Q1NjlF"
let keys: Array = [["userID": hashAttribute1], ["userID": hashAttribute2]]
let keysAndAttributesMap = AWSDynamoDBKeysAndAttributes()
keysAndAttributesMap?.keys = keys as? [[String : AWSDynamoDBAttributeValue]]
keysAndAttributesMap?.consistentRead = true
let tableMap = ["Your-Table-Name" : keysAndAttributesMap]
let request = AWSDynamoDBBatchGetItemInput()
request?.requestItems = tableMap as? [String : AWSDynamoDBKeysAndAttributes]
request?.returnConsumedCapacity = AWSDynamoDBReturnConsumedCapacity.total
DynamoDB.batchGetItem(request!) { (output, error) in
if output != nil {
print("Batch Query output?.responses?.count:", output!.responses!)
}
if error != nil {
print("Batch Query error:", error!)
}
}
Why I get the error when trying to do this function:
let compile_file path use_asms output =
use pro = new FSharpCodeProvider()
let opt = CompilerParameters(use_asms, output)
let res = pro.CompileAssemblyFromFile(opt, path) // <-- Error
if res.Errors.Count = 0
then Some(FileInfo(res.PathToAssembly))
else None
Error-code: -2147467259
Error: cant find the file specified
Now I'm trying two broken implementations:
type System.CodeDom.Compiler.ICodeCompiler with
member this.CompileAssemblyFromFile
(options:CompilerParameters,fileName:string) : CompilerResults =
this.CompileAssemblyFromFileBatch(options, [|fileName|])
let compile_file str assemblies output =
let pro = new System.CodeDom.Compiler.CodeCompiler()
let opt = CompilerParameters(assemblies, output)
let res = pro.CompileAssemblyFromFile(opt, str)
if res.Errors.Count = 0 then
Some(FileInfo(res.PathToAssembly))
else None
let compile_file2 path use_asms output =
use pro = new FSharpCodeProvider()
let opt = CompilerParameters(use_asms, output)
let res = pro.CompileAssemblyFromFile(opt, path)
if res.Errors.Count = 0
then Some(FileInfo(res.PathToAssembly))
else None