How to solve Command failed due to signal: Segmentation fault: 11 - ios

I was searching for this issue here, and found out that this issue is not common one.
Everyone had different approaches to solve it. I'm using Firebase and Gifu framework. Actually for the last one - i copied all the files to my project, but that didn't helped either.
Here is my source code:
import FirebaseDatabase
import FirebaseAuth
import Firebase
import UIKit
import Gifu
class ViewController: UIViewController {
#IBOutlet weak var userImage: AnimatableImageView!
var displayedUserId = ""
var AcceptedOrRejected = ""
override func viewDidLoad() {
super.viewDidLoad()
let urlArray = ["http://i.imgur.com/VAWlQ0S.gif", "http://i.imgur.com/JDzGqvE.gif", "http://67.media.tumblr.com/4cd2a04b60bb867bb4746d682aa60020/tumblr_mjs2dvWX6x1rvn6njo1_400.gif", "https://media.giphy.com/media/TlK63ELk5OPDzpb6Tao/giphy.gif", "http://i3.photobucket.com/albums/y90/spicestas/GeriHalliwell-Calling-new1.gif", "http://media.tumblr.com/tumblr_lnb9aozmM71qbxrlp.gif"]
var counter = 1
for url in urlArray {
let nsUrl = NSURL(string: url)
let girls = ProfileClass()
girls.profilePhotoUrl = url
girls.profileGender = "female"
girls.profileName = "girlsname\(counter)"
girls.profileSurname = "girlsurname\(counter)"
girls.interest = "men"
girls.uid = "\(randomStringWithLength(45))"
counter++
girls.SaveUser()
}
//----setting variables
let label = UILabel(frame: CGRectMake(self.view.bounds.width / 2 - 100, self.view.bounds.height / 2 - 50, 300, 100))
//label.text = "Drag me!"
//label.textAlignment = NSTextAlignment.Center
self.view.addSubview(label)
let gesture = UIPanGestureRecognizer(target: self, action: Selector("wasDragged:"))
userImage.addGestureRecognizer(gesture)
userImage.userInteractionEnabled = true
//----getting access to database
let thisUserRef = URL_BASE.childByAppendingPath("profile")
thisUserRef.queryOrderedByChild("Interest").queryEqualToValue("men").observeEventType(.Value, withBlock: {
snapshot in
for child in snapshot.children{
self.displayedUserId = (child.value["uid"] as? String)!
let imageURL = child.value["photo"] as? String
let imURL = NSURL(string: imageURL!)
//print(imageURL)
if self.AcceptedOrRejected != "" {
let AcceptedArray = child.value[AcceptedOrRejected] as? Array
AcceptedArray.append(displayedUserId)
}
if let picData = NSData(contentsOfURL: imURL!) {
self.userImage.animateWithImageData(picData)
//self.userImage.image = UIImage(data: picData)
}
}
})
}
//-----Dragging function-----------
func wasDragged(gesture: UIPanGestureRecognizer) {
//set traslations
let translation = gesture.translationInView(self.view)
let label = gesture.view
//set center position
label!.center = CGPoint(x: self.view.bounds.width / 2 + translation.x, y: self.view.bounds.height / 2 - translation.y )
let xfromCenter = (label?.center.x)! - self.view.bounds.width / 2
let scale = min(100 / abs(xfromCenter),1)
var rotation = CGAffineTransformMakeRotation(xfromCenter / 200)
var strech = CGAffineTransformScale(rotation, scale, scale)
label?.transform = strech
if gesture.state == UIGestureRecognizerState.Ended {
if label?.center.x < 100 {
self.AcceptedOrRejected = "Accepted"
} else if label?.center.x > self.view.bounds.width / 100 {
self.AcceptedOrRejected = "Rejected"
}
rotation = CGAffineTransformMakeRotation(0)
strech = CGAffineTransformScale(rotation, 1, 1)
label?.transform = strech
label?.center = CGPoint(x: self.view.bounds.width / 2 , y: self.view.bounds.height / 2 )
}
}
//---Function for generating randomn userid
func randomStringWithLength (len : Int) -> NSString {
let letters : NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
let randomString : NSMutableString = NSMutableString(capacity: len)
for (var i=0; i < len; i += 1){
let length = UInt32 (letters.length)
let rand = arc4random_uniform(length)
randomString.appendFormat("%C", letters.characterAtIndex(Int(rand)))
}
return randomString
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "LogOutSegue" {
try! FIRAuth.auth()!.signOut()
}
}
}
And I get this error
1. While emitting SIL for 'viewDidLoad' at /Users/zkid18/Desktop/wrk/Bloom/Bloom/ViewController.swift:23:14
2. While silgen closureexpr SIL function #_TFFC5Bloom14ViewController11viewDidLoadFT_T_U_FCSo15FIRDataSnapshotT_ for expression at [/Users/zkid18/Desktop/wrk/Bloom/Bloom/ViewController.swift:68:114 - line:107:9] RangeText="{
snapshot in
for child in snapshot.children{
self.displayedUserId = (child.value["uid"] as? String)!
let imageURL = child.value["photo"] as? String
let imURL = NSURL(string: imageURL!)
//print(imageURL)
if self.AcceptedOrRejected != "" {
let AcceptedArray = child.value[AcceptedOrRejected] as? Array
AcceptedArray.append(displayedUserId)
}
if let picData = NSData(contentsOfURL: imURL!) {
self.userImage.animateWithImageData(picData)
//self.userImage.image = UIImage(data: picData)
}
}
}"
I don't really know what to do with that

I just attempted a conversion to Swift 3 to get a jump on fixing issues in my code. I have similar error but I just integrated Firebase into all of my project. I found that by removing the pod and framework from the app and commenting out all firebase code fixed this compile issue.

Related

How to make surface material double-sided for MDLAsset?

I am trying to create an app that allows me to scan a room and then export a 3D file using lidar. I am able to do this with the following code (thanks to ARKit – How to export OBJ from iPhone/iPad with LiDAR?); however, it seems that the surfaces are all one-sided (when you rotate the object around, the backside of every surface is clear). How can I make the surface double-sided in my saveButtonTapped method?
import RealityKit
import ARKit
import MetalKit
import ModelIO
#IBOutlet var arView: ARView!
var saveButton: UIButton!
let rect = CGRect(x: 50, y: 50, width: 100, height: 50)
override func viewDidLoad() {
super.viewDidLoad()
let tui = UIControl.Event.touchUpInside
saveButton = UIButton(frame: rect)
saveButton.setTitle("Save", for: [])
saveButton.addTarget(self, action: #selector(saveButtonTapped), for: tui)
self.view.addSubview(saveButton)
}
#objc func saveButtonTapped(sender: UIButton) {
print("Saving is executing...")
guard let frame = arView.session.currentFrame
else { fatalError("Can't get ARFrame") }
guard let device = MTLCreateSystemDefaultDevice()
else { fatalError("Can't create MTLDevice") }
let allocator = MTKMeshBufferAllocator(device: device)
let asset = MDLAsset(bufferAllocator: allocator)
let meshAnchors = frame.anchors.compactMap { $0 as? ARMeshAnchor }
for ma in meshAnchors {
let geometry = ma.geometry
let vertices = geometry.vertices
let faces = geometry.faces
let vertexPointer = vertices.buffer.contents()
let facePointer = faces.buffer.contents()
for vtxIndex in 0 ..< vertices.count {
let vertex = geometry.vertex(at: UInt32(vtxIndex))
var vertexLocalTransform = matrix_identity_float4x4
vertexLocalTransform.columns.3 = SIMD4<Float>(x: vertex.0,
y: vertex.1,
z: vertex.2,
w: 1.0)
let vertexWorldTransform = (ma.transform * vertexLocalTransform).position
let vertexOffset = vertices.offset + vertices.stride * vtxIndex
let componentStride = vertices.stride / 3
vertexPointer.storeBytes(of: vertexWorldTransform.x,
toByteOffset: vertexOffset,
as: Float.self)
vertexPointer.storeBytes(of: vertexWorldTransform.y,
toByteOffset: vertexOffset + componentStride,
as: Float.self)
vertexPointer.storeBytes(of: vertexWorldTransform.z,
toByteOffset: vertexOffset + (2 * componentStride),
as: Float.self)
}
let byteCountVertices = vertices.count * vertices.stride
let byteCountFaces = faces.count * faces.indexCountPerPrimitive * faces.bytesPerIndex
let vertexBuffer = allocator.newBuffer(with: Data(bytesNoCopy: vertexPointer,
count: byteCountVertices,
deallocator: .none), type: .vertex)
let indexBuffer = allocator.newBuffer(with: Data(bytesNoCopy: facePointer,
count: byteCountFaces,
deallocator: .none), type: .index)
let indexCount = faces.count * faces.indexCountPerPrimitive
let material = MDLMaterial(name: "material",
scatteringFunction: MDLPhysicallyPlausibleScatteringFunction())
let submesh = MDLSubmesh(indexBuffer: indexBuffer,
indexCount: indexCount,
indexType: .uInt32,
geometryType: .triangles,
material: material)
let vertexFormat = MTKModelIOVertexFormatFromMetal(vertices.format)
let vertexDescriptor = MDLVertexDescriptor()
vertexDescriptor.attributes[0] = MDLVertexAttribute(name: MDLVertexAttributePosition,
format: vertexFormat,
offset: 0,
bufferIndex: 0)
vertexDescriptor.layouts[0] = MDLVertexBufferLayout(stride: ma.geometry.vertices.stride)
let mesh = MDLMesh(vertexBuffer: vertexBuffer,
vertexCount: ma.geometry.vertices.count,
descriptor: vertexDescriptor,
submeshes: [submesh])
asset.add(mesh)
}
let filePath = FileManager.default.urls(for: .documentDirectory,
in: .userDomainMask).first!
let usd: URL = filePath.appendingPathComponent("model.usd")
if MDLAsset.canExportFileExtension("usd") {
do {
try asset.export(to: usd)
let controller = UIActivityViewController(activityItems: [usd],
applicationActivities: nil)
controller.popoverPresentationController?.sourceView = sender
self.present(controller, animated: true, completion: nil)
} catch let error {
fatalError(error.localizedDescription)
}
} else {
fatalError("Can't export USD")
}
}

How can I create multiple button by SwiftyJson and Almofire in swift 4?

These are my effort:
var cats = [[String:AnyObject]]()
func getAllCats(){
_ = EZLoadingActivity.show("Loading...", disableUI: true)
let param: [String: AnyObject] = ["apiKey": "???" as AnyObject]
_ = Alamofire.request(APIRouters.GetAllCats(param)).responseJSON { (responseData) -> Void in
if((responseData.result.value) != nil) {
let getJson = JSON(responseData.result.value!)
if (getJson["status"].stringValue == "200"){
if let resData = getJson["data"].arrayObject {
self.cats = resData as! [[String:AnyObject]]
}
} else if (getJson["status"].stringValue == "404") {
} else {
}
}
_ = EZLoadingActivity.hide()
}
}
var buttonY: CGFloat = 20 // our Starting Offset, could be 0
for villain in cats {
print("ok",villain["pt_name_Fa"])
let villainButton = UIButton(frame: CGRect(x: 50, y: buttonY, width: 250, height: 30))
buttonY = buttonY + 50 // we are going to space these UIButtons 50px apart
villainButton.layer.cornerRadius = 10 // get some fancy pantsy rounding
villainButton.backgroundColor = UIColor.darkGray
villainButton.setTitle("Button for Villain: \(villain["pt_name_Fa"] ?? "" as AnyObject))", for: UIControlState.normal) // We are going to use the item name as the Button Title here.
villainButton.titleLabel?.text = "\(villain)"
villainButton.addTarget(self,action:#selector(villainButtonPressed),
for:.touchUpInside)
// villainButton.addTarget(self, action: Selector(("villainButtonPressed:")), for: UIControlEvents.touchUpInside)
self.view.addSubview(villainButton) // myView in this case is the view you want these buttons added
}
It did not work, but if i use an array such below it works!
var arrayOfVillains = ["santa", "bugs", "superman", "batman"]
Thanks for your helping in advance
I found the solution. Adding button should be run after Json load completely:
var cats = [[String:AnyObject]]()
_ = EZLoadingActivity.show("Loading...", disableUI: true)
let param: [String: AnyObject] = ["apiKey": "???" as AnyObject]
_ = Alamofire.request(APIRouters.GetAllCats(param)).responseJSON { (responseData) -> Void in
if((responseData.result.value) != nil) {
print(responseData.request!) // original URL request
print(responseData.response!) // URL response
let getJson = JSON(responseData.result.value!)
if (getJson["status"].stringValue == "200"){
if let resData = getJson["data"].arrayObject {
self.cats = resData as! [[String:AnyObject]]
}
if self.cats.count > 0 {
self.addButton()
}
} else if (getJson["status"].stringValue == "404") {
_ = SweetAlert().showAlert("Ok", subTitle: "Api Error!", style: AlertStyle.warning)
} else {
_ = SweetAlert().showAlert("Error", subTitle: getJson["message"].stringValue, style: AlertStyle.warning)
}
}
_ = EZLoadingActivity.hide()
}
func addButton(){
var buttonY: CGFloat = 20 // our Starting Offset, could be 0
for villain in self.cats {
let villainButton = UIButton(frame: CGRect(x: 50, y: buttonY, width: 250, height: 30))
buttonY = buttonY + 50 // we are going to space these UIButtons 50px apart
villainButton.layer.cornerRadius = 10 // get some fancy pantsy rounding
villainButton.backgroundColor = UIColor.darkGray
villainButton.setTitle("Button for Villain: \(villain["pt_name_Fa"] ?? "" as AnyObject))", for: UIControlState.normal) // We are going to use the item name as the Button Title here.
villainButton.titleLabel?.text = "\(villain)"
villainButton.addTarget(self,action:#selector(villainButtonPressed),
for:.touchUpInside)
self.view.addSubview(villainButton) // myView in this case is the view you want these buttons added
}
}
Please attention to this part of code :
if self.cats.count > 0 {
self.addButton()
}
Thanks for your attendance.

ios Swift - Group separated sprites with syncronized animation

I am trying to make a synchronized animation (a large video decomposed by frames on separated and smaller puzzle jigsaw parts). This game is a video puzzle. Here is the code I use in three parts by way of example:
func Anim_Puzzle13 (Node13 : SKPuzzle) {
let puzzle13 = SKAction.animateWithTextures(sheet_puzzle13.Puzzle13_(), timePerFrame: 0.066)
NPuzzle13 = Node13
NPuzzle13.runAction(SKAction.repeatActionForever(puzzle13))
NPuzzle13.position = CGPoint(x: 500, y: 400)
NPuzzle13.zPosition = 1
}
func Anim_Puzzle19 (Node19 : SKPuzzle) {
let puzzle19 = SKAction.animateWithTextures(sheet_puzzle19.Puzzle19_(), timePerFrame: 0.066)
NPuzzle19 = Node19
NPuzzle19.runAction(SKAction.repeatActionForever(puzzle19))
NPuzzle19.position = CGPoint(x: 600, y: 500)
NPuzzle19.zPosition = 1
}
func Anim_Puzzle30 (Node30 : SKPuzzle) {
let puzzle30 = SKAction.animateWithTextures(sheet_puzzle30.Puzzle30_(), timePerFrame: 0.066)
NPuzzle30 = Node30
NPuzzle30.runAction(SKAction.repeatActionForever(puzzle30))
NPuzzle30.position = CGPoint(x: 700, y: 600)
NPuzzle30.zPosition = 1
}
It works well but it does not synchronize between the animations and the video has no integrity. I searched for a long time for a solution to make the animations synchronize; I see two possibilities: first is to create a unique SKNode() with all the jigsaw parts inside, but I want to be able to move each jigsaw part independently and have had no success getting a synchronized animation with this method.
The other way seem to be to create a group with all the animations together but this doesn't work, and causes the application to stop.
Here is all the code I use:
import SpriteKit
import UIKit
import AVFoundation
import AVKit
import CoreFoundation
private let kpuzzleNodeName = "puzzle"
private let kdancing = "dancing"
class SKPuzzle: SKSpriteNode {
var name2:String = "";
}
class GameScene: SKScene {
var background = SKVideoNode(videoFileNamed: "Video_Socle.mov")
var selectedNode = SKPuzzle()
var player:AVPlayer?
var videoNode:SKVideoNode?
var NPuzzle13 = SKPuzzle()
var NPuzzle19 = SKPuzzle()
var NPuzzle30 = SKPuzzle()
var NPuzzle11 = SKPuzzle()
var NPuzzle29 = SKPuzzle()
var NPuzzle35 = SKPuzzle()
var puzzle13 = SKAction()
var puzzle19 = SKAction()
var puzzle30 = SKAction()
var puzzle11 = SKAction()
var puzzle29 = SKAction()
var puzzle35 = SKAction()
let sheet_puzzle13 = Puzzle13()
let sheet_puzzle19 = Puzzle19()
let sheet_puzzle30 = Puzzle30()
let sheet_puzzle11 = Puzzle11()
let sheet_puzzle29 = Puzzle29()
let sheet_puzzle35 = Puzzle35()
override init(size: CGSize) {
super.init(size: size)
// 1
self.background.name = kdancing
self.background.anchorPoint = CGPointZero
background.zPosition = 0
self.addChild(background)
// 2
let sheet = Statiques()
let sprite_dancing1 = SKSpriteNode(texture: sheet.Dancing1())
let sprite_dancing2 = SKSpriteNode(texture: sheet.Dancing2())
sprite_dancing1.name = kdancing
sprite_dancing2.name = kdancing
sprite_dancing1.position = CGPoint(x: 837, y: 752)
sprite_dancing1.zPosition = 2
sprite_dancing2.position = CGPoint(x: 1241, y: 752)
sprite_dancing2.zPosition = 2
background.addChild(sprite_dancing1)
background.addChild(sprite_dancing2)
let imageNames = [sheet.Puzzle13() , sheet.Puzzle19(), sheet.Puzzle30(), sheet.Puzzle11(), sheet.Puzzle29(), sheet.Puzzle35() ]
for i in 0..<imageNames.count {
let imageName = imageNames[i]
let sprite = SKPuzzle(texture: imageName)
sprite.name = kpuzzleNodeName
sprite.name2 = "\(i)"
let offsetFraction = (CGFloat(i) + 1.0)/(CGFloat(imageNames.count) + 1.0)
sprite.position = CGPoint(x: size.width * offsetFraction, y: size.height / 2)
sprite.zPosition = 3
background.addChild(sprite)
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch: AnyObject in touches {
let positionInScene = touch.locationInNode(self)
selectNodeForTouch(positionInScene)
}
}
override func didMoveToView(view: SKView) {
let urlStr = NSBundle.mainBundle().pathForResource("Video_Socle", ofType: "mov")
let url = NSURL(fileURLWithPath: urlStr!)
player = AVPlayer(URL: url)
NSNotificationCenter.defaultCenter().addObserverForName(AVPlayerItemDidPlayToEndTimeNotification, object: player!.currentItem, queue: nil)
{ notification in
let t1 = CMTimeMake(5, 100);
self.player!.seekToTime(t1)
self.player!.play()
}
videoNode = SKVideoNode(AVPlayer: player!)
videoNode!.position = CGPointMake(frame.size.width/2, frame.size.height/2)
videoNode!.size = CGSize(width: 2048, height: 1536)
videoNode!.zPosition = 0
background.addChild(videoNode!)
videoNode!.play()
let gestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(GameScene.handlePanFrom(_:)))
self.view!.addGestureRecognizer(gestureRecognizer)
}
func handlePanFrom(recognizer : UIPanGestureRecognizer) {
if recognizer.state == .Began {
var touchLocation = recognizer.locationInView(recognizer.view)
touchLocation = self.convertPointFromView(touchLocation)
self.selectNodeForTouch(touchLocation)
} else if recognizer.state == .Changed {
var translation = recognizer.translationInView(recognizer.view!)
translation = CGPoint(x: translation.x, y: -translation.y)
self.panForTranslation(translation)
recognizer.setTranslation(CGPointZero, inView: recognizer.view)
} else if recognizer.state == .Ended {
}
}
func degToRad(degree: Double) -> CGFloat {
return CGFloat(degree / 180.0 * M_PI)
}
func selectNodeForTouch(touchLocation : CGPoint) {
// 1
let touchedNode = self.nodeAtPoint(touchLocation)
if touchedNode is SKPuzzle {
// 2
if !selectedNode.isEqual(touchedNode) {
selectedNode.runAction(SKAction.rotateToAngle(0.0, duration: 0.1))
selectedNode = touchedNode as! SKPuzzle
// 3
if touchedNode.name! == kpuzzleNodeName {
let sequence = SKAction.sequence([SKAction.rotateByAngle(degToRad(-4.0), duration: 0.1),
SKAction.rotateByAngle(0.0, duration: 0.1),
SKAction.rotateByAngle(degToRad(4.0), duration: 0.1)])
selectedNode.runAction(SKAction.repeatActionForever(sequence))
}
}
}
}
func panForTranslation(translation : CGPoint) {
let position = selectedNode.position
if selectedNode.name! == kpuzzleNodeName {
selectedNode.position = CGPoint(x: position.x + translation.x * 2, y: position.y + translation.y * 2)
print (selectedNode.name)
print (selectedNode.name2)
if selectedNode.name2 == "0" {
Anim_Puzzle13(selectedNode)
}
print (selectedNode.name2)
if selectedNode.name2 == "1" {
Anim_Puzzle19(selectedNode)
}
print (selectedNode.name2)
if selectedNode.name2 == "2" {
Anim_Puzzle30(selectedNode)
}
print (selectedNode.name2)
if selectedNode.name2 == "3" {
Anim_Puzzle11(selectedNode)
}
print (selectedNode.name2)
if selectedNode.name2 == "4" {
Anim_Puzzle29(selectedNode)
}
print (selectedNode.name2)
if selectedNode.name2 == "5" {
Anim_Puzzle35(selectedNode)
}
}
}
func Anim_Puzzle13 (Node13 : SKPuzzle) {
let puzzle13 = SKAction.animateWithTextures(sheet_puzzle13.Puzzle13_(), timePerFrame: 0.066)
NPuzzle13 = Node13
NPuzzle13.runAction(SKAction.repeatActionForever(puzzle13))
NPuzzle13.position = CGPoint(x: 500, y: 400)
NPuzzle13.zPosition = 1
}
func Anim_Puzzle19 (Node19 : SKPuzzle) {
let puzzle19 = SKAction.animateWithTextures(sheet_puzzle19.Puzzle19_(), timePerFrame: 0.066)
NPuzzle19 = Node19
NPuzzle19.runAction(SKAction.repeatActionForever(puzzle19))
NPuzzle19.position = CGPoint(x: 600, y: 500)
NPuzzle19.zPosition = 1
}
func Anim_Puzzle30 (Node30 : SKPuzzle) {
let puzzle30 = SKAction.animateWithTextures(sheet_puzzle30.Puzzle30_(), timePerFrame: 0.066)
NPuzzle30 = Node30
NPuzzle30.runAction(SKAction.repeatActionForever(puzzle30))
NPuzzle30.position = CGPoint(x: 700, y: 600)
NPuzzle30.zPosition = 1
}
func Anim_Puzzle11 (Node11 : SKPuzzle) {
let puzzle11 = SKAction.animateWithTextures(sheet_puzzle11.Puzzle11_(), timePerFrame: 0.066)
NPuzzle11 = Node11
NPuzzle11.runAction(SKAction.repeatActionForever(puzzle11))
NPuzzle11.position = CGPoint(x: 800, y: 700)
NPuzzle11.zPosition = 1
}
func Anim_Puzzle29 (Node29 : SKPuzzle) {
let puzzle29 = SKAction.animateWithTextures(sheet_puzzle29.Puzzle29_(), timePerFrame: 0.066)
NPuzzle29 = Node29
NPuzzle29.runAction(SKAction.repeatActionForever(puzzle29))
NPuzzle29.position = CGPoint(x: 900, y: 800)
NPuzzle29.zPosition = 1
}
func Anim_Puzzle35 (Node35 : SKPuzzle) {
let puzzle35 = SKAction.animateWithTextures(sheet_puzzle35.Puzzle35_(), timePerFrame: 0.066)
NPuzzle35 = Node35
NPuzzle35.runAction(SKAction.repeatActionForever(puzzle35))
NPuzzle35.position = CGPoint(x: 1000, y: 900)
NPuzzle35.zPosition = 1
}
}
I'm not sure if it's possible to synchronize animations like this: with SKAction() in several separated parts, because it's necessary to be able to select them individually.
UPDATE: I've tried to follow the action group way but I have the same animation playing on each sprite instead of a different animation synchronized for each sprite (6 different animations synchronized: 6 different sprites):
let sheet13 = Puzzle13()
let sheet19 = Puzzle19()
let sheet30 = Puzzle30()
let sheet11 = Puzzle11()
let sheet29 = Puzzle29()
let sheet35 = Puzzle35()
let imageAnims = [sheet13.Puzzle13_0000() , sheet19.Puzzle19_0000(), sheet30.Puzzle30_0000(), sheet11.Puzzle11_0000(), sheet29.Puzzle29_0000(), sheet35.Puzzle35_0000() ]
let puzzle13 = SKAction.animateWithTextures(sheet13.Puzzle13_(), timePerFrame: 0.066)
let puzzle19 = SKAction.animateWithTextures(sheet19.Puzzle19_(), timePerFrame: 0.066)
let puzzle30 = SKAction.animateWithTextures(sheet30.Puzzle30_(), timePerFrame: 0.066)
let puzzle11 = SKAction.animateWithTextures(sheet11.Puzzle11_(), timePerFrame: 0.066)
let puzzle29 = SKAction.animateWithTextures(sheet29.Puzzle29_(), timePerFrame: 0.066)
let puzzle35 = SKAction.animateWithTextures(sheet35.Puzzle35_(), timePerFrame: 0.066)
let group = SKAction.group([puzzle13,puzzle19,puzzle30,puzzle11,puzzle29,puzzle35])
for i in 0..<imageAnims.count {
let imageAnim = imageAnims[i]
let spriteAnim = SKPuzzle(texture: imageAnim)
spriteAnim.name = kanimNodeName
spriteAnim.name2 = "\(i)"
let offsetFraction = (CGFloat(i) + 1.0)/(CGFloat(imageAnims.count) + 1.0)
spriteAnim.position = CGPoint(x: ((size.width)*2) * offsetFraction, y: size.height * 1.5)
spriteAnim.zPosition = 3
spriteAnim.runAction(SKAction.repeatActionForever(group))
background.addChild(spriteAnim)
}
First of all I want to list two differents method to create your SKAction:
Starting with parallel actions by using SKAction.group:
let sprite = SKSpriteNode(imageNamed:"Spaceship")
let scale = SKAction.scaleTo(0.1, duration: 0.5)
let fade = SKAction.fadeOutWithDuration(0.5)
let group = SKAction.group([scale, fade])
sprite.runAction(group)
Another useful method can be the completion , so you can know when an SKAction was finished:
extension SKNode
{
func runAction( action: SKAction!, withKey: String!, optionalCompletion: dispatch_block_t? )
{
if let completion = optionalCompletion
{
let completionAction = SKAction.runBlock( completion )
let compositeAction = SKAction.sequence([ action, completionAction ])
runAction( compositeAction, withKey: withKey )
}
else
{
runAction( action, withKey: withKey )
}
}
}
Usage:
node.runAction(move,withKey:"swipeMove",optionalCompletion: {
// here the action is finished, do whatever you want
})
After that, about your project, I've seen many node.runAction.., you can also adopt this strategy to sinchronize your actions:
var myAction30 :SKAction!
var myAction31 :SKAction!
self.myAction30 = SKAction.repeatActionForever(puzzle30)
self.myAction31 = SKAction.repeatActionForever(puzzle31)
let group = SKAction.group([self.myAction30, self.myAction31])
self.runAction(group)
UPDATE: I've seen your update part, when you speak about "synchronize" probably you don't means the "running in parallel" actions.
So, if you want to run an action after another there is also:
self.myAction30 = SKAction.repeatActionForever(puzzle30)
self.myAction31 = SKAction.repeatActionForever(puzzle31)
let sequence = SKAction.sequence([self.myAction30, self.myAction31])
self.runAction(sequence)

How to release memory for UIImageView (Swift)

I got a problem with UIImage. I've manually added UIImageView objects to a scroll view. The problem is : when I have more than 50 images, memory will increase to around 200MB, and the app will be crash on iphone 4 or 4s. I want to release memory for images that is not in visible part when I receive Memory Warning to prevent crashing but I don't know how to release them with Swift. Help me please.
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func loadImage(index:Int){
if self.imgPaths.count == 0 {
println("Has not data")
actInd.stopAnimating()
return
}
var imgURL: NSURL = NSURL(string: self.imgPaths[index].stringByTrimmingCharactersInSet(.whitespaceAndNewlineCharacterSet()))!
let width:CGFloat = self.view.bounds.width
let height:CGFloat = self.view.bounds.height
var view:UIView = UIView(frame: CGRectMake(0, 0, width, height));
if let imgObj = self.dicData[index] {
}
else
{
println("imgURL \(imgURL)")
let request: NSURLRequest = NSURLRequest(URL: imgURL)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: {(response: NSURLResponse!,data: NSData!,error: NSError!) -> Void in
if error == nil {
let imgItem = UIImage(data: data)!
var te :Float = self.imgPaths.count > 0 ? Float(index + 1) / Float(self.imgPaths.count) : 1
self.progressView.setProgress(te, animated: true)
if let imgObj = self.dicData[index] {
if index < self.imgPaths.count - 1
{
var nextIndex:Int = index + 1
self.loadImage(nextIndex)
}
if(index == self.imgPaths.count - 1)
{
if self.currentImageIndex > 0
{
self.isAddedFirstImg = true
}
if !self.isAddedFirstImg
{
self.scrollViews[0].zoomScale = self.zoomScales[0]
self.view.insertSubview(self.scrollViews[0], belowSubview: self.tabBar.viewWithTag(77)!)
self.isAddedFirstImg = true
}
self.actInd.stopAnimating()
println("loaded image")
}
}
else
{
self.dicData[index] = UIImageView(image: imgItem)
self.dicData[index]?.frame = CGRect(origin: CGPointMake(0.0, 0.0), size:imgItem.size)
// 2
self.scrollViews[index].addSubview(self.dicData[index]!)
self.scrollViews[index].contentSize = imgItem.size
// 3
var doubleTapRecognizer = UITapGestureRecognizer(target: self, action: "scrollViewDoubleTapped:")
doubleTapRecognizer.numberOfTapsRequired = 2
doubleTapRecognizer.numberOfTouchesRequired = 1
self.scrollViews[index].addGestureRecognizer(doubleTapRecognizer)
var singleTapRecognizer = UITapGestureRecognizer(target: self, action: "scrollViewSingleTapped:")
singleTapRecognizer.numberOfTapsRequired = 1
singleTapRecognizer.numberOfTouchesRequired = 1
self.scrollViews[index].addGestureRecognizer(singleTapRecognizer)
var swipeRight = UISwipeGestureRecognizer(target: self, action: "respondToSwipeGesture:")
swipeRight.direction = UISwipeGestureRecognizerDirection.Right
self.scrollViews[index].addGestureRecognizer(swipeRight)
var swipeLeft = UISwipeGestureRecognizer(target: self, action: "respondToSwipeGesture:")
swipeLeft.direction = UISwipeGestureRecognizerDirection.Left
self.scrollViews[index].addGestureRecognizer(swipeLeft)
// 4
var scrollViewFrame = self.scrollViews[index].frame
var scaleWidth = scrollViewFrame.size.width / self.scrollViews[index].contentSize.width
var scaleHeight = scrollViewFrame.size.height / self.scrollViews[index].contentSize.height
var minScale = min(scaleWidth, scaleHeight)
self.zoomScales[index] = minScale
self.scrollViews[index].minimumZoomScale = minScale
// 5
self.scrollViews[index].maximumZoomScale = 1.0
self.scrollViews[index].delegate = self
// 6
self.centerScrollViewContents(index)
dispatch_async(dispatch_get_main_queue(), {
println("downloaded image index: \(index) CH.\(self.chapterID)")
if(index == 0)
{
self.scrollViews[0].zoomScale = self.zoomScales[0]
self.view.insertSubview(self.scrollViews[0], belowSubview: self.tabBar.viewWithTag(77)!)
self.actInd.stopAnimating()
}
if index < self.imgPaths.count - 1 && !self.stopDownload
{
var nextIndex:Int = index + 1
self.loadImage(nextIndex)
}
if(index == self.imgPaths.count - 1)
{
if self.currentImageIndex > 0
{
self.isAddedFirstImg = true
}
if !self.isAddedFirstImg
{
self.scrollViews[0].zoomScale = self.zoomScales[0]
self.view.insertSubview(self.scrollViews[0], belowSubview: self.tabBar.viewWithTag(77)!)
self.isAddedFirstImg = true
}
self.actInd.stopAnimating()
println("loaded image")
}
})
}
}
else {
println("Error: \(error.localizedDescription)")
}
})
}
}
Swift uses ARC (Automatic Reference Counting) to manage memory. To free something from memory, you must remove all references to that object. ARC maintains a count of the number of places that hold a reference to the object, and when that count reaches 0, the memory is freed.
In your case, your imageViews are stored in self.dicData[index] and they are added as subviews of self.scrollViews[index]. You will need to remove the imageView from its superview and from self.dicData. Once you do that, the memory will be freed.
If you have the index of the imageView you want to free:
self.dicData[index]?.removeFromSuperview()
self.dicData[index] = nil
in swift there is really good tool called "lazy"
you might wanted to study about lazy var its very handy when it comes down to the images and tableview (for your instance collectionview)
you will see a huge difference when its used from custom cell.
create a imageview e.g. lazy var imageViewer:UIImageView
my app was at about 150mb 200mb memory now its at 40~60mb try it!

Cannot index empty buffer in Swift

I'm following along with Rob Percival's tutorial on Udemy and my app crashes with a fatal error: cannot index empty buffer.
The error happens on the following line in the ViewdidLoad method:
userImage.image = UIImage(data: self.userImages[0])
Using println(self.userImages) right above that erroneous line I found out the array is empty. The console outputs a []. This must be why it's crashing. Correct?
My Parse.com dashboard shows that all my users have images. I'm not sure why the array would be empty. Any ideas?
import UIKit
class SwipeViewController: UIViewController {
var xFromCenter: CGFloat = 0
var usernames = [String]()
var userImages = [NSData]()
var currentUser = 0
override func viewDidLoad() {
super.viewDidLoad()
println(PFUser.currentUser()["first_name"])
PFGeoPoint.geoPointForCurrentLocationInBackground { (geopoint: PFGeoPoint!, error: NSError!) -> Void in
println(error)
if error == nil {
println(geopoint)
var user = PFUser.currentUser()
user["location"] = geopoint
var query = PFUser.query()
query.whereKey("location", nearGeoPoint:geopoint)
query.limit = 10
query.findObjectsInBackgroundWithBlock({ (users, error) -> Void in
for user in users {
var gender1 = user["gender"] as? NSString
var gender2 = PFUser.currentUser()["interestedIn"] as? NSString
if gender1 == gender2 && PFUser.currentUser().username != user.username {
self.usernames.append(user.username)
// Update - chaned as to as!
self.userImages.append(user["image"] as NSData)
}
}
var userImage: UIImageView = UIImageView(frame: CGRectMake(0, 0, self.view.frame.width, self.view.frame.height))
println("images:")
println(userImage)
println(self.userImages)
userImage.image = UIImage(data: self.userImages[0])
userImage.contentMode = UIViewContentMode.ScaleAspectFit
self.view.addSubview(userImage)
var gesture = UIPanGestureRecognizer(target: self, action: Selector("wasDragged:"))
userImage.addGestureRecognizer(gesture)
userImage.userInteractionEnabled = true
})
user.save()
}
}
}
func wasDragged(gesture: UIPanGestureRecognizer) {
let translation = gesture.translationInView(self.view)
var label = gesture.view!
xFromCenter += translation.x
var scale = min(100 / abs(xFromCenter), 1)
label.center = CGPoint(x: label.center.x + translation.x, y: label.center.y + translation.y)
gesture.setTranslation(CGPointZero, inView: self.view)
var rotation:CGAffineTransform = CGAffineTransformMakeRotation(xFromCenter / 200)
var stretch:CGAffineTransform = CGAffineTransformScale(rotation, scale, scale)
label.transform = stretch
if label.center.x < 100 {
println("Not Chosen")
} else if label.center.x > self.view.bounds.width - 100 {
println("Chosen")
}
if gesture.state == UIGestureRecognizerState.Ended {
self.currentUser++
label.removeFromSuperview()
if self.currentUser < self.userImages.count {
var userImage: UIImageView = UIImageView(frame: CGRectMake(0, 0, self.view.frame.width, self.view.frame.height))
userImage.image = UIImage(data: self.userImages[self.currentUser])
userImage.contentMode = UIViewContentMode.ScaleAspectFit
self.view.addSubview(userImage)
var gesture = UIPanGestureRecognizer(target: self, action: Selector("wasDragged:"))
userImage.addGestureRecognizer(gesture)
userImage.userInteractionEnabled = true
xFromCenter = 0
} else {
println("No more users")
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
Looks like a data issue. The problem must comes from the loop just above the failing line.
Conditions are not met, and so no image is pushed into the array. Reasons can be:
You only have 1 user (your current user)
There is no other users with a gender that meets the "interested in" condition of your current user
Your users (current or not) doesn't have the "gender" or "interestedIn" attributes set
The best way is to put breakpoint (or log) inside your loop in order to determine users gender and "interestedIn" attributes and see if there is some matches.

Resources