I have a UIView that i create with a XIB. I then want to add it on top of a parent, take up the whole screen but use the safe area i have set up constraints for in the xib.
I can add the view fine, but when i do, the safe area is ignored, and the view goes all the way to the top and bottom.
The code i use (objective-c still sorry):
(UIView *parent)
MyViewController *newViewController = [[MyViewController alloc] initWithNibName:MY_VIEW_NIB_NAME bundle:nil];
[view setFrame:CGRectMake(0, 0, parent.bounds.size.width, parent.bounds.size.height)];
[parent addSubview:self.view];
In the Xib, i have the top and bottom constrained to SafeArea.top and bottom. It looks fine in the layout there.
Any tips are appreciated.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
as the title suggests, i cant run my (objective c) project in xcode after upgrading to Xcode 12. It is a Cocoapods project.
It works fine when i deploy to my phone, but in the simulator
I get three different errors for some reason.
It complains about "missing module map" for a separate project i include:
module map file '...(path)/Build/Products/Debug-iphonesimulator/MyLibraryProject/MyLibraryProject.imagemap' not found
2. It complains about a precompiled header:
<unknown>:0: error: failed to emit precompiled header '(path)/Build/Intermediates.noindex/PrecompiledHeaders/myProject-Bridging-Header-swift2UGSYUUFRK85M-clang18QKMU0TXX4JD.pch' for bridging header '(path)/iphone/myProject/myProject-Bridging-Header.h'
3. Finally it complains about Not finding a bundle for a library that i use:
error: Resource "(path)/Products/Debug-iphonesimulator/FCAlertView/FCAlertView.bundle" not found. Run 'pod install' to update the copy resources script.
Again, i can build and deploy to my phone, and submit to TestFlight/Appstore, but if i pick an emulator it's crash and burn.
I am not very knowledgeable about xcode inner workings, so if anyone has any pointers, i'd be *most* grateful.
Topic:
Developer Tools & Services
SubTopic:
Xcode
Tags:
Xcode Sanitizers and Runtime Issues
Xcode
Compiler
Hey, i have an app with a notification action that enables the user to make a phone call directly from the notification. I made this a good while ago, but we just noticed that it stopped working everywhere - except for when i install it via xcode.
To make a long story short, what i do is that in
didReceiveNotificationResponse, i get the phone number out from the payload and finally i call
[application openURL:[NSURL URLWithString:[@"tel://+" stringByAppendingString:msisdn]] options:@{} completionHandler:nil];
This used to result in that the dialog pops up from the bottom with the phone number and a "call" button, but now it works when installed from xcode, but nothing happens when installed from testflight.
I have made debug traces and it gets to the openurl-row with the correct phone number, but nothing seems to happen when i call it.
Any idea what has changed? I made this several years ago and haven't touched the code. Pointers appreciated!
Hello!
We have a time reporting app of sorts, where one functionality we have is that users can turn on to check in and out from work via geofencing - i.e. they select a location when they want to start and end a work period. This works great.
We have had clients asking for some time to be able to use a wifi network to do the same thing. I.e. check in to work when they join a specific wifi network and checkout when they leave it. So, this is something they will want to use, and will turn on themselves if they want to use it.
I have found NWPathMonitor and this thread:
https://developer.apple.com/forums/thread/685255
that kind of asks the same thing, but it references specifying why i need it - so i did that above, hoping that someone knows whether i could accomplish this.
Thanks in advance!
Hi there,
i have just made a widget, whoohoo! As you can see in the code below, it draws an icon and a random number.
This works fine, however, i have noticed when running, that it is drawn twice every time. That is, first a number is shown, then a second later, it changes again.
This seems unneccessary, and i don't understand why it happens.
Hoping that someone can show me the light. Code:
import SwiftUI
import Intents
struct Provider: IntentTimelineProvider {
func placeholder(in context: Context) -> WidgetEntry {
print(">>>> MyWidget;getTimeline")
return WidgetEntry(status: 0, date: Date(), configuration: ConfigurationIntent())
}
func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (WidgetEntry) -> ()) {
print(">>>> MyWidget;getSnapshot")
let entry = WidgetEntry(status: 0, date: Date(), configuration: configuration)
completion(entry)
}
func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
print(">>>> MyWidget;getTimeline")
let entry = WidgetEntry(status: 0, date: Date(), configuration: configuration)
let timeline = Timeline(entries: [entry], policy: .never)
completion(timeline)
}
}
struct WidgetEntry: TimelineEntry {
let status: Int
let date: Date
let configuration: ConfigurationIntent
}
struct WidgetView : View {
var entry: Provider.Entry
init(entry: Provider.Entry){
print(">>>> WidgetView;init()")
self.entry = entry;
}
var body: some View {
//Text(entry.date, style: .time)
VStack{
Image("check")
Text("# \(Int.random(in: 1..<6))")
}
}
}
@main
struct MyWidget: Widget {
let kind: String = "MyWidget"
var body: some WidgetConfiguration {
IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider()) { entry in
WidgetView(entry: entry)
}
.configurationDisplayName("My Widget")
.description("Leeloo Dallas Multipass.")
.supportedFamilies([.accessoryInline, .accessoryCircular, .systemSmall])
}
}
struct MyWidget_Previews: PreviewProvider {
static var previews: some View {
WidgetView(entry: WidgetEntry(status: 0, date: Date(), configuration: ConfigurationIntent()))
.previewContext(WidgetPreviewContext(family: .accessoryCircular))
}
}
Hi, i have a separate question for the same widget here, so please look there for the source code.
In the widget, you can see i have various print()-calls in the methods. On the simulator i can see the calls, however when i run on my phone, they are not visible anywhere. In xcode the log window closes (and opens up again if i run the app itself, not the extension), and i cannot find them in the console app either.
Is this expected behavior or am i missing something? Thankful for pointers.
Hi, please consider the following widget view
case .accessoryCircular:
VStack{
Image(entry.icon).resizable().padding().border(.red)
Text("IN")
}
EDIT, i also have tried this without success:
Image(entry.icon).resizable().frame(height: gp.size.height * 0.30, alignment: .center)
The image works if it's a PNG but now it's an SVG. I'm pretty much a SwiftUI noob, so i don't know how to get the image to work within the circular widget... or perhaps SVG isn't supported in lockscreen widgets?
The error message i'm getting from the preview is
The body of the Widget' entries contains an image of size(2094, 2010) which is beyond the maximum of (1418,8, 3067,2).
That's a pretty strange error message to me, i thought the vstack would keep the image within the boundaries? also, I get the same message if i remove the text.
Do i have to set the size explicitly?? In that case i have to hard-code it to some fixed widget size, right? I'd like to avoid that if possible.
Grateful for pointers.
please consider this code:
[NEHotspotNetwork fetchCurrentWithCompletionHandler:^(NEHotspotNetwork *network) {
if (network) {
DebugLog(@"Network ssid: %@, bssid: %@", network.SSID, network.BSSID);
} else {
DebugLog(@"No available network");
}
}];
For me, I have a strange situation - say that the BSSID of my network is "01:34:56:78:90"
the string in the property is missing the first character! what is contains (and is printed) is "1:34:56:78:90" - the leading "0" is missing.
So, I was wondering if this is a know thing, or if perhaps it's only Asus (my router)? Or, am I doing something wrong?
Pointers would be much appreciated.
Hello,
I created a lock screen widget for my app last year, as a widget app extension. It has worked fine, but I am working on a new release and it has stopped updating:
It is not called anymore when I call WidgetCenter.shared.reloadTimelines(ofKind: "MyWidget"), and the preview screen is now blank when I add it on the lockscreen.
I haven't touched anything related to the widget from what I know. The only things I can think of is that Xcode has updated my project files automagically, and I have updated cocoapods.
I looked at the device logs, and found this:
[...MyWidget] Failed to launch extension with error: Error Domain=com.apple.extensionKit.errorDomain Code=2 UserInfo={NSUnderlyingError=0x84b4d4410 {Error Domain=RBSRequestErrorDomain Code=5 UserInfo={NSLocalizedFailureReason=, NSUnderlyingError=0x84b45ea30 {Error Domain=NSPOSIXErrorDomain Code=111 UserInfo={NSLocalizedDescription=}}}}}.
I have no idea what this is, hoping someone can come up with suggestions on where to look. I have looked at my git history but I can't find anything changed.
Our app is a time reporting service with various functions around that. The user checks in at work, checks out when they go home.
We thought it'd be useful to provide a live activity to show how long they have worked for.
There is also a couple of other cool things we could do that users would love, but i couldn't find definitive answers to the questions below.
1.
We have a geofence-based function that checks the user in when they for example arrive at work, and check them out when they go home, so that they don't have to open the app.
However, this means that we will need to start and end the live activity from within a geofence trigger. Is this possible?
2.
It seems that the maximum time for a live activity is 8 hours? Sometimes people work for longer... How would we solve this? i would be fine with 12 since it would solve most cases.
Is it possible somehow to go beyond 8 hours up to 12?
If not, is there a callback that "8 hours are up!" so that i could do a final update on the live activity from a counter to "you started working at 09:04"
3.
I have seen that some live activities have buttons. It would be neat if the user can check out via a button on the live activity. However, since we take location and call our servers when checking out, we
need to be able to use both the locationmanager and make a network call from the live activity. Is this possible?
Thanks in advance, Cheers
Basically, in my widget/live activity, I want to extract reusable views into a separate file with an isolated view and preview. Dummy example below.
I cannot do it because it says "missing previewcontext".
The only way I've found is to add the view to my main app target, but I don't want to clutter my main app wiews that only exist in my widgets if I can avoid it.
Can this be done somehow? Thoughts appreciated.
Dummy example (tried with and without "previewLayout":
struct StatusActivityView: View {
let status: UserStatusData
var body: some View {
VStack(alignment: .center) {
Text("Dummy example")
}.background(.blue).padding(5)
}
}
@available(iOS 16.2, *)
struct StatusActivityView_Previews: PreviewProvider {
static var previews: some View {
let status = WidgetConstants.defaultEntry()
return StatusActivityView(status: status).previewLayout(.sizeThatFits)
}
}
Please consider simple example below.
I am trying to put a timer in the upper right corner of a live activity. I am done, it works, but I'm trying to get the timer to look better.
If I take a regular text, I can get it to align properly by adjusting the .frame(), , but for a text with a timer inside it, alignment is ignored from what I can see.
Text("Hello").frame(width: 90, alignment: .trailing).border(.red)
/*Text(timerInterval: timeRange, countsDown: false)
.monospacedDigit().font(.subheadline).frame(width: 90, alignment: .trailing).border(.red)*/
}
Is there any way to fix this?
Right now, I have a fixed width so that HH:mm:ss will fit, but that doesn't look super great if it's just minutes and seconds for example, there's an empty block to the right
I am working on a live activity with a button that will do a network call when pressed on.
I want to make sure that it can only be pressed once, and then ignored while the request is processed.
This is what I did:
Since it seems that a new intent object is created for each button press, I am using a static synchroniser like this:
private var _isBusy: Bool = false
private var _timestamp: Date? = nil
private let queue: DispatchQueue
private let resetInterval: TimeInterval
init(resetInterval: TimeInterval = 60, queueLabel: String = "default.synchronizedBoolQueue") {
self.resetInterval = resetInterval
self.queue = DispatchQueue(label: queueLabel)
}
var isBusy: Bool {
get {
return queue.sync {
return _isBusy
}
}
set {
queue.sync {
_isBusy = newValue
}
}
}
func setIfNotBusy() -> Bool {
return queue.sync {
let now = Date()
if let timestamp = _timestamp {
if now.timeIntervalSince(timestamp) > resetInterval {
// Reset if it was more than the specified interval ago
_isBusy = false
_timestamp = nil
}
}
if !_isBusy {
_isBusy = true
_timestamp = now
return true
}
return false
}
}
func clearBusy() {
queue.sync {
_isBusy = false
_timestamp = nil
}
}
}
Then, in my intent I have:
private static let synchronizedBoolean = SynchronizedBoolean(queueLabel: "myIntent")
...
func perform() async throws -> some IntentResult {
NSLog("---LIVE perform() called")
if(!UserEventIntent.synchronizedBoolean.setIfNotBusy()){
NSLog("---LIVE Was already in progress!")
}else{
//doing intent logic here
UserEventIntent.synchronizedBoolean.clearBusy()
}
}
I am pretty new to Swift, so my hope is that someone more experienced than me could tell me if this a reasonable approach or if I'm missing anything?
A big question - let's say I go into the perform() method, and while I'm in there, the user presses the button and the intent is called again. I get the "already in progress", but the method must still provide a result. Will that effect the intent already in progress?
Thoughts much appreciated.
OK, so I'm trying to share some utils classes for logging. The problem is a use-case where I want to create a debug notification.
However, inside the app, I want to show a popup instead if the app is showing, but I can't share that code because it uses UIApplication.shared.ApplicationState.
I've tried gating it off with all sorts of methods, @available etc. but I get compilation error "unavailable for application extensions"
Example of me trying:
static func doNotification(_ header: String, message: String) {
//so I'm trying to gate off the code that only can be called in an extension , and in addition I have @available below
if(isAppExtension()){
doNotificationFromExtension(header, message: message)
}else{
doNotificationFromApp(header, message: message)
}
}
@available(iOSApplicationExtension, unavailable)
static func doNotificationFromApp(_ header: String, message: String) {
let state = UIApplication.shared.applicationState
if state != .active {
//my dialog handler in-app popup
}else{
NotifUtils.createLocalNotification(message, header: header, category: NOTIFICATION_CATEGORY_DEBUG, playSound: false)
}
}
//here I know that I'm in an extension, so app isn't showing - always local notification
static func doNotificationFromExtension(_ header: String, message: String) {
NotifUtils.createLocalNotification(message, header: header, category: NOTIFICATION_CATEGORY_DEBUG, playSound: false)
}
static func isAppExtension() -> Bool {
return Bundle.main.executablePath?.contains(".appex/") ?? false
}
Is there any way to share the code like this? The reason I want to do this is because I have various live activity code that I'd want to re-use, but this is a show.-stopper.
Please find below a complete app example.
It has a button, when you press it, a local notification is created. However, the UnNotificationCenter.delegate is called twice, and I can't understand why.
I am trying to move my project from Objective-C to Swift, and my similar code there doesn't get called twice, so I'm confused.
Can anybody shine a light on this? Pointers appreciated.
App:
@main
struct NotifTestApp: App {
init() {
UNUserNotificationCenter.current().delegate = NotificationReceiveHandler.shared
configureUserNotifications()
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
private func configureUserNotifications() {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
if granted {
print("Notification permission granted.")
} else if let error = error {
print("Error requesting notification permissions: \(error)")
}
}
}
}
class NotificationReceiveHandler: NSObject, UNUserNotificationCenterDelegate {
static let shared = NotificationReceiveHandler()
//>> THIS IS CALLED TWICE WHEN I PRESS THE BUTTON
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
NSLog(">>> Will present notification!")
completionHandler([.sound])
}
}
///THE UI
struct ContentView: View {
var body: some View {
VStack {
Text("👾")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Notification test!")
Text("When i press the button, will present is called twice!!").font(.footnote)
.padding(10)
Button("Create Notification") {
createNotification(
message: "This is a test notification",
header: "Test Notification",
category: "TEST_CATEGORY",
playSound: true,
dictionary: nil,
imageName: nil)
}
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(8)
}
.padding()
}
}
#Preview {
ContentView()
}
private func createNotification(message: String, header: String, category: String, playSound: Bool = true, dictionary: NSDictionary? = nil, imageName: String? = nil) {
let content = UNMutableNotificationContent()
content.title = header
content.body = message
content.categoryIdentifier = category
content.badge = NSNumber(value: 0)
if let imageName = imageName, let imageURL = Bundle.main.url(forResource: imageName, withExtension: "png") {
do {
let attachment = try UNNotificationAttachment(identifier: "image", url: imageURL, options: nil)
content.attachments = [attachment]
} catch {
print("Error creating notification attachment: \(error)")
}
}
content.sound = playSound ? UNNotificationSound(named: UNNotificationSoundName("event.aiff")) : nil
if let infoDict = dictionary {
content.userInfo = infoDict as! [AnyHashable: Any]
}
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: nil)
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
}