Good morning.
I wrote some declares to make use of the iOS NSCalendar class. They work fine when I run on the simulator. They are not working when I run on a phone. There’s no crash, just no results.
Anyone have any suggestions?
-Bob
Good morning.
I wrote some declares to make use of the iOS NSCalendar class. They work fine when I run on the simulator. They are not working when I run on a phone. There’s no crash, just no results.
Anyone have any suggestions?
-Bob
Could you post a bit of the code?
A bit of code:
#tag Class
Protected Class CalendarConverter
#tag ExternalMethod, Flags = &h21
Private Declare Function alloc Lib "Foundation" Selector "alloc" (id as Ptr) As Ptr
#tag EndExternalMethod
#tag Method, Flags = &h21
Private Function components(pCalendar as Ptr, unitFlags as UInt64, pDate as Date) As Ptr
dim result as Ptr
dim nDate as Ptr
declare Function components _
lib "Foundation" _
selector "components:fromDate:" (calendar as Ptr, flags as Integer, fromDate as Ptr) as Ptr
nDate = self.NSDate(pDate)
result = components(pCalendar,unitFlags,nDate)
return result
End Function
#tag EndMethod
#tag ExternalMethod, Flags = &h21
Private Declare Function dateFromComponents Lib "Foundation" Selector "dateFromComponents:" (pCalendar as Ptr, pComponents as Ptr) As Ptr
#tag EndExternalMethod
#tag Method, Flags = &h0
Function GregorianToHebrew(pDate as Date) As Date
// see: http://stackoverflow.com/questions/4644451/gregorian-to-hebrew
// and: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/DatesAndTimes/Articles/dtCalendars.html
// and: https://forum.xojo.com/23627-how-to-get-date/0
dim g1 as Ptr
dim g2 as Ptr
dim h1 as Ptr
dim h2 as Ptr
dim dc as Ptr
dim hd as Ptr
dim s1 as Double
dim s0 as Double
dim result as Date
dim d1 as ptr
d1 = self.NSDate(pDate)
s0 = pDate.SecondsFrom1970
s1 = timeIntervalSince1970(d1)
g1 = NSClassFromString("NSCalendar")
g2 = initWithCalendarIdentifier(alloc(g1),"gregorian")
h1 = NSClassFromString("NSCalendar")
h2 = initWithCalendarIdentifier(alloc(h1),"hebrew")
dc = self.components(h2,self.unitDate + self.unitTime,pDate)
hd = dateFromComponents(g2,dc)
s1 = timeIntervalSince1970(hd)
result = new Date(s1,Timezone.Current)
return result
End Function
#tag EndMethod
#tag ExternalMethod, Flags = &h1, Description = 416C6C6F6361746573206D656D6F727920666F7220616E206F626A6563742E2043617374206F6E206120436C6173735074722E
Protected Declare Function init Lib "Foundation" Selector "init" (id as ptr) As ptr
#tag EndExternalMethod
#tag ExternalMethod, Flags = &h21
Private Declare Function initWithCalendarIdentifier Lib "Foundation" Selector "initWithCalendarIdentifier:" (id as Ptr, name as CFStringRef) As Ptr
#tag EndExternalMethod
#tag ExternalMethod, Flags = &h21
Private Declare Function NSClassFromString Lib "foundation" (pClassName as CFStringRef) As Ptr
#tag EndExternalMethod
#tag Method, Flags = &h21
Private Function NSDate(pDate as Date) As Ptr
/// class: CalendarConverter
/// method: NSDate
/// summary: creates as NSDate from a Xojo date
/// parameters: pDate as Date, the Xojo date to convert to an NSDate
/// returns: Ptr, an NSDate
/// author: Bob Gordon
/// date: May 4, 2017
dim datePtr as Ptr
Dim NSDateClass as Ptr = NSClassFromString("NSDate")
Declare Function dateWithTimeIntervalSince1970 _
Lib "Foundation" Selector "dateWithTimeIntervalSince1970:" (classRef As Ptr, seconds As Double) As Ptr
datePtr = dateWithTimeIntervalSince1970(NSDateClass,pDate.SecondsFrom1970)
return datePtr
End Function
#tag EndMethod
#tag ExternalMethod, Flags = &h21
Private Declare Sub release Lib "Foundation" Selector "release" (id as ptr)
#tag EndExternalMethod
#tag ExternalMethod, Flags = &h21
Private Declare Function timeIntervalSince1970 Lib "Foundation" Selector "timeIntervalSince1970" (pDate as Ptr) As Double
#tag EndExternalMethod
#tag ExternalMethod, Flags = &h21
Private Declare Function timeIntervalSinceReferenceDate Lib "Foundation" Selector "timeIntervalSinceReferenceDate" (pDate as Ptr) As Double
#tag EndExternalMethod
#tag Property, Flags = &h21
Private months() As Text
#tag EndProperty
#tag Constant, Name = NSUIntegerMax, Type = Double, Dynamic = False, Default = \"&hffffffffffffffff", Scope = Private
#tag EndConstant
#tag Constant, Name = StyleLong, Type = Double, Dynamic = False, Default = \"3", Scope = Private
#tag EndConstant
#tag Constant, Name = StyleMedium, Type = Double, Dynamic = False, Default = \"2", Scope = Private
#tag EndConstant
#tag Constant, Name = StyleNone, Type = Double, Dynamic = False, Default = \"0", Scope = Private
#tag EndConstant
#tag Constant, Name = StyleShort, Type = Double, Dynamic = False, Default = \"1", Scope = Private
#tag EndConstant
#tag Constant, Name = UnitDate, Type = Double, Dynamic = False, Default = \"28", Scope = Private
#tag EndConstant
#tag Constant, Name = UnitDay, Type = Double, Dynamic = False, Default = \"16", Scope = Private
#tag EndConstant
#tag Constant, Name = UnitMonth, Type = Double, Dynamic = False, Default = \"8", Scope = Private
#tag EndConstant
#tag Constant, Name = UnitTime, Type = Double, Dynamic = False, Default = \"224", Scope = Private
#tag EndConstant
#tag Constant, Name = UnitYear, Type = Double, Dynamic = False, Default = \"4", Scope = Private
#tag EndConstant
#tag ViewBehavior
#tag ViewProperty
Name="Index"
Visible=true
Group="ID"
InitialValue="-2147483648"
Type="Integer"
#tag EndViewProperty
#tag ViewProperty
Name="Left"
Visible=true
Group="Position"
InitialValue="0"
Type="Integer"
#tag EndViewProperty
#tag ViewProperty
Name="Name"
Visible=true
Group="ID"
Type="String"
#tag EndViewProperty
#tag ViewProperty
Name="Super"
Visible=true
Group="ID"
Type="String"
#tag EndViewProperty
#tag ViewProperty
Name="Top"
Visible=true
Group="Position"
InitialValue="0"
Type="Integer"
#tag EndViewProperty
#tag EndViewBehavior
End Class
#tag EndClass
Phew, quite a lot! I will have to check that more thoroughly, but a first hint might be that dateWithTimeIntervalSince1970 is a class constructor which means the object created is not retained. This often works in certain constructions, but especially when returning the ptr to somewhere else the object might simply cease to exist.
As a first attempt I would propose to cast a retain on it once you have it created (and at the end release it).
Ulrich,
Thanks for the hint. This is actually just a part of the code. I was having trouble getting the entire class to post.
I would expect the simulator to work like the phone. That is, if it works in the simulator, it should work on the phone. Is this not true?
-Bob
Sadly no. The simulator is a simulator, not an emulator. It tries to mimic the device, but it is no perfect substitute for the real thing. Which is very disappointing with several graphics routines that, although existent on macOS too, are only rendered on the CPU which makes the simulator extremely slow. Timing in general is nothing one can depend on.
Ulrich,
I tracked down the problem to the NSCalendar component:fromDate: method. Don’t know why, but it is giving a seriously wrong result but only on the phone.
I changed what I was doing to use the NSDateFormatter class. Everything seems to be working correctly now (pending further testing, of course). Thank you for your assistance.
-Bob
I’m not sure if this is the entire cause, but the declare is incorrect. NSCalendarUnit is a typedef for NSUInteger, so the Xojo declare should have flags as UInteger instead of Integer.
@Joe Ranieri do you have some documentation on why Integer vs. UInteger should make a difference?