Restart MKUserTrackingMode.FollowWithHeading - mkusertrackingmode

Code:
map.UserTrackingMode = MKUserTrackingMode.FollowWithHeading;
But after a user interacts with the map or after mKMapView.ShowAnnotations, the map automatically stops following the device's heading. (Not by my code. That's just how mkmapview works. This is also the case in the built in Maps app.)
How can I make the map start following the device's heading again from code?

This is exactly like how the Maps app works and is what the user will expect. The behavior you're describing is completely normal; you shouldn't interfere with it.
The usual thing is that you put an MKUserTrackingButton in the interface, associated with the map view, and the user can just tap it to switch modes automatically. Except for initially configuring the button, no code is needed.
https://developer.apple.com/documentation/mapkit/mkusertrackingbutton
or
https://developer.apple.com/documentation/mapkit/mkusertrackingbarbuttonitem

Related

NSPopover to start in a detached state

Is there a way to force the NSPopover to start in the detached state? I only see isDetached which is a read-only property for the state of the popover and an NSPopoverDelegate method detachableWindow(forPopover:) which lets me override the window that gets created. I'd like to essentially click a button and have the NSPopover start in the state in this photo.
The style of this window is exactly what a product requirement is and I can't seem to find any NSWindow style settings that would make a window do something like this (nor an NSPanel)
This detached popover functionality seems special in that it:
non-modal, but stays above main app. Able to still interact with the main app just like in Messages how you can still click around and type a new message.
Clicking another app, AppFoo, puts both the main app and the helper window behind AppFoo.
The helper window can be moved around and isn't hidden on app deactivation (another app gets selected).
Has the little, native, grey X in the top left.
If you don't mind calling private API, it's actually pretty simple:
let detach = NSSelectorFromString("detach")
if popover.responds(to: detach) {
popover.perform(detach)
}
No need to even add a delegate. I don't know when this private method was added but it's available at least since macOS 10.13. I suspect it's available since the introduction of NSPopover, though.
Here is the trick.
Use the required delegate method detachableWindowForPopover: to do the work for you, like:
- (void) showPopoverDetached
{
NSWindow* detachedWindow = [self detachableWindowForPopover:nil];
[detachedWindow.windowController showWindow:nil];
}
Seems that the Apple engineers implemented detachableWindowForPopover: on a pretty smart way, I guess it uses the content view controller class, and will always create a singleton like instance of the detached window.
Once detachableWindowForPopover: has called the presented window instance will be re-used no matter when and why it is called, called it directly (from a func like my sample above) or indirectly (e.g. when you drag out, detach, the popover from its original position)
This way they can prevent a popover from being detached 'twice' and we can also implement the detached way programmatically, nice job from them!
Here is a tiny demo of how it works in a real life (tested on macOS 10.13 - 13.0)
https://imgur.com/a/sfc7e6d

Bing Maps Touch Responsiveness to Map Pins on Mobile

I've created a Bing Maps tool to view High Schools and Competitions in out state. The implementation works perfectly on the desktop. You can click on a map pin, and you see either the School information or the Competition information.
However, I noticed today that on my iPhone, the map pins do not respond, i.e. the Info Box does not open. I tried it in Chrome in Responsive mode, and I get the same thing.
I'm using the standard map pins on one and a FontAwesome map pin on the other, but neither is responsive. What am I missing?
https://www.mshsaa.org/Activities/ClassAndDistrictAssignments.aspx?alg=3&class=1
https://www.mshsaa.org/Activities/Scoreboard.aspx?alg=3&view=map
Well, I figured it out. I guess I didn't give enough details.
It turns out I had bound show and hide of the Infoboxes to mouseover and mouseout. I added binding to the "click" event, and that seems to work fine. I did also need to explicitly hide all previously opened boxes, but that was pretty easy to do:
Microsoft.Maps.Events.addHandler(thisPin, 'click', function () {
$(".Infobox").parent().hide(); /* This hides the other open Infoboxes */
infobox.setOptions({ visible: true })
});

Addon SDK way to make a dialog

What is the proper way to use the SDK to make a dialog (which is not anchored to the add-on bar, etc. but shows centered on screen)? It doesn't seem like there is any API for this important capability. I do see windows/utils has open but I have two problems with that:
The dialog opening seems to require "chrome" privs to get it to be centered on the screen (and I'd be expectant of add-on reviewers complaining of chrome privs, and even if not, I'd like to try to stick to the SDK way).
While I can get the DOM window reference of the new window/utils' open() dialog, I'm not sure how to attach a content script so I can respond to user interaction in a way that prompts (and can respond to) privileged behavior ala postMessage or port.emit (without again, directly working with chrome privs).
Ok, this answer should have been pretty obvious for anyone with a little experience with the SDK. I realized I can just use a panel. In my defense, the name "panel" is not as clear as "dialog" in conjuring up this idea, and I am so used to using panels with widgets, that it hadn't occurred to me that I could use it independently!
Edit
Unfortunately, as per Bug 595040, these dialogs are not persistent, meaning if the panel loses focus, the "dialog" is gone... So panel looks like it is not a suitable candidate after all... :(
Edit 2
I've since moved on and have gotten things working mostly to my satisfaction with sdk/window/utils and openDialog on whose returned window I add a load listener and then call tabs.activeTab.on('ready', and then set tabs.activeTab.url to my add-on local HTML file so the ready event will get a tab to which I can attach a worker. There is still the problem with chrome privs I suppose, but at least the main communications are using SDK processes.
Update to Edit 2:
Code sample provided by request:
var data = require('sdk/self').data,
tabs = require('sdk/tabs');
var win = require('sdk/window/utils').openDialog({
// No "url" supplied here in this case as we add it below (in order to have a ready listener in place before load which can give us access to the tab worker)
// For more, see https://developer.mozilla.org/en-US/docs/Web/API/window.open#Position_and_size_features
features: Object.keys({
chrome: true, // Needed for centerscreen per docs
centerscreen: true, // Doesn't seem to be working for some reason (even though it does work when calling via XPCOM)
resizable: true,
scrollbars: true
}).join() + ',width=850,height=650',
name: "My window name"
// parent:
// args:
});
win.addEventListener('load', function () {
tabs.activeTab.on('ready', function (tab) {
var worker = tab.attach({
contentScriptFile: ....
// ...
});
// Use worker.port.on, worker.port.emit, etc...
});
tabs.activeTab.url = data.url('myHTMLFile.html');
});
if the panel loses focus, the "dialog" is gone...
It doesn't get destroyed, just hides, right? If so, depending on why it's getting hidden, you can just call show() on it again.
You'd want to make sure it's not being hidden for a good reason before calling show again. If there's a specific situation in which it's losing focus where you don't want it to, create a listener for that situation, then call if (!panel.isShown) panel.show();
For example, if it's losing focus because a user clicks outside the box, then that's probably the expected behaviour and nothing should be done. If it's losing focus when the browser/tab loses focus, just register a tab.on('activate', aboveFunction)
Simply adding ",screenX=0,screenY=0" (or any values, the zeroes seem to be meaningless) to the features screen seems to fix centerscreen.

Google Maps APi for iOS: UIActivityView on custom info window

I'm trying to put a spinner inside a custom info window that appears when the user presses a marker. I have a custom view for the window that has lots of subviews that show up fine. But when I try to add a UIActivityView or an animated PNG sequence, that doesn't show. Has anyone else experienced this?
The documentation on the mapView:markerInfoWindow: method says:
If you change this view after this method is called, those changes
will not necessarily be reflected in the rendered version.
It seems likely that the Google map is not showing the actual UIView you return, but a screenshot of it taken when the info window is returned by the delegate.
As mentioned in this answer, this is made explicit in the Android documentation - it seems likely that the Android and iOS SDKs work similarly.
If you've changed the view I'm not sure if there is a way to force the SDK to take a new screenshot of it. Possibly you could try setting the map's selected marker to nil and then back to your marker, to see if it then calls mapView:markerInfoWindow: again - although it might also re-centre the marker on the map when you do that. It also likely wouldn't be very efficient.
You can call mapView:markerInfoWindow: then inside the method you can create a UIView which you can add different controls on that UIView including the spinner. You can also specify on which location you would like to put the defined control.

How to simulate a mouse click on a UIWebView in Cocoa for the iPhone?

I'm trying to setup automated unit tests for an iPhone application. I'm using a UIWebView and need to simulate clicks on different links. I've tried doing this with JavaScript, but it doesn't produce the same result as when I manually click on the links. The main problem is with links that have their target property set.
When you manually click on a standard "popup" link (e.g. <a href="http://example.com" target="_blank">), the UIWebView will ignore the click event and won't navigate to anything. If you then try clicking on this very same link automatically via the JavaScript dispatchEvent() method, the UIWebView will completely ignore the target attribute and will open up the link normally in the current page.
I need an my automatic unit testing to produce the exact same results as when you manually click a link.
I believe the only way for this automated unit test to work correctly is to simulate a mouse click at a specific x/y coordinate (i.e. where the link is located). Since the unit testing will only be used internally, private API calls are fine.
It seems like this should be possible since the iPhone app isimulate seems to do something similar.
Is there any way to do this in the framework?
I found a similar question titled Simulate mouse click to window instead of screen, however I'm guessing this method is only valid for OS X, and not for iPhone OS.
I suppose you could simulate the touches by calling the touchesBegan/touchesEnded methods directly on the UIView (check the UIResponder class).
The proper way to do this would be to construct your own UIEvent and then post this event to your UIApplication instance via its -sendEvent: method.
However, there doesn't appear to be a public API for constructing a UIEvent, so you might be out of luck.
Could you store the locations of the clicks in a data structure that you use in your tests and then simulate standard touch events as described here described here
--- Just spotted that you didn't have much luck with the example on this link. The only other options I can suggest would be to manipulate the html when running from a test to replace any _target links (you know that UIWebView handles these properly when clicking manually, so I think a small bodge is ok for the unit test?).
Nice walkthrough in this answer
For your specific case, it may be sufficient to test in the simulator and use a MacOS event generator to make the clicks.
The private calls for recording and sending events are part of GraphicServices/GSEvent.h with the standard use at your own risk disclaimers. Every UIEvent is really a UIInternalEvent that has a reference to a __GSEvent, so for recording you can use the _gsEvent property to get the underlying event.
#property (nonatomic,assign) struct __GSEvent *_gsEvent;
I have not used any of this stuff, but it looks like GSSendSystemEvent would be a good place to start.