I need help with displaying a default mapView to first-time users with no network connectivity. Then as soon as the network is available, load the mapView using the styleURL.
The latter part is taken care of, however, I'm still struggling with displaying the mapView for the first-time users using the local styles I downloaded from Mapbox:
let localURL = Bundle.main.url(forResource: "style", withExtension: "json")
if Reachability.isConnectedToNetwork() == true {
mapView = MGLMapView(frame: view.bounds, styleURL: styleURL)
...
} else {
mapView = MGLMapView(frame: view.bounds, styleURL: localURL)
...
}
Am I missing something?
Related
I'm working on the offline downloads section for a video streaming app. Currently, I'm able to download videos and also can see the file path for the downloads as follows:
Button(action: {
let fileManager = FileManager.default
do {
let resourceKeys : [URLResourceKey] = [.creationDateKey, .isDirectoryKey]
let documentsURL = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let enumerator = FileManager.default.enumerator(at: documentsURL,
includingPropertiesForKeys: resourceKeys,
options: [.skipsHiddenFiles], errorHandler: { (url, error) -> Bool in
print("directoryEnumerator error at \(url): ", error)
return true
})!
for case let fileURL as URL in enumerator {
let resourceValues = try fileURL.resourceValues(forKeys: Set(resourceKeys))
// print(fileURL.path, resourceValues.creationDate!, resourceValues.isDirectory!)
print(fileURL.path)
self.array.append(fileURL.path)
}
} catch {
print(error)
}
}){
Text("Check downloads")
}
//response when button is clicked
/private/var/mobile/Containers/Data/Application/AD90B554-3465-43DD-BAE2-04BC83F850A3/Documents/Bz75srG5nctDCnAWIspM.mp4
/private/var/mobile/Containers/Data/Application/AD90B554-3465-43DD-BAE2-04BC83F850A3/Documents/GWYgrgDVYaowxeGcOjzp.mp4
Since I've renamed the mp4 files using movie ID's (eg: GWYgrgDVYaowxeGcOjzp.mp4) my goal is to use this name to show which videos were downloaded and allow users to play the video. I'm able to do the name processing later on, but how am I able to get the downloaded mp4 files into a view like a VStack? I was thinking of looping through and adding the files into an array but wanted to check if there's a different way. Also, would be great if you could show me how to play a video using the path as the url. I've tried applying suggested methods but ended up with a "NSURLConnection finished with error - code -1002" error. Thank you!
I have implemented code as per the google SDK documentation line by line in my app, but still when I click on google sign in button app shifts to new view controller with webview with blank screen. Have tried multiple solution found here : GIDSignIn white screen on iOS 91. But no lucks with resolving the problem , have attached the screen shot for getting closer look about the screen.
Following are the pods that I'm using,
Running XCode 9.1, iOS 10.0 and later. Kindly request someone to help.
Update: View Hierarchy
Update: viewDidLoad's code:
GIDSignIn.sharedInstance().uiDelegate = self
if self.isChangePassword {
self.addSignInView()
}
else {
self.addSignUpView()
}
fileprivate func addSignInView() {
guard let signInEmailView: SignInEmailView = Bundle.main.loadNibNamed(NibNames.SignInEmailView.rawValue, owner: self, options: nil)?[0] as? SignInEmailView
else {
return
}
signInEmailView.delegate = self
gaManager.trackScreen(screenName: ScreenNames.SignIn.rawValue)
self.animateView(signInEmailView)
}
fileprivate func addSignInView() {
guard let signInEmailView: SignInEmailView = Bundle.main.loadNibNamed(NibNames.SignInEmailView.rawValue, owner: self, options: nil)?[0] as? SignInEmailView
else {
return
}
signInEmailView.delegate = self
gaManager.trackScreen(screenName: ScreenNames.SignIn.rawValue)
self.animateView(signInEmailView)
}
I have the same problem. I use the UIAlertView to confirm user really want to do authorization. It will show the blank screen. If I remove the UIAlertView and show the authorization view directly. It works fine.
The problem also show in the Dropbox authorization screen.
If you not use UIAlertView , please try to pass the top most controller
https://github.com/dropbox/dropbox-sdk-obj-c/issues/182
Hope this can do some help.
Finally after so many days found the problem. I was showing splash view from my appDelegate using refrence of UIWindow which was adding and removing an imgview as subview to the window. So it was somehow messing with the UINavigation's stack and my view controller was not getting any reference to the UINavigationController. After removing that code it's working just fine. Also came to the solution that, if I want to show splash screen, as I can't use UIWindow's reference, I have to add new VC and write my all navigation code there. #TedYu Thank you very much for the help. :)
I am trying to pass the instance of a created user onto to another view controller. The problem is the user that is passed over depends on type of user is selected. What I mean is I have created many sub-class of the main class User. So for example: Guest, VIP, Child etc and so when an instance is created on first page it is the sub class for that user that is created. I cannot get my head around how I pass the user to the second view controller without the second view controller user property being set to Type User. The problem is type User does not have all properties that sub classes have so in second page I am unable to access all properties that a sub class might have. This is example how I currently have it set:
First screen / view controller
var entrantData: People?
var entrantSelected: EntrantType = .none
#IBAction func generatePass(_ sender: UIButton) {
do{
switch entrantSelected {
case .freechildguest: entrantData = try Child(dateOfBirth: "\(dobTextField.text!)")
case .classicguest: entrantData = ClassicGuest()
case .maintenance: entrantData = try Maintenance(NameAddress(firstName: firstNameTextField.text, lastName: lastNameTextField.text, streetAddress: streetAddressTextField.text, city: cityTextField.text, state: stateTextField.text, zipCode: zipCodeTextField.text, entrantType: .maintenance))
default: break
}
} catch let error {
showAlert(title: "Error", message: "\(error)")
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destViewController = segue.destination as? TicketViewController {
destViewController.dataFromForm = entrantData
}
}
Second screen / view controller
class TicketViewController: UIViewController {
var dataFromForm: People?
So in second View controller I now have the user data in dataFromForm but I want it to be in its sub class so I can get its properties that are only divided in its sub class. E.g. maintenance user has firstname property that child and classicGuest do not.
I suppose I could create all properties that sub class use in the User super class but I feel that defeats the point creating sub classes that have their own unique properties.
One way to solve this issue is to keep the property of type People on the TicketViewController and when trying to access a property that only a certain subclass has, try conditional down casting the People instance to the appropriate subclasses.
Here's a basic example of how you can achieve this:
if let vip = dataFromForm as? VIP {
//access VIP properties
} else if let guest = dataFromForm as? Guest {
//access guest properties
}
Another thing you can do is down cast to the protocol itself. This may make it easier in certain situations when there are multiple subclasses conforming to the same protocol.
if let entrant = entrantData as? Nameable {
fullNameLabel.text = entrant.fullName
}
So the above code would not be executed on child or classicGuest since they do not conform to the Nameable protocol.
Say you construct an image that is fullscreen on different devices. You then use UIActivityViewController to post to - for example - Instagram in the normal way.
The user clicks your share button, it brings up the usual iOS-sharing-thingy,
and you can post to Instagram (assuming the user's an Instagram user of course). No worries.
But typically the image is cropped on Instagram - you lose a little of the top and bottom.
Is there actually any solution for this?
Note that indeed - say you open the normal Photos app on the iPhone, and "share" and post on Instagram ... you lose a little of the top and bottom!
When the user does click the Instagram icon on this ...
in fact is there a way for me then to go back, be aware of the user's choice, and make the image the appropriate size?
Is there perhaps a way to pass a selection of images (various sizes) to the UIActivityViewController?
What's the deal on this, it seems like a basic failing?
Note - I'm fully aware that BEFORE going to the iOS-share-thingy, I could ask the user myself "What size image would you like me to make?"
Note - I'm aware that it's in some cases possible to post "directly" to say Instagram inside the app, without using Apple's share system; that's lame though.
To save anyone typing, here's some clean code to bring up the iOS-share system...
#IBAction func userClickedOurShareButton()
{
let s:[AnyObject] = [buildImage()]
let ac = CleanerActivity(activityItems:s, applicationActivities:nil)
ac.popoverPresentationController?.sourceView = view
// needed so that iPads won't crash. sarcasm: thanks Apple
ac.excludedActivityTypes = [UIActivityType.assignToContact,
UIActivityType.saveToCameraRoll,
UIActivityType.addToReadingList,
UIActivityType.copyToPasteboard ]
// consider UIActivityTypeMessage also
if #available(iOS 9.0, *) {
ac.excludedActivityTypes?.append(UIActivityType.openInIBooks)
} else {
// Fallback on earlier versions
}
self.present(ac, animated:false, completion:nil)
}
class CleanerActivity: UIActivityViewController {
func _shouldExcludeActivityType(_ activity: UIActivity) -> Bool {
let activityTypesToExclude = [
"com.apple.reminders.RemindersEditorExtension",
"com.apple.mobilenotes.SharingExtension",
"com.google.Drive.ShareExtension",
"com.apple.mobileslideshow.StreamShareService"
]
if let actType = activity.activityType {
if activityTypesToExclude.contains(actType.rawValue) {
return true
}
else if super.excludedActivityTypes != nil {
return super.excludedActivityTypes!.contains(actType)
}
}
return false
}
Disclaimer: this solution involves hard-coding Instagram's extension identifier into your app, which may or may not make it through app review, and may break in the future. Try at your own risk!
Apple provides a mechanism for this called UIActivityItemProvider. Instead of passing an image to your UIActivityViewController, you can pass subclass of UIActivityItemProvider that overrides itemForActivityType to return an appropriate image based on the activity type chosen by the user.
Apple provides constants for many common activity types, but Instagram isn't yet included. You can identify Instagram by checking if the activity type's raw value is com.burbn.instagram.shareextension. This would break if Instagram changed the ID of their extension.
Here's an UIActivityItemProvider that provides different images to Instagram:
class DynamicImageProvider: UIActivityItemProvider {
let instagramImage: UIImage
let defaultImage: UIImage
init(instagramImage: UIImage, defaultImage: UIImage) {
self.instagramImage = instagramImage
self.defaultImage = defaultImage
super.init(placeholderItem: defaultImage)
}
override func activityViewController(_ activityViewController: UIActivityViewController,
itemForActivityType activityType: UIActivityType) -> Any? {
if activityType.rawValue == "com.burbn.instagram.shareextension" {
return instagramImage
}
else {
return defaultImage
}
}
}
Then change the first two lines of your IBAction:
let imageProvider = DynamicImageProvider(instagramImage:buildInstagramImage(), defaultImage:buildImage())
let ac = CleanerActivity(activityItems:[imageProvider], applicationActivities:nil)
My developer and I had previously tried to get interstitial adverts loading on iPhone and iPad, however only managed to get this working on iPad.
During our testing we discovered that interstitials weren't supported on iPhone, but since the release of iOS7 some people now say this is possible.
However I can't find any decent documentation on this. This Stack question has got me wondering again though iAd & Admob Interstitial Integration on iPhone
So, are full screen interstitials possible on iPhone using iAds?
I've also been waiting for interstitial ads for iPhone from iAd. I finally have it implemented into one of my apps and it is running and showing test ads just fine. The app is currently in review and I will update my answer once it is approved and I can test if any actual ads are being served. In the meantime, here is the code I used to implement iAd interstitials:
ViewController.h
#interface ViewController : UIViewController <ADInterstitialAdDelegate> {
ADInterstitialAd *interstitial;
BOOL requestingAd;
}
-(void)showFullScreenAd;
ViewController.m
-(void)viewDidLoad {
requestingAd = NO;
}
// Interstitial iAd
-(void)showFullScreenAd {
// Check if already requesting ad
if (requestingAd == NO) {
[ADInterstitialAd release];
interstitial = [[ADInterstitialAd alloc] init];
interstitial.delegate = self;
self.interstitialPresentationPolicy = ADInterstitialPresentationPolicyManual;
[self requestInterstitialAdPresentation];
NSLog(#"interstitialAdREQUEST");
requestingAd = YES;
}
}
-(void)interstitialAd:(ADInterstitialAd *)interstitialAd didFailWithError:(NSError *)error {
interstitial = nil;
[interstitialAd release];
[ADInterstitialAd release];
requestingAd = NO;
NSLog(#"interstitialAd didFailWithERROR");
NSLog(#"%#", error);
}
-(void)interstitialAdDidLoad:(ADInterstitialAd *)interstitialAd {
NSLog(#"interstitialAdDidLOAD");
if (interstitialAd != nil && interstitial != nil && requestingAd == YES) {
[interstitial presentFromViewController:self];
NSLog(#"interstitialAdDidPRESENT");
}
}
-(void)interstitialAdDidUnload:(ADInterstitialAd *)interstitialAd {
interstitial = nil;
[interstitialAd release];
[ADInterstitialAd release];
requestingAd = NO;
NSLog(#"interstitialAdDidUNLOAD");
}
-(void)interstitialAdActionDidFinish:(ADInterstitialAd *)interstitialAd {
interstitial = nil;
[interstitialAd release];
[ADInterstitialAd release];
requestingAd = NO;
NSLog(#"interstitialAdDidFINISH");
}
I just call -(void)showFullScreenAd after the user performs a certain action. For more information refer to UIViewController iAd Additions Reference
EDIT: 01/03/14
The app update was approved and has been live for 12 hours now. I still have not received any interstitial iAds as of this moment. It may be due to the lack of inventory for interstitial ads on iPhone or it may have something to do with the following message I've received in my iAd module on iTunes Connect. The message reads
When you submit your app, [app name], for approval, it will also be reviewed by iAd for use on the App Network to determine its appropriateness for receiving ads from iAd advertisers. Once your app is approved, you will be ready to start earning revenue for ads that run in your app.
I've never received this message before, I usually receive the "Your app is now eligible to receive ads" message as soon as the update is released in the App Store. It's either because of the new implementation of interstitial ads in my app or Apple has updated some of its iAd procedures.
Will update answer again if and when I do start receiving interstitial iAds. In the meantime you may test it yourself on my app +Quotes. The above code is invoked and an interstitial ad should show once a user shares via Facebook within the app.
EDIT: 01/07/14
Contacted iAd directly and received a response today
Hello Daniel,
Initial fill rates will reflect the recent launch of interstitials on iOS 7. Thank you for your patience as we ramp up ad serving.
If you haven't already, we recommend you integrate standard portrait and landscape iAd banners in your app to take advantage of all available types of advertising inventory.
Finally, for future reference, when you submit your app for approval, it will also be reviewed by iAd to determine its appropriateness for receiving ads from iAd advertisers. Therefore, it may take a few days for your new iAd enabled app to begin receiving ad impressions.
Best Regards,
iAd App Network Support
So, interstitial iAds for iPhone do work with iOS 7.0 and above but have a low fill rate currently.
My original answer is starting to age away so here's a newer Swift implementation:
This implementation uses a Manual ADInterstitialPresentationPolicy so we can present our interstitials at our own intervals. When manually presenting your interstitial it does not load with its own close button to dismiss itself. So, what I've done is created a UIView to present the interstitial in and used the interstitial's delegate methods to dismiss the UIView. The inconsistency with receiving an ad from the iAd network still arises when testing. Sometimes you receive an ad, sometimes it fails to load which allows us to request a new ad, and sometimes nothing happens at all. This just seems to be the nature of iAd's interstitials.
import UIKit
import iAd // Import iAd
class ViewController: UIViewController, ADInterstitialAdDelegate { // Include the delegate
var iAdInterstitial = ADInterstitialAd() // Our ad
var iAdInterstitialView = UIView() // View to present our ad in
var adLoaded = false // Bool to keep track if an ad is loaded or not
override func viewDidLoad() {
super.viewDidLoad()
setupAd()
}
func setupAd() {
// Set presentation to manual so we can choose when to present the interstitial
// Setting this will also fetch an interstitial ad for us
self.interstitialPresentationPolicy = ADInterstitialPresentationPolicy.Manual
iAdInterstitial.delegate = self // Set the delegate
// Make our view the same size as the view we will be presenting in
iAdInterstitialView.frame = self.view.bounds
}
func requestNewAd() {
// This will fetch an ad for us
ViewController.prepareInterstitialAds()
println("Requesting new ad")
}
#IBAction func presentAdButton(sender: AnyObject) {
if (adLoaded) {
// We have an ad that is loaded so lets present it
self.view.addSubview(iAdInterstitialView)
iAdInterstitial.presentInView(iAdInterstitialView)
}
else {
// No ad has been loaded
println("Ad not loaded")
}
}
func interstitialAdDidUnload(interstitialAd: ADInterstitialAd!) {
// Kinda works as expected
// Sometimes is called prematurely
// Sometimes takes minutes after ad is dismissed to be called
println("interstitialAdDidUnload")
// Get new ad
adLoaded = false
iAdInterstitialView.removeFromSuperview()
requestNewAd()
}
func interstitialAd(interstitialAd: ADInterstitialAd!, didFailWithError error: NSError!) {
// Failed to load ad so lets try again
println("didFailWithError: \(error)")
requestNewAd()
}
func interstitialAdWillLoad(interstitialAd: ADInterstitialAd!) {
// There is an ad and it has begun to download
println("interstitialAdWillLoad")
}
func interstitialAdDidLoad(interstitialAd: ADInterstitialAd!) {
// We got an ad
println("interstitialAdDidLoad")
adLoaded = true
}
func interstitialAdActionShouldBegin(interstitialAd: ADInterstitialAd!, willLeaveApplication willLeave: Bool) -> Bool {
println("interstitialAdActionShouldBegin")
return true;
}
func interstitialAdActionDidFinish(interstitialAd: ADInterstitialAd!) {
// Done with this ad. Lets get a new one
println("interstitialAdActionDidFinish")
iAdInterstitialView.removeFromSuperview()
adLoaded = false
requestNewAd()
}