recently I created production scheme for my app, after that, the Xcode doesn't show anything whenever I use print and it just shows in console when I use NSLog. It happens both on development scheme and production scheme.
What is this issue come from?
for example
#if Production
guard let filePath = Bundle.main.path(forResource: "GoogleService-Info-PROD", ofType: "plist") else { return }
if let options = FirebaseOptions.init(contentsOfFile: filePath) {
FirebaseApp.configure(options: options)
}
print("[FIREBASE] Production mode.")
NSLog("[FIREBASE] Production mode.")
#elseif Development
guard let filePath = Bundle.main.path(forResource: "GoogleService-Info-DEV", ofType: "plist") else { return }
if let options = FirebaseOptions.init(contentsOfFile: filePath) {
FirebaseApp.configure(options: options)
}
print("FIREBASE - Development mode.")
NSLog("FIREBASE - Development mode.")
#endif
FirebaseConfiguration.shared.setLoggerLevel(.min)
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(options: authOptions) { _, _ in }
application.registerForRemoteNotifications()
Messaging.messaging().delegate = self
here the first NSLog will print something in console, not print(). I don't know what I changed to make it like that, could anyone give me a hint?
Thanks
Related
I've noticed that my NSLog (and I've also tried it with os_log) statements are not showing up consistently in the console application.
Here's some code that runs when my app starts up.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
NSLog("xyz didFinishLaunchingWithOptions")
FirebaseApp.configure()
NSLog("xyz FirebaseApp.configure() done")
let db = FirestoreDelegate.db()
let now = Date()
NSLog("xyz about to write")
db.collection("atest").document(DateUtils.formatTimestampGMT(now)).setData(["ts": now, "note":"delegate startup"]) {
err in
if let err = err {
NSLog ("xyz error ats \(err)")
return
}
NSLog("xyz wrote to ats \(DateUtils.formatTimestampGMT(now))")
}
NSLog("xyz after write")
... extraneous code removed
}
When I run, sometimes I see "xyz didFinishLaunchingWithOptions" and "wrote to ats", but none of the other log statements. Sometimes I see them all, but it's pretty inconsistent. Are they getting filtered or optimized out somehow?
I'm not debugging through xcode, I'm just running the app on my phone and viewing the logs through the console app on my computer.
I didn't figure out why the logging is inconsistent. Instead I created a custom logger that writes to a file.
public class FileWriter {
static func getTs() -> String {
let timestampFormat = DateFormatter()
timestampFormat.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
return timestampFormat.string(from: Date())
}
static func write(_ text: String) {
do {
let dir: URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last! as URL
let url = dir.appendingPathComponent("log.txt")
if !FileManager.default.fileExists(atPath: url.path) {
FileManager.default.createFile(atPath: url.path, contents: nil, attributes: nil)
}
let fileHandle = try FileHandle(forWritingTo: url)
let line = "\(getTs()) \(text)\n"
let data = line.data(using: String.Encoding.utf8)!
fileHandle.seekToEndOfFile()
fileHandle.write(data)
fileHandle.closeFile()
} catch let error as NSError {
print ("error \(error)")
}
}
}
To read the file, I added the following keys to my Info.plist "UIFileSharingEnabled"
, "LSSupportsOpeningDocumentsInPlace" and then I could open the file on my phone with the Files app.
I'm trying to share file originally generated in watch App Extension but it's not working. I am using iOS 11.3 and Watch 4.3. I am also using Simulator.
I have done like this
Enable App domain in Main app and Watch App Extension.
App domain in selected in both with identifier.
REF : https://www.techotopia.com/index.php/Sharing_Data_Between_a_WatchKit_App_and_the_Containing_iOS_App
Code added:
In Watch App Extension:
do {
let fileManager = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: AppDomain)
guard let url = fileManager?.appendingPathComponent("TabCareLogs.txt") else { return }
try SOME_STRING.appendLineToURL(fileURL: url)
print("WatchKit: FILE PATH \(url.path)")
let result = try String(contentsOf: url, encoding: .utf8)
debugPrint("############# FILE: \(result) #############")
} catch let error {
print("Could not write to file : \(error.localizedDescription)")
}
extension String {
func appendLineToURL(fileURL: URL) throws {
try (self + "\n").appendToURL(fileURL: fileURL)
}
func appendToURL(fileURL: URL) throws {
let data = self.data(using: .utf8)!
try data.append(fileURL: fileURL)
}
}
extension Data {
func append(fileURL: URL) throws {
if let fileHandle = FileHandle(forWritingAtPath: fileURL.path) {
defer {
fileHandle.closeFile()
}
fileHandle.seekToEndOfFile()
fileHandle.write(self)
}
else {
try write(to: fileURL, options: .atomic)
}
}
}
WatchKit: FILE PATH
/Users/abhishek/Library/Developer/CoreSimulator/Devices/D515C513-3975-4C8F-B07D-6A0CCCD1A8EC/data/Containers/Shared/AppGroup/90DC2A1A-61D6-440B-A499-9EA608CE0C2E/TabCareLogs.txt
I'm getting file as well as its content.
In Main App:
let fileManager = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: AppDomain)
guard let url = fileManager?.appendingPathComponent("TabCareLogs.txt") else { return nil }
print("FILE PATH \(url.path)")
print("FILE PATH ABSOLUTE \(url.absoluteString)")
let exists = FileManager.default.fileExists(atPath: url.path)
print("FILE EXIST : \(exists)")
FILE PATH
/Users/abhishek/Library/Developer/CoreSimulator/Devices/D5CED7C4-B674-4BF7-A72C-C063F733F4E7/data/Containers/Shared/AppGroup/77C1EAC2-2A86-4763-973F-33929C909619/TabCareLogs.txt
FILE PATH ABSOLUTE
file:///Users/abhishek/Library/Developer/CoreSimulator/Devices/D5CED7C4-B674-4BF7-A72C-C063F733F4E7/data/Containers/Shared/AppGroup/77C1EAC2-2A86-4763-973F-33929C909619/TabCareLogs.txt
FILE EXIST : false
I have tried to print the path I'm getting path bit if I'm checking file exist then its is showing false.
Same issue : NSFileManager.defaultManager().fileExistsAtPath returns false instead of true
Also the paths are different I don't know why it is going to different path after using shared container?
When I was attempting to troubleshoot an issue with me sqlite file I realized that in my AppDelegate had an error.
let url = self.applicationDocumentsDirectory.appendingPathComponent("SingleViewCoreData.sqlite")
I want change the file name to match the app name but I don't want to lose the current data in the SingleViewCoreData.sqlite file. How can I achieve this?
This how I was able to solve the issue also this is all Swift 3.1
var pURL: URL?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
checkForOldStore()
return true
}
Then I edited the persistentStoreCoordinator section.
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
// The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
// Create the coordinator and store
let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
// let url = self.applicationDocumentsDirectory.appendingPathComponent("SingleViewCoreData.sqlite")
let url = self.pURL // ADDED THIS CODE WHICH REPLACED CODE FROM ABOVE.
var failureReason = "There was an error creating or loading the application's saved data."
do {
try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: [NSMigratePersistentStoresAutomaticallyOption: true,
NSInferMappingModelAutomaticallyOption: true])
} catch {
With the following code I first check if the old sqlite file exists with the checkForOldStore(). Note that I set the pURL to equal what the old setting was on the persistentStoreCoordinator if the file exists before calling the migrateStore(). And because the checkForOldStore() still runs every time the app starts and now that the file doesn't exists I set the pURL to the new file name.
func checkForOldStore() {
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let url = NSURL(fileURLWithPath: path)
let filePath = url.appendingPathComponent("SingleViewCoreData.sqlite")?.path
let fileManager = FileManager.default
if fileManager.fileExists(atPath: filePath!) {
print("FILE AVAILABLE")
pURL = self.applicationDocumentsDirectory.appendingPathComponent("SingleViewCoreData.sqlite")
migrateStore()
} else {
pURL = self.applicationDocumentsDirectory.appendingPathComponent("NewName.sqlite")
print("FILE NOT AVAILABLE")
}
}
At the end of the migrateStore() I call the remvoeOldDB for each of the old sqlite files.
func migrateStore() {
// migrate current store from one URL to another
// write out the current store URL before the migration
var storeURL: URL? = persistentStoreCoordinator.persistentStores.last?.url
print("Current Store URL (before migration): \(String(describing: storeURL?.description))")
// grab the current store
let currentStore: NSPersistentStore? = persistentStoreCoordinator.persistentStores.last
// create a new URL
let newStoreURL: URL? = applicationDocumentsDirectory.appendingPathComponent("NewName.sqlite")
// setup new options dictionary if necessary
// migrate current store to new URL
_ = try? persistentStoreCoordinator.migratePersistentStore(currentStore!, to: newStoreURL!, options: nil, withType: NSSQLiteStoreType)
// and to check we're on the new store, write out tha URL again
storeURL = persistentStoreCoordinator.persistentStores.last?.url
print("Current Store URL (after migration): \(String(describing: storeURL?.description))")
removeOldDB(itemName: "SingleViewCoreData", fileExtension: "sqlite")
removeOldDB(itemName: "SingleViewCoreData", fileExtension: "sqlite-shm")
removeOldDB(itemName: "SingleViewCoreData", fileExtension: "sqlite-wal")
}
func removeOldDB(itemName:String, fileExtension: String) {
let fileManager = FileManager.default
let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
guard let dirPath = paths.first else {
return
}
let filePath = "\(dirPath)/\(itemName).\(fileExtension)"
do {
try fileManager.removeItem(atPath: filePath)
} catch let error as NSError {
print(error.debugDescription)
}
}
I want to cast device local video to Chromecast using PhotoKit framework but only loading screen is displayed on Chromecast and no video is played. If replace avUrlAsset.url.absoluteString with http_url_of_video than it play the video successfully.
Code
let options = PHVideoRequestOptions()
options.isNetworkAccessAllowed = true
options.deliveryMode = .automatic
// create a meta data
let metadata = GCKMediaMetadata(metadataType: .movie)
metadata.setString("Title", forKey: kGCKMetadataKeyTitle)
metadata.setString("Subtitle", forKey: kGCKMetadataKeySubtitle)
PHImageManager.default().requestAVAsset(forVideo: asset, options: options, resultHandler: { (avAsset, audioMix, info) in
if let avUrlAsset = avAsset as? AVURLAsset {
// create media information
let mediaInfo = GCKMediaInformation(contentID: avUrlAsset.url.absoluteString,
streamType: .buffered,
contentType: "video/quicktime",
metadata: metadata,
streamDuration: 0,
customData: nil)
self._remotMediaClient?.loadMedia(mediaInfo, autoplay: true)
}
})
Please suggest me how can I play local video to cromecast. I also try to copy the video to document directory and pass url of copied video to cromecast but not working.
I solve using local http server
HttpServerManager.swift
import UIKit
class HttpServerManager: NSObject {
static let shared = HttpServerManager()
private var httpServer:HTTPServer!
override init() {
super.init()
// Create server using our custom MyHTTPServer class
httpServer = HTTPServer()
// Tell the server to broadcast its presence via Bonjour.
// This allows browsers such as Safari to automatically discover our service.
httpServer.setType("_http._tcp.")
// Normally there's no need to run our server on any specific port.
// Technologies like Bonjour allow clients to dynamically discover the server's port at runtime.
// However, for easy testing you may want force a certain port so you can just hit the refresh button.
// [httpServer setPort:12345];
let documentsDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first
httpServer.setDocumentRoot(documentsDirectory)
}
func startServer() {
// Start the server (and check for problems)
do{
try httpServer?.start()
DDLogWrapper.logInfo("Started HTTP Server on port \(httpServer?.listeningPort())")
}catch {
DDLogWrapper.logError("Error starting HTTP Server: \(error) ")
}
}
func stopServer() {
httpServer.stop()
}
func getListeningPort() -> UInt16 {
return httpServer.listeningPort()
}
func setDocumentRoot(path stirng:String) {
httpServer.setDocumentRoot(stirng)
}
}
start server in AppDelege.swift
class AppDelegate: UIResponder, UIApplicationDelegate, GCKLoggerDelegate {
var window: UIWindow?
var httpServer:HTTPServer?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
GCKLogger.sharedInstance().delegate = self
// Configure our logging framework.
// To keep things simple and fast, we're just going to log to the Xcode console.
LoggerFactory.initLogging()
// start local http server
HttpServerManager.shared.startServer()
return true
}
}
Play local video to Crome cast using below method
func playToRemotePlayer(with asset:PHAsset, forViewController viewController:UIViewController) {
// if video is paused than resume it
if _remotMediaClient?.mediaStatus?.playerState == .paused {
_remotMediaClient?.play()
return
}
// lets keep track of recent assets that is played on Crome cast
if recentPlayedAsset == nil {
recentPlayedAsset = asset
}else{
if recentPlayedAsset == asset {
self._remotMediaClient?.loadMedia(self.recentMediaInfo!, autoplay: true)
return
}else{
recentPlayedAsset = asset
}
}
let options = PHVideoRequestOptions()
options.isNetworkAccessAllowed = true
options.deliveryMode = .highQualityFormat
options.version = .original
// create a meta data
let metadata = GCKMediaMetadata(metadataType: .movie)
metadata.setString("you video title", forKey: kGCKMetadataKeyTitle)
metadata.setString("you video subtitle", forKey: kGCKMetadataKeySubtitle)
PHImageManager.default().requestAVAsset(forVideo: asset, options: options, resultHandler: { (avAsset, audioMix, info) in
if (avAsset as? AVURLAsset) != nil {
let startDate = NSDate()
//Create Export session
let exportSession = AVAssetExportSession(asset: avAsset!, presetName: AVAssetExportPresetHighestQuality)
let filePathURL = documentDirectoryUrl.appendingPathComponent("rendered_video.mp4")
let filePath = NSURL(string: (filePathURL?.absoluteString)!)
CommanUtilites.deleteFile(filePath: filePath!)
exportSession!.outputURL = filePath as URL?
exportSession!.outputFileType = AVFileTypeMPEG4
exportSession!.shouldOptimizeForNetworkUse = true
let start = CMTimeMakeWithSeconds(0.0, 0)
let range = CMTimeRangeMake(start, (avAsset?.duration)!)
exportSession?.timeRange = range
print("Exporting Media...")
DispatchQueue.main.async {
self.progressHUD = MBProgressHUD.showAdded(to: viewController.view, animated: true)
self.progressHUD?.mode = MBProgressHUDMode.indeterminate
self.progressHUD?.label.text = "Exporting video please wait..."
}
exportSession!.exportAsynchronously(completionHandler: {() -> Void in
DispatchQueue.main.async {
self.progressHUD?.hide(animated: true)
}
switch exportSession!.status {
case .failed:
print("Error : " + (exportSession?.error?.localizedDescription)!)
case .cancelled:
print("Export canceled")
case .completed:
//Video conversion finished
let endDate = NSDate()
let time = endDate.timeIntervalSince(startDate as Date)
print(time)
print("Export Successful!")
print(exportSession?.outputURL?.path ?? "")
let port = String(HttpServerManager.shared.getListeningPort())
let videoHttpUrl = "http://127.0.0.1:" + port + "/rendered_video.mp4"
// create media information
self.recentMediaInfo = GCKMediaInformation(contentID: videoHttpUrl,
streamType: .buffered,
contentType: "video/mp4",
metadata: nil,
streamDuration: (avAsset?.duration.seconds)!,
customData: nil)
self._remotMediaClient?.loadMedia(self.recentMediaInfo!, autoplay: true)
default:
break
}
})
}
})
}
We are developing an iMessage extension. It uses Core Data successfully. We need to evaluate the store.sqlite file, but can not find it.
We try to find it like this:
In Xcode: Window -> Devices
In Installed Apps, select our extension
Download Container ...
But the container is empty:
Update:
Thanks to #Mundi's answer we found out how to get the models URL:
file:///var/mobile/Containers/Data/PluginKitPlugin/9C15B67C-8917-4A24-9FB0-BD119C43B3C4/Library/Application%20Support/Model.sqlite
Now we are trying to copy the Model to the Documents folder, to be able to download it later to our MacBook via Xcode (see above).
Unfortunately the path to `Documents:
NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
is again in /var/mobile/Containers/:
file:///var/mobile/Containers/Data/PluginKitPlugin/D0BBD375-A8B7-43DD-8486-1909965CAEB0/Documents
How can we download the Model.sqlite file from a shared container to our MacBook?
The actual sqlite file is likely to be in a shared container.
What works for me is to log the store URL and use that to locate it:
print(container.persistentStoreCoordinator.persistentStores.first!.url!)
Yields something like
file:///Users/developer/Library/Developer/CoreSimulator/Devices/2EAE0CD4-7899-45A3-8E83-E7D79DEEA08F/data/Containers/Data/Application/37F48A5E-7DAB-4E30-A752-F5B62826A15A/Library/Application%20Support/Events.sqlite
Your best bet with this is to write an exporter using the mail share action. In one of my apps I allow the user to export all of the data by emailing a copy of the sqlite file.
func exportAllDataSqlite() {
let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
var newFilePath: URL!
var mutablePathComponents = [String]()
var sqliteFileCopied = false
do {
let directoryContents = try FileManager.default.contentsOfDirectory(at: documentsUrl, includingPropertiesForKeys: nil, options: FileManager.DirectoryEnumerationOptions())
for f in directoryContents {
let pathComponents = f.pathComponents
if pathComponents.last == "XXXXWhatever your file is called when created by the persisten store.sqliteXXXXX" {
//create a copy of the file with a dated file name
mutablePathComponents = pathComponents
let dateComponents = (Calendar.current as NSCalendar).components([.day, .month, .year], from: Date())
let dateString = "\(dateComponents.day)-\(dateComponents.month)-\(dateComponents.year)"
mutablePathComponents[mutablePathComponents.count-1] = "Events App \(dateString).sqlite"
newFilePath = NSURL.fileURL(withPathComponents: mutablePathComponents)
do {
try FileManager.default.copyItem(at: f, to: newFilePath!)
sqliteFileCopied = true
print("Copied sqlite file")
} catch let error as NSError {
print(error.localizedDescription)
}
}
}
} catch let error as NSError {
print(error.localizedDescription)
}
if sqliteFileCopied == true {
//sharing
let activityItem:URL = newFilePath!
let objectsToShare = [activityItem]
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
activityVC.completionWithItemsHandler = { activity, success, items, error in
do {
try FileManager.default.removeItem(at: newFilePath!)
print("Deleted file: \(newFilePath!)")
} catch let error as NSError {
print(error.localizedDescription)
}
}
let excludeActivities = [UIActivityType.airDrop,
UIActivityType.print,
UIActivityType.assignToContact,
UIActivityType.saveToCameraRoll,
UIActivityType.addToReadingList,
UIActivityType.postToFlickr,
UIActivityType.postToVimeo]
activityVC.excludedActivityTypes = excludeActivities
self.present(activityVC, animated: true, completion: nil)
} else {
print("file not copied so can't be shared")
}
}
It's some of my earliest Swift so not great but it works. I used it the other day in a deployed copy of my app to debug an issue, just email to yourself and open with an Sqlite viewer on your mac.