Problem
My app needs to send an HTTP-like request over TCP, followed by periodic data and get back a stream of data in the foreground and background in return.
In the background, I need to open and close the socket after receiving a Bluetooth characteristic value, which is an unnecessary overhead that slows the user down and may lead to a lot of lost data.
Currently
In the foreground, it opens an NSSocket (through a framework), sends the initial request and periodically sends and receives data.
While in the background, the app is started when it receives a characteristic value from the bluetooth-central background mode. It then opens the socket to send some initial data, waits for some data in return, and closes the socket.
Considerations
The protocol I need to connect to is HTTP-like (NTRIP), so I considered using a URLSession, which can keep a socket open, even in the background. However, the protocol has some non-standard behaviors. Namely:
It can return a SOURCETABLE response (interchangeable with HTTP/1.1).
Some implementations have a non-standard second status line (e.g. HTTP/1.1 OK 200, followed by HTTP/1.1. Not Authorized 401).
Some rare implementations incorrectly fail to separate the status line and message body with CRLF.
The connection needs to be kept open to periodically send and receive data.
A future revision of NTRIP does enforce HTTP compliance, but is not yet widely used.
Post
Replies
Boosts
Views
Activity
My goal is to recreate a layout that was previously designed on Android. The layout has a header, a list of profiles and controls as a footer at the bottom. My goal is to have the footer float to the bottom of the screen (if there is extra space) or the bottom of the table. Like this:
On Android I had to compromise by making the profiles list a nested scroll view. How could I make the footer float to the bottom on iOS? Or worst case, make it a proper nested scroll view?
I need the URLSession to be able to interpret non-compliant HTTP-like responses. The response may contain a non-standard status-line HTTP version (SOURCETABLE, instead of HTTP/1.1), may be missing a CRLF to separate the status-line and message body and may contain custom headers.
My thought is to intercept and modify the textual traffic to make it HTTP-compliant. How would I intercept and modify the traffic in Swift?
I'm considering intercepting and modifying the request to be optimal, since it requires the least amount of rewriting (reinventing the wheel with URLSession HTTP support). Alternatively, I've considered using a custom URLProtocol. However, this appears to require writing a lot of the HTTP parsing code.
Earlier I made a UIStackView with 3 UIButtons. By default, the axis is set to Horizontal. If the buttons would be truncated, my goal is to change the axis to Vertical.
Here is what I tried:
private func updateButtons() {
let buttonsWidth = getButtonWidth(createButton) + 10 +
getButtonWidth(updateButton) + 10 +
getButtonWidth(deleteButton)
crudButtons.axis =
buttonsWidth > crudButtons.bounds.width ?
.vertical :
.horizontal
crudButtons.setNeedsLayout()
}
private func getButtonWidth(_ button: UIButton) -> CGFloat {
return button.titleLabel!.textRect(forBounds: crudButtons.bounds, limitedToNumberOfLines: 1).width
}
It runs but does not appear to calculate the correct values. How would I properly check if the buttons would be truncated?
The goal is to provide the user with a *.log file using a UIDocument. The class is able to write to the file (if not first saved) but will not initially save it.
When saveToURL is called, it produces an EXC_BREAKPOINT (code=1 subcode=0x104a7b84c). I looked at several other implementations and they all appear to be doing the same thing. None of the objects are zombies, nothing else is overwritten and this is running on a physical iOS 12 device. What am I missing?
@implementation ReceiverLog
- (instancetype)initWithUUID:(NSUUID*)uuid
{
NSString *fileName = [[NSString alloc] initWithFormat:@"receiver-%@.log", uuid.UUIDString];
NSURL *documentsURL = [NSFileManager.defaultManager URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:nil];
NSURL *fileURL = [documentsURL URLByAppendingPathComponent:fileName];
self = [super initWithFileURL:fileURL];
return self;
}
- (void)open
{
NSURL *fileURL = [self fileURL];
if ([NSFileManager.defaultManager fileExistsAtPath:fileURL.absoluteString]) {
// Never runs
// Open
[self openWithCompletionHandler:^(BOOL success) {
}];
} else {
// Results in EXC_BREAKPOINT
// Create
[self saveToURL:fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
}];
}
}
- (void)close
{
[self closeWithCompletionHandler:^(BOOL success) {
}];
}
- (void)write:(NSString*)format, ...
{
// This works
va_list args;
va_start(args, format);
[_entries addObject:[[NSString alloc] initWithFormat:format arguments:args]];
va_end(args);
[self updateChangeCount:UIDocumentChangeDone];
}
- (id)contentsForType:(NSString *)typeName
error:(NSError * _Nullable *)outError
{
NSString *contentsString = [_entries componentsJoinedByString:@"\n"];
return [contentsString dataUsingEncoding:NSUTF8StringEncoding];
}
- (BOOL)loadFromContents:(id)contents
ofType:(NSString *)typeName
error:(NSError * _Nullable *)outError
{
if (![contents isKindOfClass:[NSData class]]) return NO;
NSString *contentsString = [[NSString alloc] initWithData:contents encoding:NSUTF8StringEncoding];
[_entries removeAllObjects];
[_entries addObjectsFromArray:[contentsString componentsSeparatedByString: @"\n"]];
return YES;
}
@end
Our app needs to read as many packets as possible from a Bluetooth peripheral. To accomplish this, the peripheral is restored in the background (bluetooth-central background mode). At a minimum, it needs to read one specific type of packet that is sent every 1 second.
Apple recommends:
Apps woken up for any Bluetooth-related events should process them and return as quickly as possible so that the app can be suspended again.
But they never say how to return. Although it is preferable for the user that the app never suspends, it is better that the app is not penalized for staying awake too long.
We have a process in our iPhone app that uses CoreBluetooth to transfer a large amount of data over time using Bluetooth LE. Now I'm looking for ways to speed up this process.
From what I have gathered, there is no way to set a preferred phyaical layer (PHY) for CoreBluetooth. How does iOS determine the best PHY to use? Is there any way I can influence it?
I was not able to locate any documentation from Apple mentioning "physical layer" or "phy" for CoreBluetooth, only a brief GitHub Issue for a multiplatform networking library that discussed setting a "PreferredPhy" for iOS.