Swfit - How can I use the UserDefaults to store variable and how to load the variable from UserDefaults next time - swiftyuserdefaults

I need to store some variables like ione and itwo which for method repeat.
The variables value will increase,after increased,I want to store the increased variables into userdefaults.
import UIKit
class ViewController: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
/* How can I load UserDefaults here to restore ione's value and
itwo's value and How to store them in UserDefaults ? */
let ionevalue = ione
println(ionevalue)
let itwovalue = itwo
println(itwovalue)
// Do any additional setup after loading the view, typically from a nib.
}
var ione = 0
var itwo = 0
ione++
itwo++
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

ok,I finally got inspired in SOF and I figure it out,I initial a public NSUserDefaults can be used in any Func:
let aaa = NSUserDefaults.standardUserDefaults()
and use below code to store the update value :
aaa.setObject(AnythingYouInitialed, forKey: "DefineAKeyYouWant")
and use below code to load the value from NSUserDefaults:
if let bbb = aaa.valueForKey("DefineAKeyYouWant") as?Int
{
ccc = bbb
}
Now I have load the value and I can use it by assign ccc into other variabels.
I'm a old guy of 30 years old and I'm just starting be a programmer,that's not easy for me...haha...

Related

CollectionView using NSDiffableDataSource with UICollectionViewFlowLayout

When I use UICollectionView with UICollectionViewFlowLayout set. And then try to apply snapshots of datasource via
// load initial data
reloadDataSource()
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(3)) {
self.reloadDataSource(animating: true)
}
I am getting crash on second snapshot applied after 3 seconds delay.
The crash is happening only when animating: true
If I set animating to false then there is no crash but the collection view if left empty.
Here is this mathod applying data source
extension CollectionViewController {
func reloadDataSource(animating: Bool = false) {
print("reloading data source with snapshot -> \(snapshot.numberOfItems)")
self.dataSource.apply(self.snapshot, animatingDifferences: animating) {
print("applying snapshot completed!")
}
}
}
Data source is just
let dataSource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView, cellProvider: cellProvider)
Full project you can play (may changes over time): https://github.com/michzio/SwifUICollectionView
Update
I've tried to simplify example and do something like this and it doesn't work correctly. It seems that moving .apply() to background queue, other queue causes empty data in collectionview
func reloadDataSource(animating: Bool = false) {
print("reloading data source with snapshot -> \(snapshot.numberOfItems)")
diffQueue.async {
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections([.categories])
snapshot.appendItems(Item.categoryItems)
self.dataSource.apply(snapshot, animatingDifferences: animating) {
print("applying snapshot completed!")
}
}
}
Ok it seems that i found the reason of all my errors with updating datasource by applying new snapshots
This lazy var dataSource is causing errors:
private(set) lazy var dataSource: UICollectionViewDiffableDataSource<Section, Item> = {
let dataSource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView, cellProvider: cellProvider)
//dataSource.supplementaryViewProvider = supplementaryViewProvider
return dataSource
}()
I've changed it to
private(set) var dataSource: UICollectionViewDiffableDataSource<Section, Item>!
and after configureCollectionView in viewDidLoad()
now I am calling configureDataSource() that does what was in lazy var initializer.

Swift Here API Examples

I'm incorporating the HERE SDK into my app. Aside from one simple map setup, all the examples on the HERE website are shown in objective-C, and I'm trying my best to translate them into Swift but it's not working 100% yet. I'm trying to put a route between 2 coordinates onto a map view as per their routing example shown at:
https://developer.here.com/mobile-sdks/documentation/ios/topics/routing.html
The interesting thing is that if I just call for the map everything works, but if I add the routing part I get the following error:
NMAKit FATAL: License Key, App ID, or App Code not set. error on launch which is odd because the credentials are fine! So I think the bug is entirely in my Swift translation.
The instructions in objective-C are very clear:
1. Adopt NMARouteManagerDelegate protocol and create a NMARouteManager:
#interface ClassName : NSObject <NMARouteManagerDelegate>
{
// Setup your class
}
(void)setup
{
Create a NMARouteManager.**
NMARouteManager* routeManager = [NMARouteManager sharedRouteManager];
// Setup delegate
[routeManager setDelegate:self];
}
2. Create an NSMutableArray and add two NMAGeoCoordinates stops:
NSMutableArray* stops = [[NSMutableArray alloc] initWithCapacity:4];
NMAGeoCoordinates* geoCoord1 = [[NMAGeoCoordinates alloc]
initWithLatitude:49.1966286 longitude:-123.0053635];
NMAGeoCoordinates* geoCoord2 = [[NMAGeoCoordinates alloc]
initWithLatitude:49.1947289 longitude:-123.1762924];
[stops addObject:geoCoord1];
[stops addObject:geoCoord2];
3. Create an NMARoutingMode and set its NMATransportMode, NMARoutingType and NMARoutingOption values:
NMARoutingMode* routingMode = [[NMARoutingMode alloc]
initWithRoutingType:NMARoutingTypeFastest
transportMode:NMATransportModeCar
routingOptions:0];
4. Calculate the route:
[routeManager calculateRouteWithStops:stops routingMode:routingMode];
5. To receive the results of the route calculation, implement the NMARouteManagerDelegate protocol method
routeManager:didCalculateRoutes:withError:violatedOptions: in your delegate class.
Note: Routes are returned even if you receive the NMARouteManagerErrorViolatesOptions error. It is up to you to handle these route results that violate routing options.
-(void) routeManager: (NMARouteManager*)routeManager
didCalculateRoutes:(NSArray*)routes
withError:(NMARouteManagerError)error
violatedOptions:(NSArray*)violatedOptions
{
// If the route was calculated successfully
if (!error && routes && routes.count > 0)
{
NMARoute* route = [routes objectAtIndex:0];
// Render the route on the map
mapRoute = [NMAMapRoute mapRouteWithRoute:route];
[mapView addMapObject:mapRoute];
}
else if (error)
{
// Display a message indicating route calculation failure
}
}
And this is what I'm trying to do in Swift:
import UIKit
//I changed the NMARouteManagerDelegate to my original class here
//and couldnt allow NSObject in the class delegation because it conflicts with UIViewController
class TestViewController: UIViewController, NMARouteManagerDelegate {
var mapCircle:NMAMapCircle?
#IBOutlet weak var mapView: NMAMapView!
#IBAction func get_route_action(sender: AnyObject) {
doRouting()
}
let routeManager = NMARouteManager.sharedRouteManager()
func doRouting() {
let geoCoord1 = NMAGeoCoordinates(latitude:41.350949, longitude:-74.182097)
let geoCoord2 = NMAGeoCoordinates(latitude:41.3437502, longitude:-74.1624284)
let stops = [geoCoord1, geoCoord2]
routeManager.calculateRouteWithStops(stops)
}
func routeManager(routeManager: NMARouteManager!, didCalculateRoutes routes: [AnyObject]!, withError error: NMARouteManagerError, violatedOptions: [AnyObject]!) {
print(routes)
print(error)
print(violatedOptions)
guard error == NMARouteManagerError.None else {
print("Route calculation error: \(error)")
return
}
guard let routes = routes, route = routes[0] as? NMARoute else {
print("Route calculation error: no routes")
return
}
let mapRoute = NMAMapRoute(route: route)
// Render the route on the map
mapView.addMapObject(mapRoute)
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
//mapView.useHighResolutionMap = true
var coordinates: NMAGeoCoordinates
coordinates = NMAGeoCoordinates(latitude: 41.350949, longitude: -74.182097)
mapView.zoomLevel = 13.2
mapView.setGeoCenter(coordinates, withAnimation: NMAMapAnimation.Linear)
mapView.copyrightLogoPosition = NMALayoutPosition.BottomCenter
addMapCircle()
}
func addMapCircle() {
if mapCircle == nil {
let coordinates: NMAGeoCoordinates =
NMAGeoCoordinates(latitude: 41.350949, longitude: -74.182097)
mapCircle = NMAMapCircle(geoCoordinates: coordinates, radius: 50)
mapView.addMapObject(mapCircle)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I tried your code, and worked basically for me quite fine.
But I additionally added the credentials in AppDelegate.swift:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
NMAApplicationContext.setAppId(YourAppID, appCode: YourToken, licenseKey: YourKey);
return true;
}
This is critical, since if it's missing, it's throwing exactly the error you get.

How to create a static pointer variable to itself in Swift?

In Objective-C I often use the pattern of using a static void* as an identification tag. At times these tags are only used within that function/method, hence it's convenient to place the variable inside the function.
For example:
MyObscureObject* GetSomeObscureProperty(id obj) {
static void* const ObscurePropertyTag = &ObscurePropertyTag;
MyObscureObject* propValue = objc_getAssociatedObject(id,ObscurePropertyTag);
if(!propValue) {
propValue = ... // lazy-instantiate property
objc_setAssociatedObject(obj,ObscurePropertyTag,propValue, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
return propValue;
}
The question is, how to write the ObscurePropertyTag private-constant-pointer-to-itself in Swift? (Preferrably 2.1 but future already-announced versions should be okay)
I've looked around and it seems that I have to put this ObscurePropertyTag as a member variable and there doesn't seem to be a way around it.
Unlike (Objective-)C, you cannot take the address of an
uninitialized variable in Swift. Therefore creating a self-referencing
pointer is a two-step process:
Swift 2:
var ptr : UnsafePointer<Void> = nil
withUnsafeMutablePointer(&ptr) { $0.memory = UnsafePointer($0) }
Swift 3:
var ptr = UnsafeRawPointer(bitPattern: 1)!
ptr = withUnsafePointer(to: &ptr) { UnsafeRawPointer($0) }
For your purpose, is it easier to use the address of a global variable with &, see for
example
Is there a way to set associated objects in Swift?.
If you want to restrict the scope of the "tag" to the function itself
then you can use a static variable inside a local struct. Example:
func obscureProperty(obj : AnyObject) -> MyObscureObject {
struct Tag {
static var ObscurePropertyTag : Int = 0
}
if let propValue = objc_getAssociatedObject(obj, &Tag.ObscurePropertyTag) as? MyObscureObject {
return propValue
}
let propValue = ... // lazy instantiate property value
objc_setAssociatedObject(obj, &Tag.ObscurePropertyTag,propValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return propValue
}
Try this:
var GetSomeObscureProperty: MyObscureObject = nil
withUnsafePointer(& GetSomeObscureProperty) {
GetSomeObscureProperty = MyObscureObject($0)
}
In short
let GetSomeObscureProperty = UnsafePointer<()>()

Appending JsonFile (UrL) in array to display on application

I am trying to add my data from my Json file into the application.I want append the Authors name from the Json file into the empty array.
I have added all of the areas that needed to be added when i run the simulation i get an empty array. I need it display the Authors first name on the simulator.
Does anyone know what i need to do to my code to make it work?
My Code :
var AuthorGlobal = [String]()
class ViewController: UIViewController, UITextFieldDelegate{
#IBOutlet weak var DisplayAuthor: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
DisplayAuthor.text="\(AuthorGlobal)"
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated);
Alamofire.request(.GET, "http://178.62.83.50/newsletters.json")
.responseJSON { response in
// print(response.request) // original URL request
// print(response.response) // URL response
// print(response.data) // server data
// print(response.result) // result of response serialization
if let _ = response.result.value {
// print("JSON: \(JSON)")
}
let json = JSON(data: response.data!)
if let Author = json["NewsLetter"][0]["Author"].string {
AuthorGlobal.append(Author)
}
if let LastName = json["NewsLetter"][0]["LastName"].string {
print(LastName)
}
if let ArticleTitle = json["NewsLetter"][0]["ArticleTitle"].string {
//Now you got your value
print(ArticleTitle)
}
if let Author = json["NewsLetter"][1]["Author"].string {
//Now you got your value
print(Author)
}
if let LastName = json["NewsLetter"][1]["LastName"].string {
//Now you got your value
print(LastName)
}
if let ArticleTitle = json["NewsLetter"][1]["ArticleTitle"].string {
//Now you got your value
print ("Article Title: " + (ArticleTitle))
}
}
}
I just tried by putting your json in my file system and loading it locally. Below is my code on Swift 2 and it all worked fine. You might want to check the JSON data coming correctly in your service call. Also, try to compare it line by line with my code to see if you missed out something. Its too late for me to call it a day so bear with me to not pointing out the exact root cause in your code!
var AuthorGlobal = [String]()
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var DisplayAuthor: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// DisplayAuthor.text="\(AuthorGlobal)"
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated);
let filePath = NSBundle.mainBundle().pathForResource("1", ofType: "json")
var fileContents : String = ""
do {
fileContents = try String(contentsOfFile: filePath!, encoding: NSUTF8StringEncoding)
} catch (_) {
}
var json : Dictionary<String,Array<Dictionary<String,String>>> = Dictionary()
do {
json = try NSJSONSerialization.JSONObjectWithData(fileContents.dataUsingEncoding(NSUTF8StringEncoding)!, options:NSJSONReadingOptions.AllowFragments) as! Dictionary<String, Array<Dictionary<String, String>>>
} catch (_) {
}
let array = json["NewsLetter"] as Array?
if let author = array?[0]["Author"] {
AuthorGlobal.append(author)
}
print(AuthorGlobal) // This prints - ["Tom"]
if let LastName = array?[0]["LastName"] {
print(LastName) // This prints - Holton
}
if let ArticleTitle = array?[0]["ArticleTitle"] {
//Now you got your value
print(ArticleTitle) // This prints - XcodeGhost: Apple suffers a major malware infection inside the iOS app store.
}
if let Author = array?[1]["Author"] {
//Now you got your value
print(Author) // This prints - Sam
}
if let LastName = array?[1]["LastName"] {
//Now you got your value
print(LastName) // This prints - Devaney
}
if let ArticleTitle = array?[1]["ArticleTitle"] {
//Now you got your value
print ("Article Title: " + (ArticleTitle)) // This prints - Article Title: Google is 2 Billion Lines of Code
}
}
}

How i get back to old scene in SpriteKit?

How can I go to old scene in SpriteKit ( in Swift ) ? I am in scene1 , i paused it and i move to scene 2 and I want to get back to scene1 and i to resume it . I don't want to recreate it again .
Thanks.
EDIT :
So , I tried this :
In secondScene class i put a oldScene SKScene property and a computed setOldScene property:
class SecondScene: SKScene {
var oldScene:SKScene?
var setOldScene:SKScene? {
get { return oldScene }
set { oldScene = newValue }
}
init(size: CGSize) {
super.init(size: size)
/* Setup my scene here */
}}
And then , in FirstScene class ( where i have ONE moving ball ) , in touchBegan method i have this
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
/* Called when a touch begins */
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
if(self.view.scene.paused) {
self.view.scene.paused = false
}
else {
self.view.scene.paused = true
}
var secondScene = SecondScene(size: self.frame.size)
secondScene.setOldScene = self.scene
if !transition { self.view.presentScene(secondScene, transition: SKTransition.doorsOpenHorizontalWithDuration(2)) ; transition = true }
}
}
But , when i call self.view.presentScene(oldScene) in SecondScene class i move yo first class and i have TWO balls that moving :-??
I can't use class variable , Xcode not suport yet .
I solved this issue by having a public property on the second scene.
And then using that to present the first scene.
So in the First Scene, when you want to show the second scene....
if let scene = SKScene(fileNamed: "SecondScene") as! SecondScene?
{
scene.parentScene = self
self.view?.presentScene(scene)
}
This following code is in the SecondScene.
When ready to return to the first scene, just call the method showPreviousScene()...
public var parentScene: SKScene? = nil
private func showPreviousScene()
{
self.view?.presentScene(parentScene!)
}
You will have to keep a reference to your old scene around, and then when you want to move back to it, simply call
skView.presentScene(firstScene)
on your SKView instance.
There are several ways to keep a reference to your class around. You could use a Singleton, or simply a class with a class type property to store the reference and access it from anywhere.