I attributed the tag "tokyo" to my .mp4 video, and set it as installed during the app installation.
Originally, I was using a path to load it from my resources, however, now it's different because it's located in the Asset catalog.
After reading the documentation, I tried something like:
NSBundleResourceRequest(tags: ["tokyo"]).beginAccessingResourcesWithCompletionHandler { (error) -> Void in
let tokyoVideo = NSDataAsset(name: "tokyo")
}
To access this video as NSData I could use:
tokyoVideo.data
However, I'm using AVPlayer which takes the parameter as an NSURL, not NSData.
So how do I get the NSURL for my video?
Is the Asset catalog only for storing Data and should I be using that to store my video, or is there a better alternative?
The problem is putting the mp4 in the asset catalogue. Resources don't have to be in the asset catalogue to be accessed as on demand resources.
Move your assets out of the catalogue in to the workspace and tag them then use the bundle property of the NSBundleResourceRequest
import UIKit
class ViewController: UIViewController {
var bundleRequest = NSBundleResourceRequest(tags: [])
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let tags: Set<String> = ["odr"]
bundleRequest = NSBundleResourceRequest(tags: tags)
bundleRequest.beginAccessingResourcesWithCompletionHandler { (error:NSError?) -> Void in
if let e = error {
print(e)
return
}
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
if let url = self.bundleRequest.bundle.URLForResource("tokyo", withExtension: "mp4") {
//use the url to play the video with avplayer
}
})
}
}
}
Sure it can the movie will end up getting stored in a data file.
NSDataAsset
I think its possible to use Asset Catalog for video stuff, Its simplify management of images. Use NSDataAsset for it. Review the last row in below table.
Refer this link for more info
The following table lists the types of resources that can be tagged as on-demand resources.
Related
I am using Swift 4 and I am wondering how having a reference to a ViewController in AppDelegate works. I have two questions which I have put in bold. I understand that AppDelegate is a delegate that has functions that get called when the app becomes foreground or background, or even when the user does the "open with" event on a file extension that my app is registered to handle and selects to open that file with my app- AppDelegate lets the app know that took place. 1) But what I don't understand is how AppDelegate should communicate with my Views to tell them that these events happened. I am wondering what the good design pattern is for doing so. My solution is to have a reference to a viewController so here is an example:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var hotSpotRISViewController = HotSpotRISViewController()
...
func application(_ app: UIApplication, open url: URL,
options: [UIApplicationOpenURLOptionsKey : Any]) -> Bool {
hotSpotRISViewController.setURL(theURL: url)
return true
}
}
What I don't understand is how this actually works. I thought that AppDelegate looks at Main.storyboard and starts that and that Main.storyboard has it's own reference to HotSpotRISViewController(). 2) How is it that by making a reference to HotSpotRISViewController() in the AppDelegate, that it uses this reference instead?
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
}
I start project in Swift Language. Apps almost done. Single ViewController logics are all done. But I need to communicate with each other ViewController.
I want to pass some value from one ViewController to another ViewController. I'm using StoryBoard. I want to pass value using prepareSeague function as like Objective-C has. Is there any way to do this without using delegate-way.
In the first view controller handle prepareForSegue method and provide additional values to the second view controller, like:
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if segue.identifier == "someidentifier" {
let vc = segue.destinationViewController as MySecondViewController
// vc.someProperty = someValue
}
}
I have a huge message file which i need to split into multiples files for different languages.
For example :
I created one folder for English locale i.e. en and another for French locale , fr inside conf folder.
en contains messages1_en.properties and messages2_en.properties
fr contains messages1_fr.properties and messages2_fr.properties
How to access these properties files inside my view.
Thanks
The only way to do that without introducing your own alternative implementation and use that instead of the built in Messages is to use hacked locales, so you would do fr_type1, fr_type2 or something like that to select the right alternative.
This is probably a bad idea since it's always risky to use an API in a different way from how it was intended to be used, there is a high risk of unexpected behaviour and it might be brittle since there is no guarantee that you will be able to use made up locales in future versions etc.
If you look at the Messages implementation you could probably get some ideas of how to implement your own without much fuss.
Good luck!
That's an old question, but i had a close issue, and i didn't find a solution anywhere.
This example use a configuration key to load messages from a file with a custom name. But you can easily modify it to load messages file from a subdirectory and/or multiple messages files.
Override play.api.i18n.DefaultMessagesApiProvider
#Singleton
class CustomMessagesApiProvider #Inject() (
environment: Environment,
config: Configuration,
langs: Langs,
httpConfiguration: HttpConfiguration)
extends DefaultMessagesApiProvider(environment, config, langs, httpConfiguration) {
def filename =
config.get[String]("play.i18n.filename")
override protected def loadAllMessages: Map[String, Map[String, String]] = {
langs.availables.map(_.code).map { lang =>
(lang, loadMessages(filename +"." + lang))
}.toMap
.+("default" -> loadMessages(filename))
.+("default.play" -> loadMessages(filename+".default"))
}
}
Add Guice binding in Module.java
#Override
public void configure() {
bind(DefaultMessagesApiProvider.class).to(CustomMessagesApiProvider.class);
}
It's my first Scala class, so maybe it can be improved. But it works.
To load multiple files (it compiles but not tested)
override protected def loadAllMessages: Map[String, Map[String, String]] = {
langs.availables.map(_.code).map { lang =>
(lang,
loadMessageFiles("." + lang))
}.toMap
.+("default" -> loadMessageFiles(""))
.+("default.play" -> loadMessageFiles(".default"))
}
private def loadMessageFiles(suffix: String) = {
loadMessages("messages-1" + suffix) ++ loadMessages("messages-2" + suffix)
}
The MediaLibraryExtensions.GetPathFromToken has 2 parameters (MediaLibrary library, string token) as input. I assume the API returns path of specified media item from media library, The token is associated with the media of interest. However, how do I find out the "token" of the media, say a music file in media library? Could please show me how to figure out the "token" from a given Song? Thanks in advance.
The value of Token is supplied to an application on a query string when that application is registered to extend various parts of the Windows Phone OS, this includes Photo Share Picker, Photo Edit Picker and Auto Launch from a File Association
All the examples use GetPictureFromToken, but you can imagine the same scenario with other media types being 'Launched' via file association.
Here's a sample of how to use token with GetPicturesFromToken
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// Get a dictionary of query string keys and values.
IDictionary<string, string> queryStrings = this.NavigationContext.QueryString;
// Ensure that there is at least one key in the query string, and check whether the "token" key is present.
if (queryStrings.ContainsKey("token"))
{
// Retrieve the photo from the media library using the token passed to the app.
MediaLibrary library = new MediaLibrary();
Picture photoFromLibrary = library.GetPictureFromToken(queryStrings["token"]);
// Create a BitmapImage object and add set it as the image control source.
BitmapImage bitmapFromPhoto = new BitmapImage();
bitmapFromPhoto.SetSource(photoFromLibrary.GetImage());
image1.Source = bitmapFromPhoto;
}
}
GetPathFromToken should behave in the same way.