Swift framework can't get file in another bundle - ios

I'm up-skilling on swift. I'm writing a framework that will depend on a file that will not be part of the framework. It will be created by the app that imports the framework.
It works fine when running on the simulator but the live rendering in interface builder craps out because it can't find the file. I've done the same thing previously in Objective-c and I know the solution is that the interface builder is using a different bundle. The solution was to use:
[[NSBundle bundleForClass:[self class]] pathForResource:<fileName> ofType:<fileType>]
I've searched online and I believe the equivalent in swift is:
let path:String? = NSBundle(forClass: self.dynamicType).pathForResource(<fileName>, ofType: <fileType>)
however it always returns nil inside the live rendering. While:
let path:String? = NSBundle.mainBundle().pathForResource(<filename>, ofType: <fileType>)
works fine in the simulator, meaning the file is clearly there and part of the finished app. Anyone have any idea why this might be? is there a setting somewhere i'm missing also?

In Swift the code looks like this:
return NSBundle.init(forClass: <ClassName>.self).pathForResource(<FileName>, ofType: <FileType>)
for example, to get localization resources in Arabic from another bundle your code would look like this:
return NSBundle.init(forClass: <ClassName>.self).pathForResource("ar", ofType: "lproj")
I think part of your problem might be that you are trying to hit another bundle but you are accessing the bundle for the current class with your call to [[NSBundle bundleForClass:[self class]].
I haven't written much objective-C but I suspect you will be able to translate this on my behalf.

Related

React Native Module, Cocoapod file not found

I am building a module for React Native, as a part of this, there is some native iOS code that is wrapped in a cocoapod. I have this working fine, and I can install the cocoapod and see the native classes from the RN side no problem. One of the native classes is trying to get the path to a local mp3 file inside a sub folder proj/Audio/file.mp3. Using the following ObjC code: NSString *path = [[NSBundle mainBundle] pathForResource:#"file" ofType:#"mp3" inDirectory:#"Audio"];
This is returning nil and as such causing an error when trying to get the NSURL for the file. I have the mp3 extension added to the podspec # s.source_files = "ios/**/*.{h,m,swift,mp3}" so it is moving the file over. However, I assume I have to be missing something as it ultimately cannot find the file.
I have gone into the source xcode project and added the mp3 file to the Copy files phase in build phases. I have also made sure that the file was linked to the target. I am not sure what else I could be missing at this point for it to not be able to be found.
Instead of putting the mp3 file in source_files of your podspec, try using resource_bundles; see the documentation here. Basically it lets you define resource bundle files that CocoaPods creates for you with the assets that you specify, for example:
s.resource_bundles = {
'Audio' => ['ios/**/*.mp3']
}
You can load the bundle file resource that CocoaPods created (create a NSBundle object from its URL by its name - Audio in the above example, and extension - bundle), then get a path from resources inside this bundle (the same method that you used on the mainBundle).
I know this is an old post, but I was struggling with this myself. I completely agree with Artal, to sum up you need to
let bundlePath = Bundle.main.path(forResource: "Audio", ofType: "bundle");
let bundle = Bundle(path: bundlePath!)
maybe guard your the path,

Accessing a Sound-File via NSBundle - pathForResource

So I'm just trying to get into iOS Programming by going through some Online-Video-Courses. The problem is, that those are not up-to-date with Swift 3.
In the project I am at the moment it is required to import a Sound-File via the NSBundle-Framework using the following:
let path = NSBundle.mainBundle().pathForResource(name, ofType:)
The problem is, that I won't get this running in Swift 3 and I'm not able to get the right pieces off the Apple Documentation. So my Code looks the following:
import AVFoundation
import Foundation //don't know if this is right by 100 per cent
let path = NSBundle.mainBundle().pathForResource("btn", ofType: "wav")
But it seems like It doesn't even know the Class NSBundle, because Auto-Completion isn't even offering me any functions of NSBundle. I can't seem to find the right pieces which changed in Swift 3 to get this thing working. Anybody here who's able to help me with this?
I believe this is the ticket:
let path = Bundle.main.path(forResource: "btn", ofType: "wav")

Using reopened standard file descriptors in an iOS app with background capabilities?

I would like to be able to redirect my logging statements to a file so that I can retrieve them when my app runs standalone (i.e. is not attached to Xcode). I have discovered (thank you Stackoverflow) that freopen can be used to accomplish this.
If I create a new Xcode project and add the code to redirect stderr then everything works as expected.
However, when I add the redirection code to my existing, bluetooth project I am having trouble. The file is being created and I can retrieve it using iTunes or Xcode's Devices window, but it is of size 0. If I explicitly close the file then the text that I wrote actually makes it into the file. It is as though iOS is not flushing the file when the app is terminated. I suspect that the trouble stems from the fact that I have enabled background processing. Can anyone help me to understand this?
Here is my code:
let pathes = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true);
let filePath = NSURL(fileURLWithPath: pathes[0]).URLByAppendingPathComponent("Test.log")
freopen(filePath.path!, "a", stderr);
fputs("Hello, Samantha!\r\n", stderr);
struct StderrOutputStream: OutputStreamType {
static let stream = StderrOutputStream()
func write(string: String) {fputs(string, stderr)}
}
var errStream = StderrOutputStream.stream
print("Hello, Robert", toStream: &errStream)
fclose(stderr) // Without this the text does not make it into the file.
I'd leave this as a comment, but have you looked into NSFileHandle? It sounds like you just need a way to append data to the end of a text file, correct?
Once you have a handle with something like NSFileHandle(forWritingToURL:), you can use .seekToEndOfFile() and .writeData(_:). As a side note, you'll need to convert your String to Data before writing it.
Admittedly, this will probably end up being more lines of code, and you'll almost certainly need to take threading into consideration.

App resources not available when UI testing in Xcode 7

I'm trying to extend the new UI testing functionality in Xcode 7 by snapshotting the current screen elements (labels, images, buttons) and saving their accessibility information to json files.
The idea is that when running the UI tests later, a current screen snapshot can be taken and compared to the existing one, the test will fail if additional or missing elements are found.
Unfortunately the app resources don't seem available during UI testing, even with the correct target, so the json files can't be loaded for comparison. The following standard code fails to load a resource:
guard let resourcePath = NSBundle.mainBundle ().pathForResource ("StartScreenShapshot", ofType:"json") else {
XCTFail ("can't load resource StartScreenShapshot")
return
}
I can understand why Apple have taken this sandbox approach, as UI testing should be based on what's happening on the screen, and access to the workings of app shouldn't be needed, but not having access to the resource bundle is a pain.
So is there a way to load local resources from the app, or some other way locally, during Xcode 7 UI testing?
Saving the files locally (automatically) would also be a huge plus, would save creating them manually.
Thanks to #sage444
For unit testing the mainBundle() method doesn't work for retrieving a resource path, using a class does.
guard let resourcePath = NSBundle (forClass: self.dynamicType).pathForResource (contentName, ofType:"json") else {
XCTFail ("can't load resource \(contentName)")
return
}
Thanks #danfordham
Updated for Swift 3
1) Copy bundle resources
2) Reference new bundle this way,
guard let path = Bundle(for: type(of: self)).path(forResource: contentName, ofType: "json") else {
XCTFail ("can't load resource \(contentName)")
return
}

URLForResource:withExtension: method always returns nil

I am testing the MixerHost sample code. However the following code:
NSURL *beatsLoop = [[NSBundle mainBundle] URLForResource: #"beatsMono"
withExtension: #"caf"];
the beatsLoop is nil.
What's the reason for that?
Should I first create the beatsMono.caf file and then put into some specific path?
Any comments and solutions will be highly appreciated.
Thanks,
finspoo
Should I first create the beatsMono.caf file and then put into some specific path?
Yes. The file beatsMono.caf (case sensitive!) must exist in your application bundle for that method to succeed. This is done by adding the file to the target as a resource in XCode, you cannot do it at runtime.

Resources