Swift global variable - variables

I'm new in swift.
I would like to figure out how to reuse this variable (item) in other ways:
if var item = currentItem?.listCategoryScheme[countCategoryScheme].listCategory{
...
}
I tried to do this:
var item:NSObject?
func{
if item = currentItem?.listCategoryScheme[countCategoryScheme].listCategory{
...
}
} func2{
//here reuse item
}
but does not work
Thanks

Declare your variable like:
var iteam : NSObject = NSObject()
In ViewController class.

var itemGlobal:String = String()
func printItem(item: String)
{
println(item)
itemGlobal = item
}
func printGlobalItem()
{
println(itemGlobal)
}
printItem("Swift") //prints "Swift" and assignes the itemGlobal to "Swift"
printGlobalItem() //prints "Swift", from the itemGlobal, previously assigned

Related

How to convert this Swift syntax into Objective C?

I'm converting a swift project to objective c, but i get some trouble because i don't know how to convert follow code. Please help me. Thanks!
public enum UPCarouselFlowLayoutSpacingMode {
case fixed(spacing: CGFloat)
case overlap(visibleOffset: CGFloat)
}
and
fileprivate var currentPage: Int = 0 {
didSet {
let character = self.items[self.currentPage]
self.infoLabel.text = character.name.uppercased()
self.detailLabel.text = character.movie.uppercased()
}
}
The first (an enum with associated values) has no direct equivalent in Objective-C. For your particular example, you could use something like this:
typedef NS_ENUM(NSInteger, UPCarouselFlowLayoutSpacingMode) {
UPCarouselFlowLayoutSpacingModeFixed,
UPCarouselFlowLayoutSpacingModeOverlap
};
typedef struct {
UPCarouselFlowLayoutSpacingMode mode;
CGFloat amount;
} UPCarouselFlowLayoutSpacing;
You would just pass around values of type UPCarouselFlowLayoutSpacing. You could create helper functions to make these easier to create, e.g.
UPCarouselFlowLayoutSpacing UPCarouselFlowLayoutSpacingMakeFixed(CGFloat spacing) {
UPCarouselFlowLayoutSpacing value;
value.mode = UPCarouselFlowLayoutSpacingModeFixed;
value.amount = spacing;
return value;
}
UPCarouselFlowLayoutSpacing UPCarouselFlowLayoutSpacingMakeOverlap(CGFloat visibleOffset) {
UPCarouselFlowLayoutSpacing value;
value.mode = UPCarouselFlowLayoutSpacingModeOverlap;
value.amount = visibleOffset;
return value;
}
For the second, you can override the setter method of your Objective-C class's currentPage property:
- (void)setCurrentPage:(NSInteger)page {
_page = page;
MovieCharacter *character = self.items[page];
self.infoLabel.text = character.name.localizedUppercaseString;
self.detailLabel.text = character.movie.localizedUppercaseString;
}

NSMutableArray. Objective-c to swift code

I'm trying to convert this Objective-C code to swift, but can't seem to figure it out:
#implementation MultiplayerNetworking {
uint32_t _ourRandomNumber;
GameState _gameState;
BOOL _isPlayer1, _receivedAllRandomNumbers;
NSMutableArray *_orderOfPlayers;
#define playerIdKey #"PlayerId"
#define randomNumberKey #"randomNumber"
- (id)init
{
if (self = [super init]) {
_ourRandomNumber = arc4random();
_gameState = kGameStateWaitingForMatch;
_orderOfPlayers = [NSMutableArray array];
[_orderOfPlayers addObject:#{playerIdKey : [GKLocalPlayer localPlayer].playerID, randomNumberKey : #(_ourRandomNumber)}];
}
return self;
}
};
This is what I thought I would be, but I'm no sure at all, so I would appreciate som help here.
class MultiplayerNetworking {
var _ourRandomNumber = uint32_t()
var _gameState = GameState()
var isPlayer1 = false
var receivedAllRandomNumbers = false
var orderOfPlayers = [AnyObject]()
let playerIdKey = "PlayerId"
let randomNumberKey = "randomNumber"
override init() {
super.init()
self.ourRandomNumber = arc4random()
self.gameState = kGameStateWaitingForMatch
self.orderOfPlayers = [AnyObject]()
orderOfPlayers.append([playerIdKey: GKLocalPlayer.localPlayer().playerID, randomNumberKey: ourRandomNumber])
}
}
But it gives me some errors, a lot:
I used this converter: objectivec2swift.com since I have no experience with Objective-C
enum GameState {
case waitingForMatch
}
class MultiplayerNetworking {
var isPlayer1 = false
var receivedAllRandomNumbers = false
var orderOfPlayers = [AnyObject]()
private let playerIdKey = "PlayerId"
private let randomNumberKey = "randomNumber"
private var ourRandomNumber = arc4random()
private var gameState = GameState.waitingForMatch
init() {
orderOfPlayers.append([playerIdKey: GKLocalPlayer.localPlayer.playerID, randomNumberKey: ourRandomNumber] as AnyObject)
}
}
I am assuming that GameState is an enum, and have made the enum with just the one case I can see from your code. I am also guessing that variables starting with an underscore are supposed to be private instance variables of that class, so I have made them private here. Instead of initializing everything in init, I have made use of Swift to give all the properties initial values.
class MultiplayerNetworking {
var _ourRandomNumber = [__uint32_t]()
var _gameState = GameState()
var isPlayer1 = false
var receivedAllRandomNumbers = false
var orderOfPlayers = [AnyObject]()
let playerIdKey = "PlayerId"
let randomNumberKey = "randomNumber"
init() {
self.ourRandomNumber = arc4random()
self.gameState = kGameStateWaitingForMatch
self.orderOfPlayers = [AnyObject]()
orderOfPlayers.append([playerIdKey: GKLocalPlayer.localPlayer().playerID, randomNumberKey: ourRandomNumber])
}
}
Try using this code
class Player{
var playerIdKey : String?
var randomNumberKey : UInt32?
}
class MultiplayerNetworking {
var ourRandomNumber = UInt32()
var gameState = GameState()
var isPlayer1 = false
var receivedAllRandomNumbers = false
var orderOfPlayers = [Player]()
let playerIdKey = "PlayerId"
let randomNumberKey = "randomNumber"
override init() {
self.ourRandomNumber = arc4random()
self.gameState = kGameStateWaitingForMatch
let player = Player()
player.playerIdKey = GKLocalPlayer.localPlayer().playerID
player.randomNumberKey = ourRandomNumber
orderOfPlayers.append(player)
}
}
I would recommend that you create a separate class for player in the previous code the variable was an array type of AnyObject and a tipple was being appended to it so the compiler was complaining. So create a separate player class and set its properties and then append it to your array and your code should run fine.I also removed override keyword from init as there is no super class for this class.

Custom object to NSDictionary or NSData

Guys i am new to iOS development hardly 2 weeks, i want to convert custom object to NSDictionary or NSData. I want to pass that complex object to web API to get and save.
class customClass{
var firstName:String?
var lastName:String?
var services:Services
}
class Services{
var list:[String] = [String]()
}
can somebody help me to resolve this please.
A bit late... try this in playground. Please note that it will not handle NSData correctly. Also, for the code to work, you need to make sure that your custom class inherits from NSObject and adheres to protocol Parsable. That is because you need to make use of the Objective C runtime for this solution to work with classes. Furthermore all your objects need to be subclasses of NSObject (e.g. NSArray instead of Swift type Array).
import UIKit
protocol Parsable {
}
// Define classes as NSObjects
class customClass: NSObject, Parsable {
var firstName:String?
var lastName:String?
var services:Services?
}
class Services: NSObject, Parsable {
var list:NSMutableArray = NSMutableArray()
}
// Create objects
var obj = customClass()
obj.firstName = "My"
obj.lastName = "Name"
var serv = Services()
serv.list = NSMutableArray()
serv.list.addObject("AAA")
serv.list.addObject("BBB")
obj.services = serv
// The magic
func parse(o: NSObject) -> AnyObject {
let aClass : AnyClass? = o.dynamicType
var propertiesCount : CUnsignedInt = 0
let propertiesInAClass : UnsafeMutablePointer<objc_property_t> = class_copyPropertyList(aClass, &propertiesCount)
let propertiesDictionary : NSMutableDictionary = NSMutableDictionary()
if propertiesCount == 0 {
if let a = o as? [NSObject] {
return a.map( {parse($0)} )
} else {
// Take into account NSData here!!!
return o
}
} else {
for var i = 0; i < Int(propertiesCount); i++ {
let property = propertiesInAClass[i]
let propertyName = NSString(CString: property_getName(property), encoding: NSUTF8StringEncoding) as! String
let propertyValue : AnyObject = o.valueForKey(propertyName)!;
if propertyValue is NSObject && propertyValue is protocol<Parsable> {
propertiesDictionary.setValue(parse(propertyValue as! NSObject), forKey: propertyName)
} else {
propertiesDictionary.setValue(propertyValue, forKey: propertyName)
}
}
return propertiesDictionary
}
}
print(parse(obj))
//print(parse(obj.services!))
//print(parse(obj.services!.list))

Get Property List of Swift Class

I am trying to get the property list of a swift class. There is a similar question here and here. I have everything working except for certain types do not get returned from class_copyPropertyList. The ones I have tested it with so far are Int? and enums. I have an example class below of what I am trying.
enum PKApiErrorCode: Int {
case None = 0
case InvalidSignature = 1
case MissingRequired = 2
case NotLoggedIn = 3
case InvalidApiKey = 4
case InvalidLogin = 5
case RegisterFailed = 6
}
class ApiError: Serializable {
let code: PKApiErrorCode?
let message: String?
let userMessage: String?
init(error: JSONDictionary) {
code = error["errorCode"] >>> { (object: JSON) -> PKApiErrorCode? in
if let c = object >>> JSONInt {
return PKApiErrorCode.fromRaw(c)
}
return nil
}
message = error["message"] >>> JSONString
userMessage = error["userMessage"] >>> JSONString
}
}
And the Serializable class (with some help from https://gist.github.com/turowicz/e7746a9c035356f9483d is
public class Serializable: NSObject, Printable {
override public var description: String {
return "\(self.toDictionary())"
}
}
extension Serializable {
public func toDictionary() -> NSDictionary {
var aClass : AnyClass? = self.dynamicType
var propertiesCount : CUnsignedInt = 0
let propertiesInAClass : UnsafeMutablePointer<objc_property_t> = class_copyPropertyList(aClass, &propertiesCount)
var propertiesDictionary : NSMutableDictionary = NSMutableDictionary()
for var i = 0; i < Int(propertiesCount); i++ {
var property = propertiesInAClass[i]
var propName = NSString(CString: property_getName(property), encoding: NSUTF8StringEncoding)
var propType = property_getAttributes(property)
var propValue : AnyObject! = self.valueForKey(propName);
if propValue is Serializable {
propertiesDictionary.setValue((propValue as Serializable).toDictionary(), forKey: propName)
} else if propValue is Array<Serializable> {
var subArray = Array<NSDictionary>()
for item in (propValue as Array<Serializable>) {
subArray.append(item.toDictionary())
}
propertiesDictionary.setValue(subArray, forKey: propName)
} else if propValue is NSData {
propertiesDictionary.setValue((propValue as NSData).base64EncodedStringWithOptions(nil), forKey: propName)
} else if propValue is Bool {
propertiesDictionary.setValue((propValue as Bool).boolValue, forKey: propName)
} else if propValue is NSDate {
var date = propValue as NSDate
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "Z"
var dateString = NSString(format: "/Date(%.0f000%#)/", date.timeIntervalSince1970, dateFormatter.stringFromDate(date))
propertiesDictionary.setValue(dateString, forKey: propName)
} else {
propertiesDictionary.setValue(propValue, forKey: propName)
}
}
return propertiesDictionary
}
public func toJSON() -> NSData! {
var dictionary = self.toDictionary()
var err: NSError?
return NSJSONSerialization.dataWithJSONObject(dictionary, options:NSJSONWritingOptions(0), error: &err)
}
public func toJSONString() -> NSString! {
return NSString(data: self.toJSON(), encoding: NSUTF8StringEncoding)
}
}
The String seem to only appear if the Optionals are valid values and the code never appears on the object if it is an enum or Int unless the Int has a default value.
Thanks for any advice I can get for getting all properties of a class no matter what they are.
I got a response on the apple developer forums regarding this issue:
"class_copyPropertyList only shows properties that are exposed to the Objective-C runtime. Objective-C can't represent Swift enums or optionals of non-reference types, so those properties are not exposed to the Objective-C runtime."
Source
So, in summary, serialization to JSON using this approach is not currently possible. You might have to look into using other patterns to accomplish this, such as giving the task of serialization to each object, or potentially by using the reflect() method to serialize an object to JSON.

JScript.NET private variables

I'm wondering about JScript.NET private variables. Please take a look on the following code:
import System;
import System.Windows.Forms;
import System.Drawing;
var jsPDF = function(){
var state = 0;
var beginPage = function(){
state = 2;
out('beginPage');
}
var out = function(text){
if(state == 2){
var st = 3;
}
MessageBox.Show(text + ' ' + state);
}
var addHeader = function(){
out('header');
}
return {
endDocument: function(){
state = 1;
addHeader();
out('endDocument');
},
beginDocument: function(){
beginPage();
}
}
}
var j = new jsPDF();
j.beginDocument();
j.endDocument();
Output:
beginPage 2
header 2
endDocument 2
if I run the same script in any browser, the output is:
beginPage 2
header 1
endDocument 1
Why it is so??
Thanks,
Paul.
Just a guess, but it appears that JScript.NET doesn't support closures the same way as EMCAScript, so the state variable in endDocument() isn't referencing the private member of the outer function, but rather an local variable (undeclared). Odd.
You don't have to use new when calling jsPDF here since you're using a singleton pattern. jsPDF is returning an object literal so even without new you'll have access to the beginPage and endDocument methods. To be perfectly honest I don't know what the specifications call for when using new on a function that returns an object literal so I'm not sure if JScript.NET is getting it wrong or the browser. But for now try either getting rid of the new before jsPDF() or change your function to this:
var jsPDF = function(){
var state = 0;
var beginPage = function(){
state = 2;
out('beginPage');
};
var out = function(text){
if(state == 2){
var st = 3;
}
MessageBox.Show(text + ' ' + state);
};
var addHeader = function(){
out('header');
};
this.endDocument = function(){
state = 1;
addHeader();
out('endDocument');
};
this.beginDocument: function(){
beginPage();
};
}
That will allow you to use the new keyword and create more than one jsPDF object.
I've come across the same problem. In the following code, the closure bound to fun should contain only one variable called result. As the code stands, the variable result in the function with one parameter seems to be different to the result variable in the closure.
If in this function the line
result = [];
is removed, then the result in the line
return result;
refers to the result in the closure.
var fun = function() {
var result = [];
// recursive descent, collects property names of obj
// dummy parameter does nothing
var funAux = function(obj, pathToObj, dummy) {
if (typeof obj === "object") {
for (var propName in obj) {
if (obj.hasOwnProperty(propName)) {
funAux(obj[propName], pathToObj.concat(propName), dummy);
}
}
}
else {
// at leaf property, save path to leaf
result.push(pathToObj);
}
}
return function(obj) {
// remove line below and `result' 3 lines below is `result' in closure
result = []; // does not appear to be bound to `result' above
funAux(obj, [], "dummy");
return result; // if result 2 lines above is set, result is closure is a different variable
};
}();