Post

Replies

Boosts

Views

Activity

Fragment large size data sent and received using NSKeyedArchiver.archivedData in GameCenter
Trying to send and receive data in the GameCenter environment using the following methods: func sendData(dictionaryWithData dictionary: Dictionary<String, Any>,toPeer targetPeers: [GKPlayer]) { guard let match = self.match else { return } do { let dataToSend = try NSKeyedArchiver.archivedData(withRootObject: dictionary, requiringSecureCoding: false) try match.send(dataToSend, to: targetPeers, dataMode: .reliable) } catch { #if DEBUG print("CONNECTION MANAGER SEND DATA ERROR") #endif } } public func match(_ theMatch: GKMatch,didReceive data: Data,forRecipient recipient: GKPlayer,fromRemotePlayer player: GKPlayer) { if match != theMatch { return } DispatchQueue.main.async { do { guard let message = NSDictionary.unsecureUnarchived(from: data) as? Dictionary<String, Any> else {return} ... <CODE> ... } ///Source: https://stackoverflow.com/questions/51487622/unarchive-array-with-nskeyedunarchiver-unarchivedobjectofclassfrom static func unsecureUnarchived(from data: Data) -> Self? { do { let unarchiver = try NSKeyedUnarchiver(forReadingFrom: data) unarchiver.requiresSecureCoding = false let obj = unarchiver.decodeObject(of: self, forKey: NSKeyedArchiveRootObjectKey) if let error = unarchiver.error { print("Error:\(error)") } return obj } catch { print("Error:\(error)") } return nil } Everything works great until the data exceeds 87K (which, I understand, is the limit for exchanging data in GameCenter). The data is not sent and gives the following error: Async message[1FCA0D11-05DE-47D0-9714-983C8023F5C1] send error: FailedToSendData: , InternalError: reliable, maxPayloadSizeExceeded Interesting enough, I do not have this problem when using MCSession, as follows, even if data exceeds 87K: func sendData(dictionaryWithData dictionary: Dictionary<String, Any>, toPeer targetPeers: [MCPeerID]) { do { let dataToSend = try NSKeyedArchiver.archivedData(withRootObject: dictionary, requiringSecureCoding: false) try session.send(dataToSend, toPeers: targetPeers, with: MCSessionSendDataMode.reliable) } catch { #if DEBUG print("CONNECTION MANAGER SEND DATA ERROR") #endif } } I have been doing research and found that I need to fragment data and send and receive it in packages. But I could not find a good explanation how to do it. Any help would be appreciated!
5
0
557
Jul ’24
How to handle a disconnected player in a real-time match
Hi. Are there best practices in terms of how I should handle a disconnected player in a real-time match? In my app, once a player goes to background, he/she gets disconnected and the player is marked as temporarily unavailable on other players' devices. Is there any way that the disconnected player can return back to the same game when he/she becomes active again? It sounds a bit counterproductive to stop the whole match if one player has to disconnect quickly, for example to answer a call. Thank you!
1
0
760
Nov ’20
GameKit: 'didFind match' never called
I am trying to implement a real-time match in GameCenter using GameKit and SpriteKit. This is my scene: class IntroScene: SKScene, GameCenterManagerDelegate { &#9;var gameCenterManager: GameCenterManager? &#9;override func didMove(to view: SKView) { &#9;&#9;GameCenterManager.manager.delegate = self &#9;&#9;<other code> &#9;} &#9;override func didChangeSize(_ oldSize: CGSize) { &#9;&#9;super.didChangeSize(oldSize) &#9;&#9;GameCenterManager.manager.authenticatePlayer() &#9;} &#9;func didChangeAuthStatus(isAuthenticated: Bool) { &#9;&#9;...Enabling the Button to play in GameCenter &#9;} &#9;func presentGameCenterAuth(viewController: UIViewController?) { &#9;&#9;guard let vc = viewController else {return} &#9;&#9;self.view!.window?.rootViewController?.present(vc, animated: true) &#9;} &#9;func presentMatchmaking(viewController: UIViewController?) { &#9;&#9;guard let vc = viewController else {return} &#9;&#9;self.view!.window?.rootViewController?.present(vc, animated: true) &#9;} &#9;->> Problem here. Never gets called &#9;func presentGame(match: GKMatch) { &#9;&#9;print("....INTROSCENE: DELEGATE PRESENT_GAME CALLED......") &#9;&#9;... Presenting a new scene &#9;} } This is my GameCenterManager class: final class GameCenterManager : NSObject, GKLocalPlayerListener {   static let manager = GameCenterManager()   weak var delegate: GameCenterManagerDelegate?   var maxPlayers = 2   var match: GKMatch?   static var isAuthenticated: Bool {     return GKLocalPlayer.local.isAuthenticated   }       override init() {     super.init()   }           func authenticatePlayer() {     GKLocalPlayer.local.authenticateHandler = { gcAuthVC, error in       self.delegate?.didChangeAuthStatus(isAuthenticated: GKLocalPlayer.local.isAuthenticated)       if GKLocalPlayer.local.isAuthenticated {         GKLocalPlayer.local.register(self)       }       // If the User needs to sign to the Game Center       else if let vc = gcAuthVC {         self.delegate?.presentGameCenterAuth(viewController: vc)       }       else {         print(">>>>> Error authenticating the Player! \(error?.localizedDescription ?? "none") <<<<<")       }     }   }       func presentMatchmaker() {     guard GKLocalPlayer.local.isAuthenticated else { return }     let request = GKMatchRequest()     request.minPlayers = 2     request.maxPlayers = 6     request.inviteMessage = "Would you like to play?"     guard let vc = GKMatchmakerViewController(matchRequest: request) else { return }     vc.matchmakerDelegate = self     delegate?.presentMatchmaking(viewController: vc)   }     &#9;// THIS IS WORKING...   func player(_ player: GKPlayer, didAccept invite: GKInvite) {           print("-----player -- did accept invite-------\(player.displayName)")           guard let vc = GKMatchmakerViewController(invite: invite) else { return }     vc.matchmakerDelegate = self           self.gameCenterViewController?.present(vc, animated: true, completion: nil)   }       func player(_ player: GKPlayer, didRequestMatchWithRecipients recipientPlayers: [GKPlayer]) {     print("didRequestMatchWithRecipients")   }           func player(_ player: GKPlayer, matchEnded match: GKTurnBasedMatch) {     print("match ended")   }       func player(_ player: GKPlayer, wantsToQuitMatch match: GKTurnBasedMatch) {     print("wants to quit match")   } } extension GameCenterManager: GKMatchmakerViewControllerDelegate {     &#9;// THIS IS NOT WORKING -(   func matchmakerViewController(_ viewController: GKMatchmakerViewController, didFind match: GKMatch) {           print("-----matchmakerVC did find match-------")           viewController.dismiss(animated: true)           match.delegate = self           delegate?.presentGame(match: match)   }       func matchmakerViewControllerWasCancelled(_ viewController: GKMatchmakerViewController) {     print("matchmakerVC was cancelled")     viewController.dismiss(animated: true)     delegate?.matchmakingCancelled()   }       func matchmakerViewController(_ viewController: GKMatchmakerViewController, didFailWithError error: Error) {     viewController.dismiss(animated: true)     delegate?.matchmakingError(error: error)   } } extension GameCenterManager: GKMatchDelegate {       func match(_ match: GKMatch, didReceive data: Data, forRecipient recipient: GKPlayer, fromRemotePlayer player: GKPlayer) {     // HANDLE DATA   }       func match(_ match: GKMatch, didReceive data: Data, fromRemotePlayer player: GKPlayer) {     //HANDLE DATA   }           func match(_ match: GKMatch, player: GKPlayer, didChange state: GKPlayerConnectionState) {     print("-----match did change state")     guard match == self.match else { return }     switch state {     case .connected where self.match != nil :       print("-----MATCH DID CHANGE STATE CONNECTED-----")     case .disconnected:       print("-----MATCH DID CHANGE STATE DISCONNECTED-----")     default:       break     }   }       func match(_ match: GKMatch, didFailWithError error: Error?) {     print("-----match did fail with error")   } } So, basically this is what happens. Player 1 starts the game. The player gets successfully authenticated. I invite Player 2 to join the game. The invitation is sent to Player 2's device. Player 2 accepts the game (printing player did accept invite). However, after that nothing happens. There is continuing spinning wheel saying "Sending" on Player 1's device, and the game scene never launches. I never receive notification that the match has been found, i.e. matchmakerViewController(_ viewController:,match:) is never called. Any help would be greatly appreciated!
2
0
934
Oct ’20
Buying IAP for a Sandbox account: Verification Failed
Hi. I have created several sandbox accounts to test in-app purchases for my application. However, every time I try to make a purchase on my iPhone I get the following error: Verification Failed. Your Apple ID or password is incorrect. This is wrong, I am pretty sure that my credentials are fine. I used to have a similar issue on iPad. What I did was reinstalling the application on my device after I had logged in as a sandbox user and cleaning all application data before installing the application. Somehow it worked. But not on iPhone; no matter what I do, the problem persists. Your help would be much appreciated! I do not want to go to production without a successful test on an iPhone. Thank you!
1
0
1.4k
Aug ’20
Place UITextField behind SKNode
Hi.I am adding a UITextfield to my SKScene:txtName = UITextField() txtName.borderStyle = UITextField.BorderStyle.roundedRect txtName.textColor = SKColor.black txtName.backgroundColor = SKColor.white txtName.text = appDelegate.playerName_old txtName.delegate = self // Textfield delegate self.view?.addSubview(txtName) txtName.alpha = 1.0After, I am also adding an SKShapeNode to the same Scene:tutorialNotification = TutorialNotification(text: text, position: position, isShiftedByHalf: isShiftedByHalf) tutorialNotification?.alpha = 0 background.addChild(tutorialNotification) tutorialNotification!.zPosition = 2000 tutorialNotification?.run(SKAction.fadeIn(withDuration: 0.25))where TutorialNotification is a subclass of SKShapeNode. The problem I have is that the tutorialNotification node is located on top of other nodes but is always behind the UITextField.Is there any way to place the UITextField behind the SKShapeNode?Thanks a lot!
3
0
1.2k
Feb ’20
Problem with the position of multiple SKShapeNodes on rotation
Hi. I have faced a problem in a seemingly easy situation. I am using SpriteKit to present several boxes (SKShapeNodes) with texts inside (similar to a messaging app). The boxes are created just nice. However, when I rotate the device, the lowest and the second to lowest boxes are placed as expected, then the next box is located higher (by the height of the box), the other one is placed even higher (I wish I could attach screenshots).This is my code.ViewControllerclass GameViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let scene = GameScene() let skView = self.view as! SKView if skView.bounds.size.height&gt;skView.bounds.size.width { scene.size = CGSize(width: 1080, height: 1920) } else { scene.size = CGSize(width: 1920, height: 1080) } skView.showsFPS = true skView.showsNodeCount = true skView.ignoresSiblingOrder = false scene.scaleMode = .aspectFit skView.presentScene(scene) } override func viewWillLayoutSubviews() { super.viewDidLayoutSubviews() let skView = self.view as! SKView if let scene = skView.scene { if skView.bounds.size.height&gt;skView.bounds.size.width { scene.size = CGSize(width: 1080, height: 1920) } else { scene.size = CGSize(width: 1920, height: 1080) } var size = scene.size let boundWidth = skView.bounds.width let boundHeight = skView.bounds.height let newHeight = boundHeight*size.width/boundWidth let newWidth = boundWidth*size.height/boundHeight if newHeight &gt; size.height { size.height = newHeight scene.size = size } if newWidth &gt; size.width { size.width = newWidth scene.size = size } } } }GameScene:import SpriteKit import GameplayKit struct TextMessage: Equatable { var messageText : SKLabelNode? var messageBox : SKShapeNode? } class GameScene: SKScene { var background : SKSpriteNode! private var label : SKLabelNode? private var spinnyNode : SKShapeNode? var listOfTextMessages = [TextMessage]() var number = 1 override func didMove(to view: SKView) { background = SKSpriteNode() background.color = .green addChild(background) } override func touchesEnded(_ touches: Set, with event: UIEvent?) { switch number { case 1: createTextMessageBox(text:"wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww") case 2: createTextMessageBox(text:"\(number)\(number)\(number)") case 3: createTextMessageBox(text:"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee") case 4: createTextMessageBox(text:"rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr") case 5: createTextMessageBox(text:"\(number)\(number)\(number)") default: createTextMessageBox(text:"yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy") } number += 1 } func createTextMessageBox(text:String) { // Width of the textbox is fixed and depends on the device position var textboxWidth : CGFloat = 500 if UIDevice.current.orientation.isLandscape { textboxWidth = 800 } else { textboxWidth = 500 } // Create the text message label let notificationText = SKLabelNode(fontNamed: "AppleSDGothicNeo-Regular") notificationText.name = "message_text" notificationText.text = text notificationText.fontSize = 45 notificationText.fontColor = SKColor.white notificationText.alpha = 0 notificationText.numberOfLines = 0 notificationText.horizontalAlignmentMode = .left notificationText.verticalAlignmentMode = .center notificationText.preferredMaxLayoutWidth = textboxWidth-50 // Height of the textbox depends on the size of the text let textboxHeight = notificationText.frame.height + 50 // Notification textbox that contains the text let rightEdgeX = self.convert(CGPoint(x: self.frame.maxX, y: 0), to: background).x let bottomEdgeY = self.convert(CGPoint(x: 0, y: self.frame.minY), to: background).y let boxPositionX = rightEdgeX-50-textboxWidth let boxPositionY : CGFloat = bottomEdgeY+100 // Create the Notification Textbox let notificationNode = SKShapeNode(rect: CGRect(x: boxPositionX,y: boxPositionY,width: textboxWidth,height: textboxHeight), cornerRadius: 20) notificationNode.name = "message_box" notificationNode.fillColor = UIColor(red: 120/255, green: 0/255, blue: 0/255, alpha: 0.8) notificationNode.strokeColor = UIColor(red: 128/255, green: 0/255, blue: 0/255, alpha: 1) notificationNode.lineWidth = 2 notificationNode.alpha = 0 //notificationNode.zPosition = 0 // Position text in the middle of the texbox notificationText.position = CGPoint(x: notificationNode.frame.minX+25, y: notificationNode.frame.maxY-textboxHeight/2) // Add nodes to the scene background.addChild(notificationNode) notificationNode.addChild(notificationText) // Add to the list of text messages let currentMessage = TextMessage(messageText: notificationText, messageBox: notificationNode) listOfTextMessages.insert(currentMessage, at: 0) // The first message is shown at the bottom, whereas the older messages are moved on top of it. for (index,textBox) in listOfTextMessages.enumerated() { // The latest message if index == 0 { let actionBoxFadeIn = SKAction.fadeAlpha(to: 0.8, duration: 0.2) // Fade in the textbox let actionTextFadeIn = SKAction.run { textBox.messageText!.run(SKAction.fadeIn(withDuration: 0.2)) } let actionMoveGroup = SKAction.group([actionBoxFadeIn,actionTextFadeIn]) textBox.messageBox!.run(actionMoveGroup) } else { textBox.messageBox!.position.y += listOfTextMessages[0].messageBox!.frame.height } } } override func didChangeSize(_ oldSize: CGSize) { super.didChangeSize(oldSize) var zPosition : CGFloat = 10 if background != nil { background.size = CGSize(width: self.frame.width, height: self.frame.height) background.position = CGPoint(x: self.frame.width/2, y: self.frame.height/2) } if self.view != nil &amp;&amp; !listOfTextMessages.isEmpty { let textboxWidth : CGFloat = UIDevice.current.orientation.isLandscape ? 800 : 500 let textlabelWidth = textboxWidth-50 for (index,textBox) in listOfTextMessages.enumerated() { textBox.messageBox!.zPosition = zPosition zPosition += 1 textBox.messageText!.fontSize = 45 textBox.messageText!.fontColor = SKColor.white textBox.messageText!.numberOfLines = 0 textBox.messageText!.horizontalAlignmentMode = .left textBox.messageText!.verticalAlignmentMode = .center textBox.messageText!.preferredMaxLayoutWidth = textlabelWidth let textboxHeight = textBox.messageText!.frame.height + 50 let rightEdgeX = self.convert(CGPoint(x: self.frame.maxX, y: 0), to: background).x let boxPositionX = rightEdgeX-50-textboxWidth let boxPositionY : CGFloat = { return (index == 0) ? self.convert(CGPoint(x: 0, y: self.frame.minY), to: background).y : listOfTextMessages[index-1].messageBox!.frame.minY }() textBox.messageBox!.path = UIBezierPath(roundedRect: CGRect(x: boxPositionX, y: boxPositionY, width: textboxWidth, height: textboxHeight), cornerRadius: 20).cgPath textBox.messageText!.position = CGPoint(x: textBox.messageBox!.frame.minX+25, y: textBox.messageBox!.frame.minY+textboxHeight/2) } } }The text is also shifted upwards.Interesting enough, if I do the following (create each box in the array using the coordinates of the first box), the boxes are placed right on top of each other; however, their position is also skewed when their height varies:let boxPositionY : CGFloat = { return self.convert(CGPoint(x: 0, y: self.frame.minY), to: background).y }() textBox.messageText!.position = CGPoint(x: listOfTextMessages[0].messageBox!.frame.minX+25, y: listOfTextMessages[0].messageBox!.frame.minY+textboxHeight/2)Could someone please help me find the culprit?Thanks a lot!
0
0
739
Jan ’20
Expand UITextView upwards from keyboard
Hi. I am trying to figure out how to do a simple thing, but all research that I have done so far has not clarified what the proper way to do it is. I am adding a UITextView that should expand while I am typing upwards and then enable scrolling when the maximum height is reached. Instead, my UITextView is expanding downwards. My code:overridefunc didMove(to view: SKView) { txtMessage = UITextView() txtMessage.font = UIFont.systemFont(ofSize: 16) txtMessage.layer.cornerRadius = 5 txtMessage.autocorrectionType = UITextAutocorrectionType.no txtMessage.keyboardType = UIKeyboardType.default txtMessage.returnKeyType = UIReturnKeyType.done txtMessage.isScrollEnabled = false txtMessage.delegate = self self.view!.addSubview(txtMessage) registerForKeyboardNotifications() } func textViewDidChange(_ textView: UITextView) { let fixedWidth = textView.frame.size.width // Changing height of the message UITextView let newSize = textView.sizeThatFits(CGSize.init(width: fixedWidth, height: CGFloat(MAXFLOAT))) var newFrame = textView.frame newFrame.size = CGSize.init(width: CGFloat(fmaxf(Float(newSize.width), Float(fixedWidth))), height: newSize.height) txtMessage.frame = CGRect(origin: textView.frame.origin, size: CGSize(width: newFrame.width, height: newFrame.height)) } func registerForKeyboardNotifications() { let notificationCenter = NotificationCenter.default notificationCenter.addObserver( self, selector: #selector(GameScene.keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil ) notificationCenter.addObserver( self, selector: #selector(GameScene.keyboardWillBeHidden(_:)), name: UIResponder.keyboardWillHideNotification, object: nil) } func unregisterForKeyboardNotifications() { let notificationCenter = NotificationCenter.default notificationCenter.removeObserver( self, name: UIResponder.keyboardWillShowNotification, object: nil) notificationCenter.removeObserver( self, name: UIResponder.keyboardWillHideNotification, object: nil) } @objc func keyboardWillShow(_ notification: Notification) { let txtMessageViewHeight : CGFloat = 41 if let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue { let duration:TimeInterval = (notification.userInfo![UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0 let animationCurveRawNSN = notification.userInfo![UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIView.AnimationOptions.curveEaseInOut.rawValue let animationCurve:UIView.AnimationOptions = UIView.AnimationOptions(rawValue: animationCurveRaw) keyboardHeight = keyboardFrame.cgRectValue.height let viewHeight = keyboardHeight + txtMessageViewHeight self.txtMessage.frame.origin.y -= viewHeight self.txtMessage.layoutIfNeeded() } }Thank you!
6
0
2.8k
Dec ’19
'withUnsafeBytes' is deprecated
Hi. I had the following code in Swift 3 to send a String message using NSStream.@objcfunc processOutput() { // Create a message and convert it to data let msgToServer = makeMessageToServer() self.outputBuffer = msgToServer.data(using: .utf8, allowLossyConversion: false) if self.outputBuffer != nil { if self.outputBuffer?.count != 0 { let bytesWritten = self.outputBuffer!.withUnsafeBytes { self.outputStream!.write($0, maxLength: self.outputBuffer!.count) } if bytesWritten &lt;= 0 { self.error = self.outputStream?.streamError as NSError? } else { self.outputBuffer?.replaceSubrange(0..&lt;byteswritten, with:="" data())&lt;br=""&gt; } } } }Now, in Swift 5, I get the following warning in Line 12:'withUnsafeBytes' is deprecated: use `withUnsafeBytes(_: (UnsafeRawBufferPointer) throws -&gt; R) rethrows -&gt; R` insteadI have read several posts on the topic but still have not figured out how to deal with the wanring in my case.Your help would be greatly appreciated!
2
0
1.8k
Nov ’19
Adding gradient background to SKScene
Hi.I am trying to add background with gradient color to my SKScene:class GameScene: SKScene { override func didMove(to view: SKView) { let gradientView = UIView(frame: CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.height)) let image = UIImage.gradientBackgroundImage(bounds: CGRect(x: 0, y: 0, width: frame.width, height: frame.height), colors: [UIColor.yellow.cgColor, UIColor.blue.cgColor]) let background = SKSpriteNode(color: UIColor(patternImage: image), size: frame.size) addChild(background) } } extension UIImage { /** http://www.riptutorial.com/ios/example/14328/gradient-image-with-colors */ static func gradientBackgroundImage(bounds: CGRect, colors: [CGColor]) -&gt; UIImage { let gradientLayer = CAGradientLayer() gradientLayer.frame = bounds gradientLayer.colors = colors UIGraphicsBeginImageContext(gradientLayer.bounds.size) gradientLayer.render(in: UIGraphicsGetCurrentContext()!) let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return image! } }This is not working. Is there a better way to add gradient background to the SKScene?Thanks a lot!EDIT:If I do this in didMove(to view:):self.view?.backgroundColor = UIColor.blue let backgroundDep = IGABackgroundLayer().gradientMetar() // My method to create CAGradientLayer backgroundDep.frame = self.view!.bounds self.view!.layer.insertSublayer(backgroundDep, at: 0)...background is created nicely but added SKNodes are not seen on top of it.
5
0
4.2k
Sep ’18
How to draw an arc in MKMapView?
Hello. I got another question.I need to draw half-circle on MKMapView knowing the center coordinates, start and end angles, and radius in nautical miles.I have subclassed MKOverlayPathRenderer:import UIKit import MapKit class IGAAcarsDrawArc: MKOverlayPathRenderer { let PI = 3.14159265 let radius : CGFloat = 10.0 var startAngle: CGFloat = 0 var endAngle: CGFloat = 3.14159 var latitude = 25.96728611 var longitude = -80.453019440000006 override func createPath() { let line = MKPolyline() let arcWidth: CGFloat = 5 let path = UIBezierPath(arcCenter: CGPointMake(CGFloat(latitude), CGFloat(longitude)), radius: self.radius, startAngle: startAngle, endAngle: endAngle, clockwise: true) path.lineWidth = arcWidth path.stroke() } }Now, it is not clear how do I use this to create MKPolyline and implement in mapView(mapView: MKMapView, rendererForOverlay overlay: MKOverlay). Does anyone know how to draw an arc in MKMapView?Thanks a lot!
2
0
1.6k
Jun ’16
Remove only one polyline of several
Hello.I have two polylines on the map:var polylineRoute : MKGeodesicPolyline! var polylineFlight : MKGeodesicPolyline!I assign each of them a title and add them to the map like this (in different methods):let polyline = MKGeodesicPolyline(coordinates: &amp;routeCoordinates, count: routeCoordinates.count) polyline.title = "route" self.mapView.addOverlay(polyline) self.polylineRoute = polylineandlet polyline = MKGeodesicPolyline(coordinates: &amp;routeCoordinates, count: routeCoordinates.count) polyline.title = "flight" self.mapView.addOverlay(polyline) self.polylineFlight = polylineNow, when a specific action is triggered, I would like to remove the flight overlay and leave the route overlay intact.This does not work at all:func removeFlightPath() { self.mapView.removeOverlay(self.polylineFlight) self.polylineFlight = nil }The following works but removes both polylines:func removeFlightPath() { var overlays = mapView.overlays mapView.removeOverlays(overlays) }Is there a working way to remove only one polyline?Thanks a lot!
2
0
2.6k
Feb ’16
NSUserDefaults with tuples
Hello. I am using NSUserDefaults to save values, e.g.let defaultsLoad = NSUserDefaults.standardUserDefaults() // Strings string1 = defaultsLoad.stringForKey("String1") // Arrays let array1 = defaultsLoad.objectForKey("Array1") as? NSData if let array1 = array1 { self.array = NSKeyedUnarchiver.unarchiveObjectWithData(array1) as! [String] }My question is: how do I save and retrieve tuples in swift? I have a tuple variable(String,String,String)and an array of these tuples:[(String,String,String)]These do not work:let defaultsLoad = NSUserDefaults.standardUserDefaults() defaultsLoad.setObject(tuple1, forKey:"Tuple1") let tupleArrayData = NSKeyedArchiver.archivedDataWithRootObject(tupleArray) defaultsLoad.setObject(tupleArrayData, forKey: "TupleArray")let defaultsLoad = NSUserDefaults.standardUserDefaults() tuple1 = defaultsLoad.objectForKey("Tuple1") // This one does not show any error. The problem is with saving let tupleArrayData = defaultsLoad.objectForKey("TupleArray") as? NSData if let tupleArrayData = tupleArrayData { tupleArray = NSKeyedUnarchiver.unarchiveObjectWithData(tupleData) as! [(String,String,String)] }Thanks a lot!
6
0
4.0k
Oct ’15