我们正在开发消息传递应用程序,并且正在使用包含几种类型的单元格的collectionview。单元格具有不同的类型并具有动态大小,其中一个单元格应显示从Web服务器接收的具有多种颜色和格式的样式化文本。 单元格在第一个视图上正确显示了此信息,但滚动后,应用程序在HTML重新呈现时崩溃,并显示错误:
收到未处理的ObjectiveC异常:NSRangeException
我们基于此链接实现了collectionview UICollectionView insert cells above maintaining position (like Messages.app)
下面是代码:
我们尝试添加计算用于缓存的NSAttribute
,但是由于它们另存为字符串,因此我们无法将它们恢复为NSAttribute
。
ChatCollectionViewSource.cs
[Export("collectionView:layout:sizeForItemAtIndexPath:"), CompilerGenerated]
public virtual CGSize GetSizeForItem(UICollectionView collectionView, UICollectionViewLayout layout, NSIndexPath indexPath)
{
var msg = chatMessages[indexPath.Row];
var estimatedFrame = new CGRect(0, 0, 220, 1000);
if(msg.Message.IsHtml()){
var ss = NSString ss = new NSString(msg.Message);
var htmlAttributes = TextHelper.GetHtmlNSAttributes(ss);
var estimatedFrame = TextHelper.GetEstimatedCGRectHtml(htmlAttributes);
return new CGSize(this.view.Frame.Width, estimatedFrame.Height + 24);
}
else {
// return cgsize of nonhtml text cell
}
}
public override UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath)
{
var msg = chatMessages[indexPath.Row];
var textCell = collectionView.DequeueReusableCell("message_cell_identifier", indexPath) as MessageCell;
textCell.Layer.ShouldRasterize = true;
textCell.Layer.RasterizationScale = UIScreen.MainScreen.Scale;
var estimatedFrame = new CGRect(0, 0, 220, 1000);
if (msg.Message.IsHTML()) // html
{
NSString ss = new NSString(msg.Message);
NSAttributedString NSAttributes = null;
NSAttributes = TextHelper.GetHtmlNSAttributes(ss);
textCell.SetHTML(NSAttributes, msg.Date, msg.Id.ToString());
textCell.NSAttributedString = NSAttributes;
}
else
{
textCell.SetText(msg, msg.Date);
estimatedFrame = TextHelper.GetEstimatedCGRect(msg.Message); // get estimated frame
}
textCell.SetFrame(estimatedFrame, chatMessages[indexPath.Row].IsSend, this.view, msg);
return textCell;
}
MessageCell.cs
public void SetHTML(NSAttributedString NSAttributes, DateTime dateTime, string Id = null)
{
//ChatTextView.TextStorage.BeginEditing();
try
{
ChatTextView.TextColor = null;
if (NSAttributes != null)
{
DispatchQueue.MainQueue.DispatchAsync(() =>
{
ChatTextView.AttributedText = new NSMutableAttributedString(NSAttributes);
});
}
}
catch (Exception exception)
{
Debug.WriteLine(exception);
}}
TextHelper.cs
public static NSAttributedString GetHtmlNSAttributes(NSString HTMLtext)
{
var HTMLStyle = "<style>.body{font-family: '-apple-system', 'GothamMedium'; font-size:13; color:rgb(179, 178, 178);}</style>";
var text = HTMLStyle + "<div class='body'>" + HTMLtext + "</div>";
var ns = (NSString)text;
var myHtmlData = ns.Encode(NSStringEncoding.Unicode);
var options = new NSAttributedStringDocumentAttributes
{
DocumentType = NSDocumentType.HTML
};
NSError error = new NSError();
error = null;
NSDictionary dict = new NSDictionary();
dict = null;
try
{
var attrString = new NSAttributedString(myHtmlData, options, out dict, ref error);
return attrString;
}
catch (Exception ex)
{
Console.WriteLine(myHtmlData);
Console.WriteLine(ex.Message);
Console.WriteLine(options);
return null;
//throw ex;
}
}
这实际上很好用
我们正在尝试添加功能: 获取最近50条消息(无限滚动) 当用户滚动到列表顶部
ChatViewController.cs
#region scrolled to top observer
scrolledToTopObs = NSNotificationCenter.DefaultCenter.AddObserver((NSString)"scrolled_to_top",
async (notification) =>
{
var moreMessages = await Static.DB.getChatsAsync(this.CaseId, this.UserType, ++page);
if (moreMessages.Count == 0)
return;
list.InsertRange(0, moreMessages);
Debug.WriteLine("items count in list: " + list.Count);
// https://stackoverflow.com/questions/25548257/uicollectionview-insert-cells-above-maintaining-position-like-messages-app
NSIndexPath[] insertedPaths = new NSIndexPath[moreMessages.Count];
for (int i = 0; i < insertedPaths.Length; i++)
insertedPaths[i] = NSIndexPath.FromItemSection(i, 0);
DispatchQueue.MainQueue.DispatchAsync(() =>
{
var bottomOffset = ChatCollectionView.ContentSize.Height - ChatCollectionView.ContentOffset.Y;
CATransaction.Begin();
CATransaction.DisableActions = true;
ChatCollectionView.PerformBatchUpdates(() =>
{
ChatCollectionView.InsertItems(insertedPaths);
},
(finished) =>
{
ChatCollectionView.SetContentOffset(new CGPoint(0, ChatCollectionView.ContentSize.Height - bottomOffset), false);
CATransaction.Commit();
});
});
});
该崩溃报告在DispatchQueue.MainQueue.DispatchAsync()
之后导致应用崩溃:
2019-05-10 12:10:38.152 MyApp [1890:923892] Xamarin.iOS:已收到 未处理的ObjectiveC异常:NSRangeException *-[__ NSArrayM objectAtIndexedSubscript:]:索引16超出范围[0 .. 15] 2019-05-10 12:10:38.156 MyApp [1890:923892] ................................ NSAttributedString类型的HTMLString为null 2019-05-10 12:10:38.163 MyApp [1890:923892]引发了Objective-C异常。名称: NSRangeException原因:* -[__ NSArrayM objectAtIndexedSubscript:]: 索引16超出范围[0 .. 15]本机堆栈跟踪:0
CoreFoundation 0x00000001bb829ebc + 252 1 libobjc.A.dylib 0x00000001ba9f9a50 objc_exception_throw + 56 2 CoreFoundation
0x00000001bb7a1384 _CFArgv + 0 3 CoreFoundation
0x00000001bb724b78 + 0 4 UIKitCore
0x00000001e82d4f5c + 1836 5 UIKitCore
0x00000001e82d69dc + 260 6 UIKitCore
0x00000001e82d0d48 + 44 7 UIKitCore
0x00000001e82b3d50 + 1648 8 UIKitCore
0x00000001e82b3580 + 92 9基金会
0x00000001bc2c9420 __NSFireDelayedPerform + 404 10 CoreFoundation
0x00000001bb7ba718 + 28 11 CoreFoundation
0x00000001bb7ba448 + 864 12 CoreFoundation
0x00000001bb7b9c7c + 248 13 CoreFoundation
0x00000001bb7b4b58 + 1880 14 CoreFoundation
0x00000001bb7b40e0 CFRunLoopRunSpecific + 436 15 UIFoundation
0x00000001c5e42368 + 1728 16 UIFoundation
0x00000001c5e4533c + 28 17 UIFoundation
0x00000001c5e923ec _NSReadAttributedStringFromURLOrData + 8120 18 UIFoundation 0x00000001c5e45278 + 136 19 MyApp 0x000000010318b498 MyApp + 5911704 20 MyApp 0x0000000103143104 MyApp + 5615876 21 MyApp
0x000000010314329c MyApp + 5616284 22 MyApp
0x0000000102ca95f4 MyApp + 792052 23 MyApp
0x0000000102c7594c MyApp + 579916 24 MyApp
0x000000010305b598 MyApp + 4666776 25 Mono
0x0000000105a38f08 mono_get_runtime_build_info + 1332 26 Mono
0x0000000105add8a4 mono_runtime_invoke_checked + 152 27 Mono
0x0000000105ae1214 mono_runtime_invoke + 160 28 MyApp
0x0000000102c40e98 MyApp + 364184 29 MyApp
0x0000000102c40af0 MyApp + 363248 30 UIKitCore
0x00000001e82d53ac + 2940 31 UIKitCore
0x00000001e82d69dc + 260 32 UIKitCore
0x00000001e82d0830 + 224 33 UIKitCore
0x00000001e82c9054 + 228 34 UIKitCore
0x00000001e82ac2d4 + 10232 35 UIKitCore
0x00000001e82b3f90 + 92 36 UIKitCore
0x00000001e82b42c8 + 388 37 UIKitCore
0x00000001e82b4124 + 96 38 UIKitCore
0x00000001e82b40a8 + 84 39 UIKitCore
0x00000001e82b3fe4 + 64 40 MyApp
0x00000001031868f8 MyApp + 5892344 41 MyApp
0x0000000103129e88 MyApp + 5512840 42 MyApp
0x0000000102cc1878 MyApp + 891000 43 MyApp
0x000000010315a830 MyApp + 5711920 44 MyApp
0x0000000103194a7c MyApp + 5950076 45 libdispatch.dylib
0x00000001bb262484 + 16 46 libdispatch.dylib
0x00000001bb20e9a4 + 1068 47 CoreFoundation
0x00000001bb7b9ce4 + 12 48 CoreFoundation
0x00000001bb7b4bac + 1964 49 CoreFoundation
0x00000001bb7b40e0 CFRunLoopRunSpecific + 436 2019-05-10 12:10:38.163 MyApp [1890:923892] 50 GraphicsServices
0x00000001bda2d584 GSEventRunModal + 100 51 UIKitCore
0x00000001e89c8c00 UIApplicationMain + 212 52 MyApp
0x00000001031914e4 MyApp + 5936356 53 MyApp
0x000000010312798c MyApp + 5503372 54 MyApp
0x000000010312794c MyApp + 5503308 55 MyApp
0x0000000102c591c0 MyApp + 463296 56 MyApp
0x000000010305b598 MyApp + 4666776 57 Mono
0x0000000105a38f08 mono_get_runtime_build_info + 1332 58 Mono
0x0000000105add8a4 mono_runtime_invoke_checked + 152 59 Mono
0x0000000105ae3b54 mono_runtime_exec_main_checked + 120 60 Mono
0x0000000105a16bfc mono_jit_exec + 316 61 MyApp
0x000000010548777c _Z9__isctypeim + 56712 62 MyApp
0x0000000102c590b8 MyApp + 463032 63 libdyld.dylib
0x00000001bb272bb4 + 42019-05-10 12:10:38.163 MyApp [1890:923892] Foundation.NSAttributedStringDocumentAttributes到达顶部 collectionview 12:10:38 PM列表中的项目数:300 objc [1890]: 无效或过早释放的自动释放池0x1057f33c8。
本机崩溃报告
在执行本机代码时获得了SIGABRT。这通常表示 Mono运行时或使用的本机库之一中的致命错误 通过您的应用程序。
基本故障地址报告
本机指令指针周围的内存...
本机堆栈跟踪:
0x105a30fc8- /private/var/containers/Bundle/Application/20685366-DEC9-4CB0-BA4E-3B41F073FEBD/MyApp.app/Frameworks/Mono.framework/Mono :mono_dump_native_crash_info 0x105a270c8- /private/var/containers/Bundle/Application/20685366-DEC9-4CB0-BA4E-3B41F073FEBD/MyApp.app/Frameworks/Mono.framework/Mono :mono_handle_native_crash 0x1bb4359f0- /usr/lib/system/libsystem_platform.dylib:0x1bb3b780c- /usr/lib/system/libsystem_kernel.dylib:0x1bb3b77a8- /usr/lib/system/libsystem_kernel.dylib:0x1ba9f94c4- /usr/lib/libobjc.A.dylib:0x1ba9f941c- /usr/lib/libobjc.A.dylib