I am implementing a NEPacketTunnelProvider and loading it from my view controller using:
var vpnManager: NETunnelProviderManager = NETunnelProviderManager()
...
let providerProtocol = NETunnelProviderProtocol()
providerProtocol.providerBundleIdentifier = "AA.BB.CC"
providerProtocol.serverAddress = "<something>"
...
self.vpnManager.localizedDescription = "My app"
self.vpnManager.protocolConfiguration = providerProtocol
self.vpnManager.isEnabled = true
self.vpnManager.connection.startVPNTunnel()
Parts marked with "..." seemed irrelevant.
My understanding (although it's really not clear in the documentation) is that when I do this, and I have a target that was created as type "NetworkExtension" with BundleId AA.BB.CC, that the extension would be loaded and executed properly. So, my understanding is that startTunnel (from NEPacketTunnelProvider) will implicitly be called from the code block above.
I put a NSLog("STARTING TUNNEL!!!!!") right at the top of the startTunnel method, but am not sure where to see that. So far, I have viewed the logs in:
Console
Window > Devices and simulators > View device logs
None of these appear to show the logs from within the extension. The problem is that the extension seems to crash before I can attach to the running process, so I have the feeling I'm just "missing" that log because I can't attach quickly enough.
Short question
How can I attach to a running network extension quickly enough so that I don't miss an NSLog that is run immediately?
The logs from Network extensions do not go to Xcode console. to see the logs from Network extension you have to follow the bellow steps.
Open the console application.
Select your iOS device running the network extension you will see all the logs from your device.
Filter the logs by Network extension target name now you will see the logs only from your network extension.
How can I attach to a running network extension quickly enough?
What I have been doing to solve this problem was, put the thread on sleep right before log statement.
sleep(60)
It will give you enough time to attach the Network Extension process for debug.
Related
xcode debug area
hi,
i am a new beginner in iOS development. i am trying to learn someone code to build an app.
here is the screenshot of my problem : https://i.stack.imgur.com/4QX5P.png
i am trying to print("helloo") and print("your requestID is : ") but it doesnt appear in my debug area, that code is written in my ViewController.swift file
the debug area just print out the networking result from VenuesTableViewController.swift file (from another swift file)
what went wrong in here ? thanks in advance :)
Based on your code, it's very strange that your printing "helloo" doesn't appear on your debug area since it is declared on the viewDidLoad of your ViewController. Did you really use this ViewController ?
The second print "Your request id..." can or not be print based on your previous guard statements : guard let dictionnarayJSON...guard let meta...guard let requestID. A guard statement allows you to control the flow of your code. If what you test is correct it can continue to proceed your code. If not you put return so the flow of your code is stopped.
So, if one of your 3 guard statements fails, you can't reach your printing statement print(Your requet id...)
I recommend you to see Apple documentation : Control Flow
I have created an Amazon Web Services EC2 instance and deploy one of the AMIs with a Realm Object Server as its documentation explains:
https://realm.io/docs/realm-object-server/#install-realm-object-server
Once installed and created my admin user, I have completed the iOS tutorial: https://realm.io/docs/tutorials/realmtasks/, just until point 7, enough for creating task, but when I add new task in app, nothing happens. Debugging, I notice that next sentence try, is not executing:
let items = self.items
try! items.realm?.write {
items.insert(Task(value: ["text": text]), at: items.filter("completed = false").count)
}
The items collection seems to be initialized properly:
In the ROS dashboard, can see the database referenced in Xcode:
In image can be see "Default permissions" property is no access, is this the reason of not creating new task? If so, how can I change that permissions? If that is not the reason, anyone could help me?
thanks in advance
The problem was that I did not follow al the complete tutorial because I do not want to use the desktop application, just mobile example, but realm init objects in desktop app, so I never got a valid realm where perform actions.
For a quick and simple start with this realm tutorial pointing to an online server, not local, you must initialize the TaskList object and add it to self.realm on setup
// Show initial tasks
func updateList() {
if self.realm.objects(TaskList.self).count == 0 {
let list = TaskList()
list.id = "000001"
list.text = "lista de prueba"
// Add to the Realm inside a transaction
try! self.realm.write {
self.realm.add(list)
}
}
if self.items.realm == nil, let list = self.realm.objects(TaskList.self).first {
self.items = list.items
}
self.tableView.reloadData()
}
checking if there is not a TaskList with if self.realm.objects(TaskList.self).count == 0 {, you can create one and init realm.
You probably forgot to launch Mac demo app first or login with a different user. The tutorial assumes that existing data will be synced at login. If you have never launched the Mac app or logged in a different user, it may happen that items are not managed by Realm.
The tutorial says the following:
First, please follow the Get Started instructions to get set up with the Realm Mobile Platform and to launch the macOS version of RealmTasks.
Also, you attempt to try this tutorial with ROS on AWS. The tutorial assumes running ROS on a same local machine.
So you should modify the Mac app code to connect to the AWS, then run it to synchronize the initial data. Then run the tutorial iOS app.
The default permissions here show whether all other users can access the Realm or not, which isn't the case here. We already have an internal issue around clarifying this.
The registered user who owns the Realm has individual permissions to it by default. If you wouldn't have permissions opening the synchronized Realm from the client would also fail because of insufficient permissions, so this isn't the problem here.
So going back to your code:
try! items.realm?.write { … }
My guess would be that the problem here is that the collection isn't already attached to a Realm, so that items.realm? evaluates to null. In that case the write transaction wouldn't be executed.
You can resolve this by making sure to add the items first to a Realm or executing the write directly on a synchronized Realm.
Below is my recorded XCTest
let app = XCUIApplication()
let tablesQuery = app.tables
tablesQuery.staticTexts["Video"].tap()
tablesQuery.staticTexts["\tWindowed"].tap()
app.buttons["Launch"].tap()
app.buttons["Popout Video"].tap()
app.children(matching: .window).element(boundBy: 0).children(matching: .other).element(boundBy: 1).tap()
When I am trying to run the test the last part that is:
app.children(matching: .window).element(boundBy: 0).children(matching: .other).element(boundBy: 1).tap()
is not accessible. It does not throw any error but the last line of code is not executed.
I have tried solving the issue by referring to the following stackoverflow question :
Xcode UI Tests can't find views that are added programatically
Also , I have referred to the following Apple Documentations: https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/iPhoneAccessibility/Making_Application_Accessible/Making_Application_Accessible.html#//apple_ref/doc/uid/TP40008785-CH102-SW2
https://developer.apple.com/reference/uikit/uiview
But all these doesn't seem to solve the issue. Any help will be greatly appreciated.
The line in question is very brittle. It's possible that your app's views are not always available in the same order every time the app launches, depending on race conditions, so what was recorded in your recording session does not necessarily work for all launches of the app. You'll probably find that the code is actually running, but isn't tapping the element you expected.
To make your code less brittle, add an accessibility identifier to the UIView in your app code, and use the otherElements query to find the UIView.
// app code
let view: UIView!
view.accessibilityIdentifier = "myAccessibilityIdentifier"
// UI test code
app.otherElements["myAccessibilityIdentifier"].tap()
I want to read inputs from debug console, to create commands that will be read by the app in order to get more control in my app. For example I want to send commands like:
addCoins 200
and my app should read this line and parse it to call the function:
addCoins(amount: 200)
In the didViewLoad I tried to create an async function and inside read console to know if the user has written some commands but it is not working.
I am not sure if it is possible at all.
My code inside the viewDidLoad is:
let queue = DispatchQueue.global()
queue.async {
let command = readLine(strippingNewline: true)
if command != nil {
//parse command to do something
print("\(command)!")
}
}
I want to read the commands as following:
Your application can not read your console input if it's an iOS app. You can certainly use debugging features to read information during runtime.
You might not need this but, in the lldb debugger, you can set up breakpoints and use basic commands to read and modify some information at runtime. Apple has a comprehensive tutorial on Xcode debugging. Debugger You can also look at lldb tutorial here. lldb tutorial
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.