I'm trying to get the JSON from a website and parse it before putting it inside of an iOS view.
Here's my code;
func startConnection(){
let urlPath: String = "http://binaenaleyh.net/dusor/"
var url: NSURL = NSURL(string: urlPath)
var request: NSURLRequest = NSURLRequest(URL: url)
var connection: NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: false)
connection.start()
}
func connection(connection: NSURLConnection!, didReceiveData data: NSData!){
self.data.appendData(data)
}
func buttonAction(sender: UIButton!){
startConnection()
}
func connectionDidFinishLoading(connection: NSURLConnection!) {
var err: NSError
// throwing an error on the line below (can't figure out where the error message is)
var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
}
And this is the link for the JSON;
http://binaenaleyh.net/dusor/
What am I doing wrong here?
These two functions worked for me:
func getJSON(urlToRequest: String) -> NSData{
return NSData(contentsOfURL: NSURL(string: urlToRequest))
}
func parseJSON(inputData: NSData) -> NSDictionary{
var error: NSError?
var boardsDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(inputData, options: NSJSONReadingOptions.MutableContainers, error: &error) as NSDictionary
return boardsDictionary
}
UPDATE: Swift 4
// Asynchronous Http call to your api url, using URLSession:
URLSession.shared.dataTask(with: URL(string: "http://api.site.com/json")!) { (data, response, error) -> Void in
// Check if data was received successfully
if error == nil && data != nil {
do {
// Convert to dictionary where keys are of type String, and values are of any type
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String: Any]
// Access specific key with value of type String
let str = json["key"] as! String
} catch {
// Something went wrong
}
}
}.resume()
Here is how to do it with Swift 2 and NSURLSession:
// Asynchronous Http call to your api url, using NSURLSession:
NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: "http://api.site.com/json")!, completionHandler: { (data, response, error) -> Void in
// Check if data was received successfully
if error == nil && data != nil {
do {
// Convert NSData to Dictionary where keys are of type String, and values are of any type
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! [String:AnyObject]
// Access specific key with value of type String
let str = json["key"] as! String
} catch {
// Something went wrong
}
}
}).resume()
This code works fine for me. Just init data property with data = NSMutableData() and write NSURLConnectionDelegate here class ViewController: UIViewController, NSURLConnectionDelegate
import UIKit
class ViewController: UIViewController, NSURLConnectionDelegate {
#lazy var data = NSMutableData()
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
startConnection()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func startConnection(){
let urlPath: String = "http://binaenaleyh.net/dusor/"
var url: NSURL = NSURL(string: urlPath)
var request: NSURLRequest = NSURLRequest(URL: url)
var connection: NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: false)
connection.start()
}
func connection(connection: NSURLConnection!, didReceiveData data: NSData!){
self.data.appendData(data)
}
func buttonAction(sender: UIButton!){
startConnection()
}
func connectionDidFinishLoading(connection: NSURLConnection!) {
var err: NSError
// throwing an error on the line below (can't figure out where the error message is)
var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
println(jsonResult)
}
}
here is output:
{
"ders sayisi" = 15;
dersler = (
{
0 = "2013-2014";
1 = BAHAR;
10 = TeacherHold;
11 = 2;
12 = "";
2 = 2;
3 = "CEE 102";
4 = "Logic Circuits";
5 = 3;
6 = "6.00";
7 = "YRD.DO\U00c7.DR.INDRIT MYDERRIZI";
8 = 0;
9 = IA;
},
{
0 = "2013-2014";
1 = BAHAR;
10 = TeacherHold;
11 = 1;
12 = "";
2 = 2;
3 = "CIP 102";
4 = "Civic Involment Projects";
5 = 0;
6 = "2.00";
7 = "SE\U00c7\U0130L AVCI/BA\U015eAK CANSU AK\U00c7EL\U0130K/\U00c7A\U011eLA UNGUN";
8 = 0;
9 = P;
},
{
0 = "2013-2014";
1 = BAHAR;
10 = TeacherHold;
11 = 2;
12 = "";
2 = 2;
3 = "COME 108";
4 = "Algorithms and Programming II";
5 = 3;
6 = "6.00";
7 = "\U00d6\U011eR.G\U00d6R.DR.B\U0130RSEN G\U00dcLDEN \U00d6ZDEM\U0130R";
8 = 41;
9 = C;
},
{
0 = "2013-2014";
1 = BAHAR;
10 = TeacherHold;
11 = 1;
12 = "";
2 = 2;
3 = "COME 335";
4 = "Mobile Application Development";
5 = 3;
6 = "5.00";
7 = "\U00d6\U011eR.G\U00d6R.OZAN UYSAL";
8 = TeacherHold;
9 = TeacherHold;
},
{
0 = "2013-2014";
1 = BAHAR;
10 = TeacherHold;
11 = 1;
12 = "";
2 = 2;
3 = "ENG 112";
4 = "Advanced English For Engineering and Natural Sciences I";
5 = 2;
6 = "3.00";
7 = "OKT.ERIC BEECHER";
8 = 48;
9 = F;
},
{
0 = "2013-2014";
1 = BAHAR;
10 = TeacherHold;
11 = 1;
12 = "";
2 = 2;
3 = "PHYS 102";
4 = "Physics II";
5 = 4;
6 = "5.00";
7 = "YRD.DO\U00c7.DR.\U00d6ZG\U00dcL KURTULU\U015e \U00d6ZT\U00dcRK";
8 = "-1";
9 = F;
},
{
0 = "2013-2014";
1 = BAHAR;
10 = TeacherHold;
11 = 2;
12 = "";
2 = 2;
3 = "T\U00dcRK 102";
4 = "T\U00fcrk Dili II";
5 = 2;
6 = "2.00";
7 = "\U00d6\U011eR.G\U00d6R.\U015eER\U0130FE GEZG\U0130N";
8 = 10;
9 = F;
},
{
0 = "2013-2014";
1 = "G\U00dcZ";
10 = TeacherHold;
11 = 2;
12 = "";
2 = 1;
3 = "CHEM 101";
4 = Chemistry;
5 = 3;
6 = "5.00";
7 = "YRD.DO\U00c7.DR.AY\U015eEN TULPAR";
8 = TeacherHold;
9 = F;
},
{
0 = "2013-2014";
1 = "G\U00dcZ";
10 = TeacherHold;
11 = 1;
12 = "";
2 = 1;
3 = "CIP 101";
4 = "Civic Involment Projects";
5 = 0;
6 = "1.00";
7 = "YRD.DO\U00c7.DR.FATMA G\U00dcL AYGEN/Staff CIP1/SE\U00c7\U0130L AVCI/D\U0130LAYDA EM\U0130R/BA\U015eAK CANSU AK\U00c7EL\U0130K/\U00c7A\U011eLA UNGUN";
8 = TeacherHold;
9 = P;
},
{
0 = "2013-2014";
1 = "G\U00dcZ";
10 = TeacherHold;
11 = 3;
12 = "";
2 = 1;
3 = "COME 107";
4 = "Algorithms and Programming I";
5 = 4;
6 = "5.00";
7 = "PROF.DR.M\U0130TAT UYSAL";
8 = TeacherHold;
9 = "C+";
},
{
0 = "2013-2014";
1 = "G\U00dcZ";
10 = TeacherHold;
11 = 2;
12 = "";
2 = 1;
3 = "ENG 101";
4 = "Advanced English";
5 = 2;
6 = "3.00";
7 = "OKT.EZG\U0130 ARGUN";
8 = TeacherHold;
9 = B;
},
{
0 = "2013-2014";
1 = "G\U00dcZ";
10 = TeacherHold;
11 = 1;
12 = "";
2 = 1;
3 = "IUL 100";
4 = "Introduction to University Life";
5 = 0;
6 = "1.00";
7 = "YRD.DO\U00c7.DR.FATMA G\U00dcL AYGEN";
8 = TeacherHold;
9 = F;
},
{
0 = "2013-2014";
1 = "G\U00dcZ";
10 = TeacherHold;
11 = 2;
12 = "";
2 = 1;
3 = "MATH 111";
4 = "Calculus I";
5 = 4;
6 = "5.00";
7 = "DO\U00c7.DR.G\U00dcRSEL YE\U015e\U0130LOT";
8 = TeacherHold;
9 = F;
},
{
0 = "2013-2014";
1 = "G\U00dcZ";
10 = TeacherHold;
11 = 4;
12 = "";
2 = 1;
3 = "PHYS 101";
4 = "Physics I [CNE]";
5 = 4;
6 = "5.00";
7 = "YRD.DO\U00c7.DR.AR\U0130F \U00d6ZBAY";
8 = TeacherHold;
9 = F;
},
{
0 = "2013-2014";
1 = "G\U00dcZ";
10 = TeacherHold;
11 = 9;
12 = "";
2 = 1;
3 = "T\U00dcRK 101";
4 = "T\U00fcrk Dili I [CNE]";
5 = 2;
6 = "2.00";
7 = "\U00d6\U011eR.G\U00d6R.ARZU AYG\U00dcN";
8 = TeacherHold;
9 = F;
}
);
}
If the original JSON is an array, try this.
func parseJSON(inputData: NSData) -> Array<NSDictionary>{
var error: NSError?
var boardsDictionary = NSJSONSerialization.JSONObjectWithData(inputData, options: NSJSONReadingOptions.MutableContainers, error: &error) as Array<NSDictionary>
return boardsDictionary
}
The example below sends a request to fetch stock information - it's a bit more comprehensive, but has more cleanup and structure:
import Foundation
private let kSNStockInfoFetchRequestPath:String = "http://dev.markitondemand.com/Api/v2/Quote/json"
private func SNStockInfoFetchRequestURL(symbol:String) -> NSURL? {
if let components:NSURLComponents = NSURLComponents(string:kSNStockInfoFetchRequestPath) {
components.queryItems = [NSURLQueryItem(name:"symbol", value:symbol)]
return components.URL
}
return nil
}
private func SNStockInfoFetchRequestURLRequest(symbol:String) -> NSURLRequest? {
if let requestURL:NSURL = SNStockInfoFetchRequestURL(symbol) {
var request:NSMutableURLRequest = NSMutableURLRequest(URL:requestURL)
request.HTTPMethod = "GET"
return request
}
return nil
}
private func SNStockInfoFetchRequestParseData(receivedData:NSData, error:NSErrorPointer) -> NSDictionary? {
return NSJSONSerialization.JSONObjectWithData(receivedData, options:NSJSONReadingOptions.MutableContainers, error:error) as? NSDictionary
}
class SNStockInfoFetchRequest: NSObject,
NSURLConnectionDataDelegate
{
private let symbol:String
private (set) var fetching:Bool
private lazy var receivedData = NSMutableData()
init(symbol:String) {
self.symbol = symbol
self.fetching = false
}
func start() {
assert(!fetching, "Should not start a request that has already started!")
fetching = true
if let request:NSURLRequest = SNStockInfoFetchRequestURLRequest(symbol) {
var connection:NSURLConnection = NSURLConnection(request:request, delegate:self, startImmediately:true)!
connection.start()
}
}
// MARK: NSURLConnectionDataDelegate
func connection(connection:NSURLConnection, didReceiveData data:NSData) {
assert(fetching, "Should only receive data while activly fetching!")
self.receivedData.appendData(data)
}
func connectionDidFinishLoading(connection:NSURLConnection) {
var error:NSError?
if let result:NSDictionary = SNStockInfoFetchRequestParseData(receivedData, &error) {
println(result)
} else {
println(error)
}
}
}
We can now use the request as such:
let fetcher:SNStockInfoFetchRequest = SNStockInfoFetchRequest(symbol:"MSFT")
fetcher.start()
This should output the JSON in case of a success, or the error in case of a failure. Hope this helps! If you use the same structure, make sure to use a delegate to either return the parsed JSON (or even better, an immutable value object) or indicate a failure.
The answer of #david72 worked perfectly for me. So here's the same in Swift 3 and URLSession for your convenience. Also with some added error printing for easier debugging.
func getHttpData(urlAddress : String)
{
// Asynchronous Http call to your api url, using NSURLSession:
guard let url = URL(string: urlAddress) else
{
print("Url conversion issue.")
return
}
URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) -> Void in
// Check if data was received successfully
if error == nil && data != nil {
do {
// Convert NSData to Dictionary where keys are of type String, and values are of any type
let json = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as! [String:AnyObject]
print(json)
// Access specific key with value of type String
// let str = json["key"] as! String
} catch {
print(error)
// Something went wrong
}
}
else if error != nil
{
print(error)
}
}).resume()
}
//
// ViewController.swift
// Test2
//
// Created by fingent on 11/08/15.
// Copyright (c) 2015 fingent. All rights reserved.
//
import UIKit
class ViewController: UIViewController,NSURLConnectionDelegate
{
lazy var data = NSMutableData()
#IBAction func t1(sender: AnyObject) {
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
startConnection()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func startConnection(){
let urlPath: String = "https://api.github.com/users/mralexgray"
var url: NSURL = NSURL(string: urlPath)!
var request: NSURLRequest = NSURLRequest(URL: url)
var connection: NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: false)!
connection.start()
}
func connection(connection: NSURLConnection!, didReceiveData data: NSData!){
self.data.appendData(data)
}
func buttonAction(sender: UIButton!){
startConnection()
}
func connectionDidFinishLoading(connection: NSURLConnection!) {
var err: NSError
// throwing an error on the line below (can't figure out where the error message is)
var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
println(jsonResult)
}
}
Here is swift 3.1 code
URLSession.shared.dataTask(with: NSURL(string: "http://pastebin.com/raw/wgkJgazE")! as URL, completionHandler: { (data, response, error) -> Void in
// Check if data was received successfully
if error == nil && data != nil {
do {
// Convert NSData to Dictionary where keys are of type String, and values are of any type
let json = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as! [String:AnyObject]
// Access specific key with value of type String
let str = json["key"] as! String
} catch {
// Something went wrong
}
}
}).resume()
Request api REST-GET in iOS Swift
I present a very simple App where a rest service is consumed through the GET method and the information obtained is presented in our main view.
Note:
This project is built with CocoaPods, for more information go to https://cocoapods.org.
PodFile structure:
# Uncomment the next line to define a global platform for your project
# platform :ios, '8.0'
target 'ExampleRestApi' do
# Comment the next line if you don't want to use dynamic frameworks
#use_frameworks!
# Pods for ExampleRestApi
use_modular_headers!
pod 'Alamofire', '~> 5.0'
pod 'AFNetworking', '~> 2.6'
pod 'ORStackView', '~> 3.0'
end
Steps
HelperNetwork.swift: Copy HelperNetwork file, which contains the method to consume the service through Alamofire.
//
// HelperNetwork.swift
// ExampleRestApi
//
// Created by MacBook Pro on 20/11/20.
//
import Foundation
import Alamofire
public var URL_API = "https://icenparty.pythonanywhere.com/icenPartyWeb/api/v1/"
public var GET_STORE = "doStore"
public var METHOD_GET: HTTPMethod = .get
class HelperNetwork{
//Example get json for method GET
func doRequest(urlString : String,
parameters : Parameters,
method : HTTPMethod,
completion: #escaping (AFDataResponse <Any>)->()) {
let url = URL.init(string: URL_API + urlString)
AF.request(url!, method: method, parameters: parameters, encoding: URLEncoding.default, headers: nil).responseJSON {
response in completion(response)
}
}
}
BaseResponse.swift: Copy BaseResponse file, which contains the models corresponding to the information obtained in the service response.
//
// BaseResponse.swift
// ExampleRestApi
//
// Created by MacBook Pro on 20/11/20.
//
/*
BaseResponse is used to create all the models that
we need for the service response.
*/
import Foundation
public struct Store : Codable{
var pk: Int
var fields: Fields
}
public struct Fields : Codable {
var file_img_home: String
var file_img_2: String
var file_img_3: String
var title: String
var subTitle: String
var description: String
var value: Int
var material: String
var color: String
var sizes_list: String
var brand: String
}
public struct JSONResponseStore: Codable {
var success: Bool
var message: String
var stores : [Store]
}
ViewController.swift: In our viewController file, call our doRequest method
to which the necessary parameters are passed to obtain the json.
#IBOutlet weak var lblResponse: UILabel!
var helperNetwork = HelperNetwork()
/**
Get info from server for method GET
*/
func getJsonRequestGET(){
//Set text lbl
lblResponse.text = "Consultando informaciĆ³n...."
//parameters for get , we need tag typeStore
let parameters: Parameters = [ "typeStore" : "Hombre",]
self.helperNetwork.doRequest(urlString: GET_STORE,
parameters: parameters,
method: METHOD_GET) { (response) -> () in
// do stuff with the result
switch response.result
{
case .success( _):
do {
//Decode data From model JSONResponseStore , can be changed to any model
let JSONData = try JSONDecoder().decode(JSONResponseStore.self, from: response.data!)
if(JSONData.success){
self.lblResponse.text = "Respuesta: \(JSONData.stores)"
}else{
self.lblResponse.text = "Respuesta: \(JSONData.message)"
}
} catch let jsonError {
self.lblResponse.text = "Respuesta: \(jsonError)"
}
case .failure(let error):
self.lblResponse.text = "Respuesta: \(error)"
}
}
}
I remain attentive to any concerns,
Cheers
Related
I need to increase count for every 5 matches
if total_count is 0,1,2,3,4,5 then pageNum = 1
if total_count is 5,6,7,8,9,10 then pageNum = 2...
for eg. if total_count is 50 then pageNum = 50/5 = 10
here total_count = 3 but when I refresh each time currentPageNumberVM is increasing, but why?
code: for above logic i have written code like this currentPageNumberVM += 1 + Int((self.paginationData?.result?.total_count ?? 0 - 1) / 5). But here total_count stays the same. But when I refresh currentPageNumberVM is increasing all the time. How to solve this issue?
var currentPageNumberVM: Int = 1
var isLoadingList: Bool = false
override func viewDidLoad() {
super.viewDidLoad()
self.currentPageNumberVM = 1
self.PagenationMachesService(currentPageNumberVM)
}
private var paginationData = PaginationMaches(dictionary: NSDictionary())
func PagenationMachesService(_ pageNumber: Int) {
let param = ["slug": slugVal ?? "", "page_no": currentPageNumberVM] as [String: Any]
APIReqeustManager.sharedInstance.serviceCall(
param: param as [String: Any], method: .post, url: CommonUrl.get_matches
) { [weak self] (resp) in
if (self?.currentPageNumberVM)! > 1 {
if (PaginationMaches(dictionary: resp.dict as NSDictionary? ?? NSDictionary())?.result?
.matches ?? [Matches]()).count != 0
{
self?.paginationData?.result?.matches! +=
PaginationMaches(dictionary: resp.dict as NSDictionary? ?? NSDictionary())?
.result?.matches ?? [Matches]()
} else {
self?.showSingleButtonAlertWithoutAction(title: "NO more data to show")
}
} else {
self?.paginationData = PaginationMaches(
dictionary: resp.dict as NSDictionary? ?? NSDictionary())
}
self?.isLoadingList = false
self?.machesTable.reloadData()
}
}
#objc func refresh() {
self.currentPageNumberVM += 1 + Int((self.paginationData?.result?.total_count ?? 0 - 1) / 5)
self.PagenationMachesService(currentPageNumberVM)
}
extension MatchesVC {
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if (scrollView.contentOffset.y + scrollView.frame.size.height)
>= scrollView.contentSize.height
{
self.isLoadingList = true
self.refresh()
}
}
}
You are increasing the value of currentPageNumberVM because you are using the "addition assignment operator" +=.
Change it to the "assignment" operator = and it should work fine.
self.currentPageNumberVM = 1 + Int((self.paginationData?.result?.total_count ?? 0 - 1) / 5)
documentation
I am new to swift/spritekit, i was asked by my 8 year old to make him a basic game so i said yes (almost regretting it now lol)
What i am trying to achieve: a character who has the ability to "level up" based off experience points earned - I am using a JSON file to describe the levels
JSON file:
[
{
"id": 1,
"spriteTexture": "playerL1",
"weapon": "playerL1Weapon",
"expToLvlUp": 50,
"health": 2,
"attack": 1,
"defense": 1,
},
{
"id": 2,
"spriteTexture": "playerL2",
"weapon": "playerL2Weapon",
"expToLvlUp": 60,
"health": 7,
"attack": 2,
"defense": 2,
},
{
"id": 3,
"spriteTexture": "playerL3",
"weapon": "playerL3Weapon",
"expToLvlUp": 100,
"health": 10,
"attack": 5,
"defense": 5,
}
]
Decodable file:
import Foundation
extension Bundle{
func decode<T: Decodable>(_ Type: T.Type, from file: String) -> T {
guard let url = self.url(forResource: file, withExtension: nil) else {
fatalError("Failed to locate \(file) in bundle")
}
guard let data = try? Data(contentsOf: url) else{
fatalError("Failed to load \(file) from bundle")
}
let decoder = JSONDecoder()
guard let loaded = try? decoder.decode(T.self, from: data) else {
fatalError("Failed to decode /(file) from bundle")
}
return loaded
}
}
I have set up a struct to get the values from the JSON file:
import SpriteKit
struct PlayerLevel: Codable {
let id: Int
let spriteTexture: String
let weapon: String
let expToLvlUp: Int
let health: Int
let attack: Int
let defense: Int
}
and here is my class:
import Foundation
import SpriteKit
class Player: SKSpriteNode {
var type: PlayerLevel
{
didSet{
levelUp()
}
}
init(type: PlayerLevel){
self.type = type
let texture = SKTexture(imageNamed: type.spriteTexture)
super.init(texture: texture, color: .clear, size: texture.size())
position.x = -900
physicsBody = SKPhysicsBody(texture: texture, size: texture.size())
physicsBody?.categoryBitMask = CollisionType.player.rawValue
physicsBody?.collisionBitMask = CollisionType.enemy.rawValue | CollisionType.enemyWeapon.rawValue
physicsBody?.contactTestBitMask = CollisionType.enemy.rawValue | CollisionType.enemyWeapon.rawValue
zPosition = 5
name = "player"
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func shoot(){
let shot = SKSpriteNode(imageNamed: type.weapon)
shot.name = self.type.weapon
shot.size = CGSize(width: 50, height: 50)
shot.physicsBody = SKPhysicsBody(rectangleOf: shot.size)
shot.physicsBody?.categoryBitMask = CollisionType.playerWeapon.rawValue
shot.physicsBody?.collisionBitMask = CollisionType.enemy.rawValue | CollisionType.enemyWeapon.rawValue
shot.physicsBody?.contactTestBitMask = CollisionType.enemy.rawValue | CollisionType.enemyWeapon.rawValue
addChild(shot)
shot.zPosition = 3
shot.physicsBody?.affectedByGravity = false
let movement = SKAction.move(to: CGPoint(x: 4000, y: shot.position.y), duration: 1)
let sequence = SKAction.sequence([movement, .removeFromParent()])
shot.run(sequence)
}
func levelUp(){
self.texture = SKTexture(imageNamed: type.spriteTexture)
let texture = SKTexture(imageNamed: type.spriteTexture)
self.physicsBody = SKPhysicsBody(texture: texture, size: texture.size())
}
}
Firstly, i'm wondering if i have this set up the right way.
In my game scene:
import SpriteKit
import GameplayKit
enum CollisionType: UInt32 {
case player = 1
case playerWeapon = 2
case enemy = 4
case enemyWeapon = 8
case ground = 16
}
class GameScene: SKScene, SKPhysicsContactDelegate {
// Properties
var isPlayerAlive = true
var playerLevels = Bundle.main.decode([PlayerLevel].self, from: "player-levels.json")
let enemyTypes = Bundle.main.decode([EnemyType].self, from: "enemies.json")
var currentEnemy = 0
var currentLevel = 0 {
didSet {
player.type = playerLevels[currentLevel]
}
}
var player: Player!
var enemy: Enemy!
var levelUp: SKSpriteNode!
var healthLabel: SKLabelNode!
var scoreLabel: SKLabelNode!
let playerLevelLabel = SKLabelNode(fontNamed: "Chalkduster")
var score = 0 {
didSet{
scoreLabel.text = "Score: \(score)"
}
}
let ground = SKSpriteNode(imageNamed: "groundBottom")
let groundT = SKSpriteNode(imageNamed: "gameGroundTop")
var expLabel: SKLabelNode!
var exp = 0 {
didSet{
expLabel.text = "Experience Points: \(exp) / \(playerLevels[currentLevel].expToLvlUp)"
}
}
var health = 0 {
didSet{
healthLabel.text = "Health: \(playerLevels[currentLevel].health)"
}
}
override func didMove(to view: SKView) {
physicsWorld.contactDelegate = self
makeGround()
initializePlayer()
spawnEnemy()
makeScoreLabel()
makeExpLabel()
makeHealthLabel()
}
func initializePlayer(){
player = Player(type: playerLevels[currentLevel])
addChild(player)
playerLevelLabel.text = "Details: \(player.type)"
playerLevelLabel.fontSize = 40
playerLevelLabel.position = CGPoint(x: 0, y: self.frame.minY + 200)
}
func makeScoreLabel(){
scoreLabel = SKLabelNode(fontNamed: "Chalkduster")
scoreLabel.position = CGPoint(x:self.frame.maxX - 250, y:self.frame.maxY - 100)
scoreLabel.horizontalAlignmentMode = .right
scoreLabel.fontSize = 40
scoreLabel.zPosition = 5
scoreLabel.text = "Score: 0"
scoreLabel.name = "score"
addChild(scoreLabel)
}
func makeExpLabel(){
expLabel = SKLabelNode(fontNamed: "Chalkduster")
expLabel.position = CGPoint(x:self.frame.minX + 500, y:self.frame.maxY - 110)
scoreLabel.fontSize = 40
expLabel.zPosition = 5
expLabel.text = "Expereience Points: 0 / \(playerLevels[currentLevel].expToLvlUp)"
expLabel.name = "exp"
addChild(expLabel)
}
func makeHealthLabel(){
healthLabel = SKLabelNode(fontNamed: "Chalkduster")
healthLabel.position = CGPoint(x:self.frame.minX + 1200, y:self.frame.maxY - 110)
healthLabel.fontSize = 40
healthLabel.zPosition = 5
healthLabel.text = "Health: \(playerLevels[currentLevel].health)"
healthLabel.name = "health"
addChild(healthLabel)
}
func makeGround(){
ground.name = "ground"
ground.position.x = frame.midX
ground.position.y = frame.minY
ground.zPosition = 1
addChild(ground)
ground.physicsBody = SKPhysicsBody(texture: ground.texture!, size: ground.texture!.size())
ground.physicsBody?.affectedByGravity = false
ground.physicsBody?.isDynamic = false
groundT.position.x = frame.midX
groundT.position.y = ground.position.y + 50
groundT.physicsBody?.isDynamic = false
addChild(groundT)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
let location = touch?.location(in: self)
let nodesAtLocation = nodes(at: location!)
for node in nodesAtLocation {
if node.name == "score"{
score += 10
exp += 5
upgrade()
}
if node.name == "attack"{
attack()
}
}
}
func upgrade() {
if exp < playerLevels[currentLevel].expToLvlUp { return }
if currentLevel + 1 > playerLevels.count - 1 {
gameOver()
return
}
if let explosion = SKEmitterNode(fileNamed: "Explosion") {
explosion.position = player.position
addChild(explosion)
}
//charLevelUp()
currentLevel += 1
playerLevelLabel.text = "Details: \(player.type)"
}
func didBegin(_ contact: SKPhysicsContact) {
guard let nodeA = contact.bodyA.node else { return }
guard let nodeB = contact.bodyB.node else { return }
let sortedNodes = [nodeA, nodeB].sorted { $0.name ?? "" < $1.name ?? ""}
let firstNode = sortedNodes[0]
let secondNode = sortedNodes[1]
if firstNode.name == "ground" { return }
if secondNode.name == "ground" { return }
if secondNode.name == "player" {
guard isPlayerAlive else { return }
if let explosion = SKEmitterNode(fileNamed: "explosion"){
explosion.position = firstNode.position
addChild(explosion)
}
//health -= 1
if playerLevels[currentLevel].health == 0{
gameOver()
secondNode.removeFromParent()
}
firstNode.removeFromParent()
} else if let enemy = firstNode as? Enemy {
enemy.health -= 1
if enemy.health == 0 {
if let explosion = SKEmitterNode(fileNamed: "Explosion") {
expLabel.position = enemy.position
addChild(explosion)
}
enemy.removeFromParent()
score += 50
exp = enemy.expGive
}
if let explosion = SKEmitterNode(fileNamed: "Explosion") {
explosion.position = enemy.position
addChild(explosion)
}
secondNode.removeFromParent()
} else {
if let explosion = SKEmitterNode(fileNamed: "Explosion") {
explosion.position = secondNode.position
addChild(explosion)
}
firstNode.removeFromParent()
secondNode.removeFromParent()
}
}
I've managed to get the sprite to change texture and physics body, the expReq points to change based on the players level, however, I can't seem to update the health property or any of the others. Any help would be appreciated - I'm not sure if I have this set up correctly - please advise :)
This question already has an answer here:
Swift 3 incorrect string interpolation with implicitly unwrapped Optionals
(1 answer)
Closed 6 years ago.
i'm using Swift 3.0 and I want to post data into mysql database from X Code 8.
I can print the value and remove Optional("") in x code, but when it send into mysql database, the Optional("") String still added.
I believe that i'm having a problem on this line of code. My question is how to post the value without Optional("") ?
var d1: String!
var d2: String!
d1 = _data1.text
d2 = _data2.text
let paramToSend = "data1=\(d1)&data2=\(d2)"
And here is my ViewController.swift
import UIKit
class ViewController: UIViewController {
#IBOutlet var _data1: UITextField!
#IBOutlet var _data2: UITextField!
#IBOutlet var _send_button: UIButton!
var d1: String!
var d2: String!
override func viewDidLoad() {
super.viewDidLoad(
}
#IBAction func sendData(_ sender: Any) {
d1 = _data1.text
d2 = _data2.text
if (d1 == "" || d2 == "") {
return
}
else {
let url = URL(string: "http://localhost/send.php")
let session = URLSession.shared
let request = NSMutableURLRequest(url: url! as URL)
request.httpMethod = "POST"
let paramToSend = "data1=\(d1)&data2=\(d2)"
request.httpBody = paramToSend.data(using: String.Encoding.utf8)
let task = session.dataTask(with: request as URLRequest) { (data, response, error) in
guard let _:NSData = data as NSData?, let _:URLResponse = response, error == nil else {
print("Error")
return
}
if let dataString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue) {
print(dataString)
let newdata1: String? = d1
let newdata2: String? = d2
print(newdata1!)
print(newdata2!)
}
}
task.resume()
}
}
}
First of all, don't declare your variables as optionals if possible:
var d1: String = ""
var d2: String = ""
d1 = _data1.text ?? ""
d2 = _data2.text ?? ""
When I load my table then activate the search, I can get the search data in my tableview. To make my app faster, I create a seperate view only for search. But I couldn't get my tableview populated with search data. I can see I get the data correctly with print(data), but my table is not populated.
class YazarTableViewController: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate {
var searchResults: [JSON]? = []
var searchController = UISearchController()
#IBOutlet weak var searchButton: UIBarButtonItem!
#IBAction func searchButtonTouched(sender: AnyObject) {
showSearchBar()
}
func showSearchBar() {
self.searchController = ({
let controller = UISearchController(searchResultsController: nil)
controller.searchResultsUpdater = self
controller.searchBar.delegate = self
controller.dimsBackgroundDuringPresentation = true
controller.searchBar.alpha = 0
navigationItem.setLeftBarButtonItem(nil, animated: true)
UIView.animateWithDuration(0.5, animations: {
controller.searchBar.alpha = 1
}, completion: { finished in
controller.searchBar.becomeFirstResponder()
})
self.tableView.tableHeaderView = controller.searchBar
return controller
})()
}
}
func updateSearchResultsForSearchController(searchController: UISearchController)
{
self.searchResults?.removeAll(keepCapacity: false)
if (!searchController.searchBar.text!.isEmpty){
let parameters = ["q" : searchController.searchBar.text]
var searchURL = "http://apilink.com/" + String(parameters) + "/1"
searchURL = searchURL.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!
Alamofire.request(.GET, searchURL, encoding: .JSON)
.responseJSON{ response in
guard response.result.error == nil else {
// got an error in getting the data, need to handle it
print("error calling GET on /posts/1")
print(response.result.error!)
return
}
if let value: AnyObject = response.result.value {
let post = JSON(value)
if let data = post[].arrayValue as [JSON]?{
self.searchResults = data
self.tableView.reloadData()
print(data)
}
}
}
}
}
I am trying to get an array of values from a JSON file using Swift. I found the way to get the values printed when a button is pressed using a IBAction method.
The Function is printing the array fine the first time the button is pressed however, if I press the button again the app crashes giving the error:
fatal error: unexpectedly found nil while unwrapping an Optional value
(lldb)
The array that I get the first time from printing jsonResult looks Like:
1: {
Age = 30;
Email = "info#example.com";
Location = Rome;
MyText = "Design Agency";
Name = Admin;
Password = 123456;
REF = 002;
"Reg_Date" = "2015-07-28";
Sex = Male;
Surname = "Mobile App"; }
2: {
Age = 30;
Email = "example#gmail.com";
Location = London;
MyText = "aaaaaaaaa";
Name = Andrew;
Password = 123456;
REF = 001;
"Reg_Date" = "2015-07-28";
Sex = Male;
Surname = Nos; }
It seems that the second time I call the function, it cannot read the file anymore.
Whats wrong with my code? Do I need to close the connection?
#IBAction func login_button(sender: AnyObject) {
searchFunction()
}
func searchFunction() {
var tempUrlValue = loginJsonResults.stringForKey("loginJsonResults")
let urlPath: String = "https://example.com/iOS/users_result.json"
var url: NSURL = NSURL(string: urlPath)!
var request: NSURLRequest = NSURLRequest(URL: url)
var connection: NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: false)!
connection.start()
}
func connection(connection: NSURLConnection!, didReceiveData data: NSData!){
self.data.appendData(data)
}
func connectionDidFinishLoading(connection: NSURLConnection!) {
var err: NSError
var jsonResult: NSMutableArray = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as! NSMutableArray
//Call jsonResult Values
var temporaryString: AnyObject = jsonResult[1]
for (index, jsonResult) in enumerate(jsonResult){
println("\(index + 1): \(jsonResult)")
countUsers++
}
println(countUsers)
}