In my project I am using MPMediaPickerController to pick a file from the device music library. I am using following piece of code for displaying the media picker.
MPMediaPickerController *mediaPicker = [[MPMediaPickerController alloc] initWithMediaTypes:MPMediaTypeMusic];
mediaPicker.delegate = self;
mediaPicker.prompt = #"Select a personal message";
[self presentViewController:mediaPicker animated:NO completion:nil];
Everything is working fine,but the MediaPickerController is taking a couple of seconds (2 to 3 sec) for showing the music library. Is there any way to reduce this loading time of MPMediaPickerController. This delay after clicking the upload button is realy a bad user experience.
There's nothing you can do. If there is a lot of music, it takes time to survey all of it and prepare the controller, and that's all there is to it. This is no different from the delay the first time the user tries to use the Music app. You might be able to reduce the amount of material shown by turning off showsCloudItems, but even that might not help.
The best you can do is probably to try to cover the delay psychologically, i.e. by giving the user something to see, such as a spinning activity indicator, until everything is in place. I have not tried this with a MPMediaPickerController, however (I've done it with my own home-built music library exploration interface, which has the same delay issues).
I noticed my MediaPickerController was very slow as well (in my current project, using Swift 2.2), even though it was pretty quick earlier in the project (and most of what I have added since has been networking code).
In my code, I was instantiating the MPMediaPickerController only when the user tapped my "Find a song" button. By creating the instance of MPMediaPickerController at the time of the main view loading (I placed it in my class declaration, outside of viewDidLoad), I was (somehow) able to bring that load time back down to less than a second (whereas it sometimes didn't even show up, when I instantiated the MPMediaPickerController at the last possible second).
TLDR: write this:
import UIKit
import MediaPlayer
import MobileCoreServices
class SomeViewController: UIViewController, MPMediaPickerControllerDelegate {
var mediaPickerController = MPMediaPickerController(mediaTypes: .AnyAudio)
func viewDidLoad() {
mediaPickerController.delegate = self
mediaPickerController.prompt = "Select a song that you like"
}
#IBAction func buttonWasTapped(sender: AnyObject) {
self.presentViewController(mediaPickerController, animated: true, completion: nil)
}
}
Instead of this: (notice how I only instantiate mediaPickerController once my button is tapped.
import UIKit
import MediaPlayer
import MobileCoreServices
class SomeViewController: UIViewController, MPMediaPickerControllerDelegate {
func viewDidLoad() {
}
#IBAction func buttonWasTapped(sender: AnyObject) {
var mediaPickerController = MPMediaPickerController(mediaTypes: .AnyAudio)
mediaPickerController.delegate = self
mediaPickerController.prompt = "Select a song that you like"
self.presentViewController(mediaPickerController, animated: true, completion: nil)
}
}
As matt suggested, a spinning activity indicator can really help the user experience as it reassures the user that it's working and it hasn't crashed. I used MBProgressHUD for this when loading a track from the music library.
Related
Here is a little problem I just noticed in one of my iOS apps.
I use Xcode Version 10.1 and Swift 4.2.
The app has a button which when pushed brings up a view controller, this VC is in charge of opening a link to the app itself in itunes. I have done this many times with no problems in the past.
But this time, a blank pages opens up and nothing else. I have tried to replace only the URL I am interested in by "https://www.google.com/" and it works perfectly as expected (i.e. the Google page shows up). Of course I have verified that my URL is correct.
Can anybody see what could be the issue?
Thanks in advance for any relevant tip.
Here is the code for the whole view controller.
import UIKit
import WebKit
class appStore_ViewController: UIViewController, WKNavigationDelegate {
let appDelegate:AppDelegate = UIApplication.shared.delegate as! AppDelegate
var webView: WKWebView!
override func loadView() {
webView = WKWebView()
webView.navigationDelegate = self
view = webView
}
override func viewDidLoad() {
super.viewDidLoad()
let appStoreURL = URL(string: "https://itunes.apple.com/app/id\ (appDelegate.applicationID)?mt=8")
//let appStoreURL = URL(string: "https://www.google.com/") // This works as expected.
print("The link: \(appStoreURL!.absoluteString)") // This shows what is expected (a working URL).
webView.load(URLRequest(url: appStoreURL!))
}
}
You should see what happen while visiting the AppStore Url with safari browser in your iPhone. then you will find the it still show blank page but show an alert to open the Appstore.
If you want to do the same function in your app with webView. you have to handle the alert the by yourself.
You need to implement the decidePolicyForNavigationAction method of WKNavigationDelegate for this to work.
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)
(WKNavigationActionPolicy))decisionHandler {
/* Code to handle other schemes such as file, https, http, etc. if required
*/
if ([[[navigationAction.request URL] scheme] isEqual:#"itms-appss"])
{
[[UIApplication sharedApplication] openURL:[navigationAction.request URL]];
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
}
WKWebview does not inherently support different schemes such as "itms-appss" and you need to check and implement the url scheme you want to support.
You also need to check if you are running in iPadOS and set WKWebpagePreference to use mobile content mode if you do so.
I have a tableView that utilizes the UIActivityViewController so users can share content on other 3rd party networks Facebook, twitter, text message etc. I have a function called IncreaseShareByOne() and it's purpose is to count the number of times that something has been shared . My problem is that right now that function fires of every time the UIActivityViewController is clicked . Is there someway that I can find out if a user really shared something so that I can use that function correctly ? becomes sometimes you open the UIActivityViewController and decide not to share anything so I want to catch and not use that function. I am new to swift and am using version 3 .
func sharedShareAction(controller: UIViewController, sender: UIButton) {
controller.present(activityViewController,animated: true,completion: nil)
IncreaseShareByOne()
}
You can add a completion handler to your UIActivityViewController. In the completion handler, check whether the user submitted using the completed value. You'll probably want to do something like this:
func sharedShareAction(controller: UIViewController, sender: UIButton) {
controller.present(activityViewController,animated: true, completion: nil)
activityViewController.completionWithItemsHandler = { activity, completed, items, error in
if !completed {
// handle task not completed
return
}
IncreaseShareByOne()
}
}
Check the API docs for more info.
I am trying to port my apps to iOS 10, including the visualization of a MPMediaPickerController by means of the following code:
#IBAction func handleBrowserTapped(_ sender: AnyObject){
let pickerController = MPMediaPickerController(mediaTypes: .music)
pickerController.prompt = NSLocalizedString("Add pieces to queue", comment:"");
pickerController.allowsPickingMultipleItems=true;
pickerController.delegate=MPMusicPlayerControllerSingleton.sharedController();
self.present(pickerController, animated:true, completion:{
MPMusicPlayerControllerSingleton.sharedController().storeQueue()
})
}
Yet all that appears on the screen is a full white screen with no back buttons or other, differently from the previous iOS versions. The block is called and so the picker's presentation seems to succeed. What could be the problem?
Add Key-value to Plist :
<key>NSAppleMusicUsageDescription</key>
<string>$(app Name) uses music</string>
The issue was fixed by the latest beta now asking for an authorisation to access the iTunes library.
I'm trying to play an alarm sound, but when I've implemented the code, it runs, but no sound is played. What is the problem?
Here is my code (the important bits):
import UIKit
//Timer Sound
let timerSoundURL = NSBundle.mainBundle().URLForResource("alarm", withExtension: "caf")
var timerSoundID: SystemSoundID = 0
override func viewDidLoad() {
//Setup sound for timer
AudioServicesCreateSystemSoundID(timerSoundURL, &timerSoundID)
}
//Plays sound
override func viewDidAppear(animated: Bool) {
AudioServicesPlaySystemSound(timerSoundID);
NSLog("Play sound")
}
Your code looks fine, but you are probably testing it in the Simulator. If so, that's your mistake. AudioServicesPlaySystemSound doesn't work in the Simulator.
Run your code on an actual device and all will be well (except that you've got a memory leak, but that's another matter entirely - the point is, you'll hear the sound, if the resource is valid, when you run on the device).
I want to add google places autocomplete to xcode with swift, so users can search on a city and press enter, so should the app show that city on the map.
I´m using google maps, so it has to be connected to that map and the search bar would i like to have in the navi-bar (just above the map)
Does anyone know a good tutorial to do that??
For Swift 3:
1- Select your podfile and type : pod 'GooglePlaces'
2- In the appDelegate, add your API Key :
GMSPlacesClient.provideAPIKey("YOUR KEY") (Import the GooglePlaces)
3- Use this code in your viewController that contains the googleMap:
// This code snippet demonstrates adding a
// full-screen Autocomplete UI control
import UIKit
import GooglePlaces
class ViewController: UIViewController {
// TODO: Add a button to Main.storyboard to invoke onLaunchClicked.
// Present the Autocomplete view controller when the button is pressed.
#IBAction func onLaunchClicked(sender: UIButton) {
let acController = GMSAutocompleteViewController()
acController.delegate = self
present(acController, animated: true, completion: nil)
}
}
extension ViewController: GMSAutocompleteViewControllerDelegate {
// Handle the user's selection.
func viewController(_ viewController: GMSAutocompleteViewController, didAutocompleteWith place: GMSPlace) {
print("Place name: \(place.name)")
print("Place address: \(place.formattedAddress)")
print("Place attributions: \(place.attributions)")
dismiss(animated: true, completion: nil)
}
func viewController(_ viewController: GMSAutocompleteViewController, didFailAutocompleteWithError error: Error) {
// TODO: handle the error.
print("Error: \(error)")
dismiss(animated: true, completion: nil)
}
// User cancelled the operation.
func wasCancelled(_ viewController: GMSAutocompleteViewController) {
print("Autocomplete was cancelled.")
dismiss(animated: true, completion: nil)
}
}
Not exactly tutorials, but there are a few resources on Github, with people providing libraries and code samples to achieve what you're asking for.
SPGooglePlacesAutocomplete (https://github.com/spoletto/SPGooglePlacesAutocomplete) is very popular and has many features, but it's written in Objective-C
iOS Google Places Autocomplete (https://github.com/watsonbox/ios_google_places_autocomplete) is more recent, written in Swift, and also contains some examples.
lots of others...
Even without proper tutorials, you can still check out these libraries and understand how their code works to get some inspiration if you want to write your own components.
As a sidetone, Google also has this page, but it's not a dedicated tutorial for iOS apps, just some useful explanations of how their API works: https://developers.google.com/places/documentation/autocomplete#examples
You can try one for wrapper to implement Autocompletion for Place API with Google:
https://github.com/mrugrajsinh/MVAutocompletePlaceSearchTextField
Its very simple drop-in control and subclass of UITextField so using by binding Class with simple UITextField you can achive Auto completion dropdown similar as Uber and many popular app does.
Here's a tutorial I came across which is based on my ios_google_places_autocomplete code.
#Frederik: If you've had a problem with the library, please create an issue describing it.
please check this one 110% work.
http://sweettutos.com/2015/09/30/how-to-use-the-google-places-autocomplete-api-with-google-maps-sdk-on-ios/
Use this latest repo. with swift 2.0
Just download zip file of project and open pod file and write pod 'GoogleMaps' and save it open terminal and install pod.
Enjoy!!!
RKAutoCompletePlaceSearch
Since the question was asked, Google has added UI elements to the iOS SDK for this sort of workflow. Check out the documentation.
Simple and lightweight solution for Swift users !
I also created a library to make these simple request without including any framework of third party library. You can also maintain cache for Autocomplete with the library.
To use to library follow these steps : -
step-1 Import GoogleApiHelper into your project.
step-2 Initialise GoogleApiHelper
GoogleApi.shared.initialiseWithKey("API_KEY")
step-3 Call the methods
var input = GInput()
input.keyword = "San francisco"
GoogleApi.shared.callApi(input: input) { (response) in
if let results = response.data as? [GApiResponse.Autocomplete], response.isValidFor(.autocomplete) {
//Enjoy the Autocomplete Api
} else { print(response.error ?? "ERROR") }
}
You can find the library here