I am trying to build share extension. Created the target, fixed the project settings (provisioning profile, app group, NSExtension).
Tried to run and saw the logs I added to the three methods isContentValid, didSelectPost, and configurationItems. This is my first time to create a share extension so, I was just looking around first and see when each method is called.
Now for some reason (I don't know what I did wrong), I am unable to see the logs from the extension. When I hit the run button in Xcode, the message Finished running ... gets displayed in the status bar on top.
Tried to change the scheme settings to the extension in the executable field, I get the following message when trying to run:
Could not locate installed application
Install claimed to have succeeded, but application could not be found on device. bundleId = <my-bundle-id-value>
Followed every solution I could find on the internet. Tried the solution from here and here.
UPDATE
I wanted to check if the extension actually runs or just the logs don't work. So I added the following logic to isContentValid:
- (BOOL)isContentValid {
// Do validation of contentText and/or NSExtensionContext attachments here
NSLog(#"isContentValid");
NSUserDefaults * userDefaults = [[NSUserDefaults alloc] initWithSuiteName:#"<group-id>"];
[userDefaults setObject:#"haha" forKey:#"key"];
[userDefaults synchronize];
return YES;
}
and read then read the haha in the main application it worked! So, the question is: Why can't I debug the application? Why doesn't the application print the log statements. Developing without logging and/or debugging could take 2x, if not more, time.
UPDATE 2
The best I was able to come up with is to manually attach the debugger to the extension, add breakpoints here and there (where I wanted to put logs) and edited the breakpoints to log as action and continue after evaluation.
I usually do debugging with support of print() method at which shows on Xcode logs as long as it is not terminated. However I have some conditions that I need to test in didFinishLaunchingWithOptions method of AppDelegate when the app's been terminated and then reopened. By "reopened" I mean by clicking on the app on simulator/iphone instead of running it from Xcode again. Sadly after termination print logs do not show. Any other way I could do it? Thanks!
Click on the options near the Appname on the upper-left corner of Xcode.
Click on Edit Scheme -> Check the Wait for executable to launch option and run as you usually do. Happy Coding :) .
Check "Wait for executable to launch" as #vishnu_146 mentioned.
CMD + R to run the app (first launch)
Double press Home and kill the app
CMD + R to run the app again (I tested that run without build will fresh launch the app).
App open with previous status. Can hit break points, but could not print logs. Reason: NSLog not working when "wait for executable to be launched" is set
In Swift 4.2,
var paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDirectory = paths[0]
let fileName = "\(Date()).log"
let logFilePath = (documentsDirectory as NSString).appendingPathComponent(fileName)
freopen(logFilePath.cString(using: String.Encoding.ascii)!, "a+", stderr)
Just add this block of code in application:didFinishLaunchingWithOptions method in the app delegate file and it will create a log file in app document directory on iPhone which logs all console log events. You need to import this file from iTunes to see all console events.
Note: In the .plist file make sure that Application supports iTunes file sharing exists and is set to YES so that you can access through iTunes.
To get Logfiles: Launch iTunes, after your device has connected
select Apps - select your App - in Augmentnt Document you will get your
file. You can then save it to your disk
You can try printing logs through "NSLog". On Xcode, go to "Devices and Simulators" and select your device. All the NSLogs will be visible there at the bottom.
I've updated my Xcode 8 to beta 2 today and I'm trying to share data between App and Today Extension. I'm facing with this log warning:
2016-07-08 18:00:24.732472 ProjetctX[941:42801] [User Defaults] Failed
to read values in CFPrefsPlistSource<0x1700f1280> (Domain:
group.x.p.t.o, User: kCFPreferencesAnyUser, ByHost: Yes, Container:
(null)): Using kCFPreferencesAnyUser with a container is only allowed
for System Containers, detaching from cfprefsd
Anyone can help me?
This is actually a spurious warning that was introduced in iOS 10 and macOS 10.12:
NSUserDefaults tip: in the current OSs there's a logged error "…with a container is only allowed for System Containers…".
This is spurious.
Trying to catch a particular failure mode, caught a normal operation case at the same time.
My successor on UserDefaults also has not figured out a way to make this less alarming without making the symptomatic case impossible to debug :/
https://twitter.com/Catfish_Man/status/784460565972332544 [thread]
The advice of prepending your team ID will silence the warning, but will also create a new empty user defaults. This will result in any previously stored data being unreadable.
For the time being, the solution is just to ignore it.
Also, Apple staff member CFM on the forums:
The logged message is spurious unless you're doing very specific things that I don't think are possible without using private functions (it was added to catch misuse of those functions, but unfortunately also caught a normal usage case).
Here’s how to use UserDefaults with App Groups to pass data between your main app and your extension:
In your main app, select your project in the Project Navigator.
Select your main app target and choose the Capabilities tab.
Toggle the App Groups switch to ON. This will communicate with the
Developer Portal in order to generate a set of entitlements.
Create a new container. According to Apple, your container ID must
start with "group", so a name such as "group.io.intrepid.myapp" is
perfect.
Select your extension target and repeat the process of enabling App
Groups. Do not create a new App Group, simply select the group that
was just created in the main app target.
When reading or writing UserDefaults in either your app or your
extension, do not access UserDefaults.standard.
Instead use UserDefaults(suiteName: "group.io.intrepid.myapp").
Note: The suite name is the name of your App Group container created
in Step 4.
Make sure, group enable and using same group id for both extension and app capability section!
Credit goes to http://blog.intrepid.io/ios-app-extensions
Change you group name in Xcode entitlements from:
group.com.mycompany.myapp
To
group.MYTEAMID.com.mycompany.myapp
ps: you can find your MYTEAMID in developer.apple.com membership
The solution for me was to not use the same identifier for the application Bundle Identifier and the part after "group.".
Say, the app bundle id is "com.app.id", then group id as "group.com.app.id" is causing issues. After I change it to "group.com.app.id.something" it stops.
Also had same issue with my macOS app.
Solved it by: Reboot the device!
https://stackoverflow.com/a/39876271
The SuiteName (postfix) must not be the main Bundle ID.
I’m facing this same issue when I’m trying to use initWithSuiteName. Seems that this is a bug from Apple.
The only solution / workaround I found is to reset all the settings of the device.
Go to Settings -> General -> Reset -> Reset All Settings.
This doesn’t erase any content on the iPhone, just erases all the settings.
After resetting the setting, everything worked fine. Let me know if it helps you too.
Build with Xcode 8.1 Beta and you will see the same warning, but you will also get the value.
By default, if you are using the Settings.Bundle/Root.plist for displaying and editing your app preferences via Apple Settings App, it uses the UserDefaults.standard dictionary.
So if you are using App-Groups and you want to share this defaults / settings within your apps and extension, you need to change the container of your settings.
Step 1: Open your Settings.Bundle -> Root.plist
Step2: Add the key ApplicationGroupContainerIdentifier and as value set your App-Group-Id, defined in your Signing & Capabilities: Looks like group.xx.yy
After you have implemented this step, the default container for your App-Settings will now switch from UserDefaults.standard (your apps Path) to the Shared Path.
Set by example
NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:#"group.com.xxx.xxx"];
[userDefaults setValue:#"value" forKey:#"key"]
[userDefaults synchronize]; // return maybe false, but it doesn't matter
Get by
NSUserDefaults *userDefaults = [[NSUserDefaults alloc] init];
[userDefaults addSuiteNamed:#"group.com.xxx.xxx"];
NSString *value = [useDefaults valueForKey:#"key"];
Although the same error will still be printed when setting, the value is indeed set and can be read correctly. But I don't know why this is happening, it's just the result of various attempts.
if you suffer this problem when you try to save data to extension APP by using userDefault, maybe you had written this code:
[[NSUserDefaults standardUserDefaults] initWithSuiteName:#"group.xxx.com"];
This code reset default userDefault.
Actually,the correct code is:
[[NSUserDefaults alloc] initWithSuiteName:#"group.xxx.com"];
http://www.jianshu.com/p/e782104c3bc3
Change from
[[NSUserDefaults alloc] initWithSuiteName:#"group.com.xxx.xxx"];
to
[[NSUserDefaults alloc] initWithSuiteName:#"nnnnnnnnnn.group.com.xxx.xxx"];
Where nnnnnnnnn is your team number, the one which you use to sign your code.
Tested under Xcode 8 GM and iOS 10 GM, and worked!
I'm developing iOS apps with Xcode. So when I build through Xcode I get device logs shown in the console output. But when I disconnect the iPhone from USB, or detach the process, then plug in the phone again and try to attach the process (my app is running on the phone still), the console doesn't output anything anymore.
If I go to Window -> Devices and my iPhone it doesn't show any output in that console either. The console app doesn't show any output either. I've tried to kill Xcode, clean the project, but to no success.
Anyone know how to show output logs from the built app after the iPhone have been detached?
I solved the log output mystery. Since we're using Cocoa Lumberjack it "devoured" the normal NSLog output, I added another log output by writing this row:
DEBUG_LOGS([DDLog addLogger:[DDASLLogger sharedInstance] withLevel:DDLogLevelDebug]);
Where DDASLLogger is the apple console.
When I run my application on the simulator I found the path of file using following code:
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
NSLog(#"%#",basePath);
}
simulator output:
file:///Users/username/Library/Application Support/iPhone Simulator/7.0.3/Applications/E7816FF6-7E6A-4606-917E-E74CDB574EC8/Documents/images/20140306113538.png
And same code when I run in my device I found output with:
Device output:
file:///var/mobile/Applications/2D86A03F-C239-4B57-849F-019BCDCA8543/Documents/images/20140306114536.png
And when I checked, file was store in documents.
When I load this url in browser with path of simulator(which I get from simulator output) is loaded in browser.
But path of device(which I get from device output) it showing error in browser with file not found.
like: Firefox can't find the file at /var/mobile/Applications/2D86A03F-C239-4B57-849F-019BCDCA8543/Documents/image/20140306114536.png.
Only just because of this reason I am not able to send file from my device on my server using web service.
Xcode Version: 5.0.2
Device: iPhone 4(iOS 7.0.6)
Any One please help.
Because you are trying to load file from your device which is not available on your system.
And your simulator directory is exist on your system thats why its loading file from your system.
So its better you can browse files from your device and copy into your system using following software
iExplorer
Why do your folder names different ?
for simulator it is "images" and for device it is "image".
Also closely check case sensitivity, since I also had faced similar problem for asset names. MAC file system searches with case insensitivity so simulator may be finding this file. Whereas iOS device file system is case-sensitive.