I'd like my map controller to save the visibleRegion when loading markers. Then as the user moves the map I can compare the current visibleRegion with the region that contains the markers.
I attempted to create a property to save a copy of a GMSVisibleRegion but I'm not understanding something about saving a struct.
So how can I take a snapshot of a visibleRegion and store it in my map controller for reference later?
typedef struct {
CLLocationCoordinate2D nearLeft;
CLLocationCoordinate2D nearRight;
CLLocationCoordinate2D farLeft;
CLLocationCoordinate2D farRight;
} GMSVisibleRegion;
Add an instance variable where you want to store the region:
#interface ViewController : UIViewController
{
GMSVisibleRegion region;
GMSMapView* mapView;
}
#end
Get the current visibleRegion:
region = mapView.projection.visibleRegion;
Related
Whats the best way to pass data to a UITabBarController from a UIViewController in Swift 3?
I am building a single view application and I have a details view which needs to be split into 4 sections. I want to use a TabBar to achieve this and pass an ID from a list in UIViewController and then pass that value down to each individual UIViewController in the TabBar. This is so that I can call a web method which takes the ID to fill out data in the individual views.
The app is being converted from Obj-C with a Storyboard to Swift 3 without a Storyboard so I don't have access to the usual segue definitions I did have. I also used to use UserDefaults in the Obj-C version to save away the selected ID and then pull it out again in the individual views. However, I'm not convinced this is the best way to achieve what I am after.
So far I have tried passing along by accessing the UITabBarController class in the initial UIViewController and setting a variable in the ViewController and then passing it down to the ViewController in the first tab. This works if I am pushing from UIViewController to UIViewController (The first view in the TabBar, but run standalone) but doesn't work when the target Controller is a TabBarController.
I have also tried posting a Notification in the ViewControler and Observing the result in the TabBarController. However the observe code is never called. I'm using:
Selected Row:
NotificationCenter.default.post(name: notificationName, object: selectedRowID)
Then in ViewDidLoad on the TabBarController (Also tried viewDidAppear and viewWillAppear):
NotificationCenter.default.addObserver(self, selector: #selector(setID), name: notificationName, object: nil)
The above works, BUT, only when I select the second tab and then go back to the first tab and then it gets called twice!?!?!
I have also tried a Singleton class, but that just flat out didn't work.
Is using UserDefaults really the best way to do this?
You can create a new class holding the variables to pass the value:
class MyTabController: UITabBarController {
var myPassedString = String()
}
Go to the StoryBoard, select the tab bar controller and open the Identity inspector, change the class to: MyTabController.
let tabBarController = window?.rootViewController as? UITabBarController
Define in each ViewController where you need the shared data:
var myPassedString = String()
To make to this variable shared, code in each ViewController:
override func viewDidLoad() {
super.viewDidLoad()
myPassedString = (tabBarController as! MyTabController).myPassedString
}
Thanks. I am not using a storyboard.
Got it working using a singleton after realising that
1. To get the values back out you must call the singleton in viewWillAppear rather than viewDidLoad and
2. When programmatically creating this, the viewWillAppear of the first child view in the TabBar is observed instead of the viewWillAppear of the actual TabBar controller itself.
for reference for anyone else trying to do similar, my code as follows
open class LastAccessedEvent {
var ID : String = ""
class var sharedInstance : LastAccessedEvent {
struct Static {
static let instance : LastAccessedEvent = LastAccessedEvent()
}
return Static.instance
}
var EventID : String {
get{
return self.ID
}
set {
self.ID = newValue
}
}
}
then in the viewWillAppear of the child view,
if !LastAccessedEvent.sharedInstance.ID.isEmpty{
let myEventID = LastAccessedEvent.sharedInstance.ID
}
So I have a Main .Fla/.SWF File which contains buttons to load in external SWF files using a LoadSWF class.
My Main class save/load code is:
private function saveData(): void {
// savedData can now take any number of properties of any type
// playerGameData is the variable name in which data is saved
savedGameData.data.savedPlayerData = playerData;
savedGameData.flush();
loadData();
tracePlayerData();
}
private function loadData(): void {
// gets the data stored in the SharedObject
playerData = savedGameData.data.savedPlayerData;
}
Assuming a set of saved data can be traced as: trace("Player Name:", playerData.playerName);
How can I load in the saved data, "playerData.playerName" into one of my externally loaded SWF files, so I can give a personalized message such as msgDisplay.text = playerData.playerName + "You Win!"
What you want to do is to pass data from a swf to another.
The simplest way to do it is to pass them using the URL parameters, for instance :
swf2.swf?params=lol
You can pass JSON or such inside that types of parameters, so you'll be able to pass full objects with any number or property.
Document yourself on how to generate, parse, and send json through URL parameters.
I have a struct, file, and a class with functions in it. I'm trying to create a linked list of structs in my function, but I can't quite understand how to go about doing it! Here's my work thus far for that portion of my code:
#include <iostream>
using namespace std;
class myPrintSpool
{
public:
void send(string);
private:
int printSpoolSize;
myPrintSpool *printSpoolHead;
myPrintSpool* next;
};
struct file
{
string fileName;
int filePriority;
file* next;
};
void myPrintSpool::send(string name)
{
//Adds to linked list
file file;
myPrintSpool* file = new myPrintSpool;
if(printSpoolHead == NULL)
{
printSpoolHead = file;
}
else
{
file->next = printSpoolHead;
printSpoolHead = file;
}
printSpoolSize++;
}
I send a string inside the function so that when the user inputs a file name to send, it changes the name of the struct to that fileName in struct file changes to that input name. However, I'm not sure what to do since I cannot get the above portion to work properly first.
Thank you in advance, and thank you for taking the time to help me out!
It's been a while since I've done any C++, so this is all from recollection. In the code you supplied, you aren't instantiating a class. You are allocating memory for one.
If you want to assign a new class to that memory:
myPrintSpool printSpool = new myPrintSpool();
myPrintSpool *file = &printSpool;
I'm somewhat confused as to what you are actually doing. It seems the printSpoolHead will always be equal to the current myPrintSpool object, and if it's anything other than the first instantiation, it points back to itself.
As you didn't say anything specific as to the location of your error(s), do a simple output to verify the function is doing what you think it should (or is) doing.
Edit: Actually, I recall being thrown off by C++ instantiation, so it may be:
myPrintSpool printSpool;
EDIT: onload() method changed to afterLoad(): Otherwise objects might not be passed properly to the map.
I am currently using some domain classes with a lot of dynamic, complex properties, that I need to persist and update regularly.
I keep these in a Map structure for each class since this makes it easy for referencing in my controllers etc.
However, since Grails does not seem to be able to persist complex property types like List and Map in the DB I am using the following approach to achieve this via JSON String objects:
class ClassWithComplexProperties {
Map complexMapStructure //not persisted
String complexMapStructureAsJSON //updated and synched with map via onload,beforeInsert,beforeUpdate
static transients = ['complexMapStructure']
def afterLoad() { //was previously (wrong!): def onLoad() {
complexMapStructure=JSON.parse(complexMapStructureAsJSON)
}
def beforeInsert() {
complexMapStructureAsJSON= complexMapStructure as JSON
}
def beforeUpdate() {
complexMapStructureAsJSON= complexMapStructure as JSON
}
static constraints = {
complexMapStructureAsJSON( maxSize:20000)
}
}
This works well as long I am only loading data from the DB, but I run into trouble when I want to save back my changes to the DB. E.g. when I do the following
/* 1. Load the json String, e.g. complexMapStructureAsJSON="""{
data1:[[1,2],[3,4]],//A complex structure of nested integer lists
data1:[[5,6]] //Another one
}""" :
*/
ClassWithComplexProperties c=ClassWithComplexProperties.get(1)
// 2. Change a value deep in the map:
c.complexMapStructure.data1[0][0]=7
// 3. Try to save:
c.save(flush:true)
This will usually not work, since, I guess(?), GORM will ignore the save() request due to the fact that the map itself is transient, and no changes are found in the persisted properties.
I can make it work as intended if I hack step 3 above and change it to:
// 3.Alternative save:
complexMapStructureAsJSON="" //creating a change in persisted property (which will be overwritten anyway by the beforeUpdate closure)
c.save(flush:true)
To me this is not a very elegant handling of my problem.
The questions:
Is there a simpler approach to persist my complex, dynamic map data?
If I need to do it the way I currently do, is there a way to avoid the hack in step 3 ?
For option 2, you can use the beforeValidate event instead of beforeInsert and beforeUpdate events to ensure that the change propagates correctly.
class ClassWithComplexProperties {
Map complexMapStructure //not persisted
String complexMapStructureAsJSON //updated and synched with map via onload,beforeInsert,beforeUpdate
static transients = ['complexMapStructure']
def onLoad() {
complexMapStructure=JSON.parse(complexMapStructureAsJSON)
}
// >>>>>>>>>>>>>>
def beforeValidate() {
complexMapStructureAsJSON= complexMapStructure as JSON
}
// >>>>>>>>>>>>>>
static constraints = {
complexMapStructureAsJSON( maxSize:20000)
}
}
I of course do not know much about the application you are building, but it won't hurt to look up alternate data storage models particularly NOSQL databases. Grails has got some support for them too.
Is there a simpler approach to persist my complex, dynamic map data?
Grails can persist List and Map out of the box, you don't need to write complex conversion code and abuse Json.
Example for Map:
class ClassWithComplexProperties {
Map<String, String> properties
}
def props = new ClassWithComplexProperties()
props.properties = ["foo" : "bar"]
props.save()
Example for List:
class ClassWithComplexProperties {
List<String> properties
static hasMany = [properties: String]
}
def props = new ClassWithComplexProperties()
props.properties = ["foo", "bar"]
props.save()
I think this is much easier and cleaner way how to deal with it.
In response to
Is there a simpler approach to persist my complex, dynamic map data?
Grails can persist Sets, Lists and Maps to the database. That may be a simpler approach than dealing with JSON conversions. To have the map persisted to the database you need to include it in the hasMany property.
Map complexMapStructure
static hasMany = [complexMapStructure: dynamicComplexPropertyObject]
The documentation suggests that using a Bag may be more efficient.
What's the best practice for passing data between the main class and the view class and vice versa?
main.as
var model : Model = new Model();
var view : View = new View();
var controller : controller = new Controller();
public function callFromView() : void {}
view.as
// how to reference the main.as
private function callToMain() : void
{
// please help
}
I generally handle communication by changing properties in the model via the controller. On change of values in the model, i will dispatch events representing those changes. Anyone (Main in this case) that has a reference to the model can subscribe to those events. This results in a more circuitous implementation, but to a very loosely coupled result.
Create a variable inside your View class called:
var main:Main;
Then a function to receive an object of type Main that sets the variable you created above, like this:
public function setMain(mainIN:Main):void
{
main = mainIN;
}
Now you have a local copy of all the data contained in your main document class in your View class. You can access properties of main by doing this (inside your view class' functions):
main.model.x = mouseX; //just an example. For this, your model variable inside Main would need to be public.
To do data passing the other way, you simply create public properties or functions inside your View class, and then because you've created the instance of View inside your Main class, it will be able to access it as normal with code like:
view.someViewFunction();
In this way each class has access to each other's properties and functions. I hope this helps!