Post

Replies

Boosts

Views

Activity

Text with standard font style appears smaller on iPadOS than on iOS
I used standard font styles in an iOS app. For example .font(.headline). I hoped that developing this way would allow the adoption of the app to other platforms, relatively easy. However, when trying to run for iPadOS, the text did not increase in size to occupy the more abundant space offered by larger screen, but it actually shrank. Overall, the app does not look great "automatically". Why does it happen? What is the best practice for cross platform development with SwiftUI (with regards to font sizes). I want to make as little as possible human interface design decisions on my own and just let SwiftUI take care of everything. (But I also want the results to look as Apple would consider great looking)
0
0
156
Oct ’24
How to make changes of text in search filed to cause animated changes in the view?
Following the examples from the official documentation: https://developer.apple.com/documentation/swiftui/adding-a-search-interface-to-your-app When the user types in the text in the search field, the list is updated with filtered results. How do I cause these changes to be animated? I tired to put .animated() after the .searchable modifier, the result was what I am looking for, however it also broke the animation of the search field getting/releasing focus.
1
0
194
Oct ’24
How do the run loop of the main thread and the main queue are related?
Do run loops use an operation queue under the hood? When I dispatch to the mian queue, I know it will run on the mian thread, which means it will be handled b the main thread's run loop. But is the other way around correct? More specific question, is it possible somehow that the following code will return true? OperationQueue.current != OperationQueue.main && Thread.isMainThread I tried to do for example to dispatch to the main thread using a timer. myQueue.sync { let timer = Timer(timeInterval: 1, repeats: false) { _ in let curr = OperationQueue.current let main = OperationQueue.main print("\(String(describing: curr)) \(main)") } RunLoop.main.add(timer, forMode: .common) } And got the same pointer. But maybe some other way of dispatching to the main run loop will give different results, possibly that is why OperationQueue.current can return nil.
1
0
1.7k
May ’23
Phased release of a version while the previous phased release is not finished
I was not able to find info regarding this situation in the official docs. What will happen if a version was not yet released to all, and a new version is phased released? For example if I am phased releasing version 2.0. On day 3, when only 5% of the users have this version, I discovered that this version has a bug. I paused the release of 2.0 and created a hotfix version 2.1. What will happen all the users who did not receive 2.0 when I start phased release of 2.1? Will they get an immediate update to 2.0 or will they skip this version?
0
0
584
May ’23
How to fit AVPlayer inside a container and align it to the top
I have a following simple code to present a video on the screen. This or similar can be found on any tutorial there is about using AVplayer from UISwift. struct PlayerView: UIViewRepresentable { func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<PlayerView>) { } func makeUIView(context: Context) -> UIView { return PlayerUIView(frame: .zero) } } class PlayerUIView: UIView { private let playerLayer = AVPlayerLayer() override init(frame: CGRect) { super.init(frame: frame) let url = Bundle.main.url(forResource: "my_video", withExtension: "mp4")! let player = AVPlayer(url: url) player.play() playerLayer.player = player layer.addSublayer(playerLayer) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func layoutSubviews() { super.layoutSubviews() playerLayer.frame = bounds } } If I put PlayerView inside an VStack the view will take as much vertical space as possible based on the sizes of the other views in the stack and then will put the video inside filling it horizontally. So if it is the only view, it will always put the video in the center of the screen and leave margins below and above it. Even if I put spacer after it. Even if I put it inside GeometryReader. What I want the view to "hug" the presented video as much as possible, and then bahve as any other SwiftUI view. But I do not understand how SwiftUI does the layout in this case when AVPlayer inside UIViewRepresentable is involved.
0
0
899
Apr ’23
Is it possible to cancel a subscription for all users who already own it?
We are adding an feature in the app and we want to sell a special subscription for the app which lets users use the feature. We might want to stop supporting this feature and remove it from the app in the future. Not just stop selling the subscription, but completely get rid of the feature in future version of the app. Once the feature is removed, the users who bought the special subscription, will not be able to access the feature and they will receive the same experience as users who bough a normal subscript we are currently offering. What is the best approach to deal with this situation? Is it possible to force cancelation of this product or changing auto renew to off for all users who are subscribed to it? Is it possible to force downgrade/upgrade of that product for all users who are subscribed to it? Are we stuck with supporting this feature forever, or is there a best practice which will allow us to phase it out?
1
0
860
Mar ’23
Is it possible to obtain the clipping path of CGContext?
There is no API to create an intersection between two CGPaths, however CoreGraphics knows how to do it behind the scenes. When calling CGContextClip (link) it will intersect current and clipping paths and store it in the clipping path. I was thinking to utilize this to perform intersections between paths I have. The problem is I can not find a way to retrieve back the clipping path from CGContext. Am I correct that such API does not exist or did I miss something?
3
0
1.5k
Aug ’22
What happens to secrets stored by apps when iCloud Keychain is turned off?
I this FAQ it says: What happens when I turn off iCloud Keychain on a device? When you turn off iCloud Keychain for a device, you're asked to keep or delete the passwords and credit card information that you saved. If you choose to keep the information, it isn't deleted or updated when you make changes on other devices. If you don't choose to keep the information on at least one device, your Keychain data will be deleted from your device and the iCloud servers.  So understand data stored by the user such as passwords is removed. What about data stored by an app installed on an iOS device? Is it removed as well? Can we assume that data stored in the keychain will not be removed by other means external to the app, or should we plan our app to handle such situation?
0
0
810
Feb ’22
How to obtain an AVAudioFormat for a canonical format?
I receive a buffer from[AVSpeechSynthesizer convertToBuffer:fromBuffer:] and want to schedule it on an AVPlayerNode. The player node's output format need to be something that the next node could handle and as far as I understand most nodes can handle a canonical format. The format provided by AVSpeechSynthesizer is not something thatAVAudioMixerNode supports. So the following:   AVAudioEngine *engine = [[AVAudioEngine alloc] init];   playerNode = [[AVAudioPlayerNode alloc] init];   AVAudioFormat *format = [[AVAudioFormat alloc] initWithSettings:utterance.voice.audioFileSettings];   [engine attachNode:self.playerNode];   [engine connect:self.playerNode to:engine.mainMixerNode format:format]; Throws an exception: Thread 1: "[[busArray objectAtIndexedSubscript:(NSUInteger)element] setFormat:format error:&nsErr]: returned false, error Error Domain=NSOSStatusErrorDomain Code=-10868 \"(null)\"" I am looking for a way to obtain the canonical format for the platform so that I can use AVAudioConverter to convert the buffer. Since different platforms have different canonical formats, I imagine there should be some library way of doing this. Otherwise each developer will have to redefine it for each platform the code will run on (OSX, iOS etc) and keep it updated when it changes. I could not find any constant or function which can make such format, ASDB or settings. The smartest way I could think of, which does not work:   AudioStreamBasicDescription toDesc;   FillOutASBDForLPCM(toDesc, [AVAudioSession sharedInstance].sampleRate,                      2, 16, 16, kAudioFormatFlagIsFloat, kAudioFormatFlagsNativeEndian);   AVAudioFormat *toFormat = [[AVAudioFormat alloc] initWithStreamDescription:&toDesc]; Even the provided example for iPhone, in the documentation linked above, uses kAudioFormatFlagsAudioUnitCanonical and AudioUnitSampleType which are deprecated. So what is the correct way to do this?
4
0
2.1k
Feb ’22
How to deduce from NSMethodSignature that a struct argument is passed by pointer?
How to deduce from NSMethodSignature that a struct argument is passed by pointer? Specifically on ARM. For example if I have: @protocol TestProtocol <NSObject> - (void)time:(CMTime)time; - (void)rect:(CGRect)point; @end And then I do: struct objc_method_description methodDescription1 = protocol_getMethodDescription(@protocol(TestProtocol), @selector(time:), YES, YES); struct objc_method_description methodDescription2 = protocol_getMethodDescription(@protocol(TestProtocol), @selector(rect:), YES, YES); NSMethodSignature *sig1 = [NSMethodSignature signatureWithObjCTypes:methodDescription1.types]; NSMethodSignature *sig2 = [NSMethodSignature signatureWithObjCTypes:methodDescription2.types]; const char *arg1 = [sig1 getArgumentTypeAtIndex:2]; const char *arg2 = [sig2 getArgumentTypeAtIndex:2]; NSLog(@"%s %s", methodDescription1.types, arg1); NSLog(@"%s %s", methodDescription2.types, arg2); The output is: v40@0:8{?=qiIq}16 {?=qiIq} v48@0:8{CGRect={CGPoint=dd}{CGSize=dd}}16 {CGRect={CGPoint=dd}{CGSize=dd}} Both look similar, no indication that CMTime will be actually passed as a pointer. But when I print the debug description: NSLog(@"%@", [sig1 debugDescription]); NSLog(@"%@", [sig2 debugDescription]); The first prints: ... argument 2: -------- -------- -------- -------- type encoding (^) '^{?=qiIq}' flags {isPointer} ... While the second prints: ... argument 2: -------- -------- -------- -------- type encoding ({) '{CGRect={CGPoint=dd}{CGSize=dd}}' flags {isStruct} ... So this information is indeed stored in the method signature, but how do I retrieve it without parsing the debug description? Are there rules I can use to deduce this myself? I tried to experiment with different structs but it is hard to spot a pattern.
3
0
1.3k
Jan ’22
Is it safe to put AVAudioSession calls not on main thread?
We have noticed that sometimes our app spends too much time in the first call of AVAudioSession.sharedInstance and [AVAudioSession setCategory:error:] which we call on app's initialization (during init of apps delegate). I am not sure if the app is stuck in these calls or it simply takes too much time to complete. This probably causes the app to crash due to main thread watchdog. Would it be safe to move these calls to a separate thread?
2
0
2.1k
Jan ’22
How to handle events by a view and then pass them to the view directly below?
I am trying to implement my own version of UIMenuController. One of the things I am struggling to imitate is what happens when a there is a touch event outside the menu. In this case the menu will be dismissed, but the event will also be passed to the correct view . So I need somehow to handle or capture the event in the menu or some transparent view covering the whole screen but also let it pass to the view below it. One idea is to override hitTest:withEvent: of the menu view, dismiss the menu when it is called (if point is outside the menu) and then return nil as if it was transparent to events. The issue is that hitTest:withEvent: must be pure function without side effect. On other hand, when touchesBegan:withEvent: is called, it is possible dismiss the menu and to pass the event to the nextResponder, but the view directly below the menu is not necessarily the superview of the menu view, so it is not part of the responder chain.
0
0
766
Oct ’21