主頁 > 移動端開發 > Windows上的JFileChooser-僅輸入空格時出現例外

Windows上的JFileChooser-僅輸入空格時出現例外

2022-10-20 04:12:41 移動端開發

描述

AJFileChooser在 Java Swing 應用程式中使用。用戶可以輸入作業系統允許的任何檔案名,但有時他們會輸入錯誤的檔案名,例如包含無效字符的名稱。

如果用戶輸入以空格結尾的名稱,例如

  • SomeName

顯示錯誤訊息。這是通過覆寫JFileChooser#approveSelection,將檔案名與不需要的正則運算式匹配,然后顯示錯誤對話框來完成的。

但是,當用戶只輸入一個空格時,就會引發例外:

2022-10-18 12:34:54 SEVERE (CustomExceptionHandler::uncaughtException) Uncaught exception: java.nio.file.InvalidPathException: Trailing char < > at index 22: C:\X\Y\Z\  on [AWT-EventQueue-0]
Exception Stacktrace:
java.nio.file.InvalidPathException: Trailing char < > at index 22: C:\X\Y\Z\ 
    at java.base/sun.nio.fs.WindowsPathParser.normalize(WindowsPathParser.java:191)
    at java.base/sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:153)
    at java.base/sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:77)
    at java.base/sun.nio.fs.WindowsPath.parse(WindowsPath.java:92)
    at java.base/sun.nio.fs.WindowsFileSystem.getPath(WindowsFileSystem.java:229)
    at java.base/java.nio.file.Path.of(Path.java:147)
    at java.base/java.nio.file.Paths.get(Paths.java:69)
    at java.desktop/sun.awt.shell.ShellFolder.getShellFolder(ShellFolder.java:247)
    at java.desktop/javax.swing.plaf.basic.BasicFileChooserUI.changeDirectory(BasicFileChooserUI.java:1353)
    at java.desktop/javax.swing.plaf.basic.BasicFileChooserUI$ApproveSelectionAction.actionPerformed(BasicFileChooserUI.java:1142)
    at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1967)
    at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2308)
    at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:405)
    at java.desktop/javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:262)
    at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:279)
    at java.desktop/java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:297)
    at java.desktop/java.awt.Component.processMouseEvent(Component.java:6635)
    at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3342)
    at java.desktop/java.awt.Component.processEvent(Component.java:6400)
    at java.desktop/java.awt.Container.processEvent(Container.java:2263)
    at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:5011)
    at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2321)
    at java.desktop/java.awt.Component.dispatchEvent(Component.java:4843)
    at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4918)
    at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4547)
    at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4488)
    at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2307)
    at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2772)
    at java.desktop/java.awt.Component.dispatchEvent(Component.java:4843)
    at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:772)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:95)
    at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
    at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:743)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
    at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:742)
    at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:117)
    at java.desktop/java.awt.WaitDispatchSupport$2.run(WaitDispatchSupport.java:190)
    at java.desktop/java.awt.WaitDispatchSupport$4.run(WaitDispatchSupport.java:235)
    at java.desktop/java.awt.WaitDispatchSupport$4.run(WaitDispatchSupport.java:233)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.desktop/java.awt.WaitDispatchSupport.enter(WaitDispatchSupport.java:233)
    at java.desktop/java.awt.Dialog.show(Dialog.java:1070)
    at java.desktop/javax.swing.JFileChooser.showDialog(JFileChooser.java:769)
    at java.desktop/javax.swing.JFileChooser.showSaveDialog(JFileChooser.java:691)
    at core.RetainerExportController.exportRetainer(RetainerExportController.java:156)
    at core.RetainerExportController.lambda$1(RetainerExportController.java:64)
    at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1967)
    at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2308)
    at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:405)
    at java.desktop/javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:262)
    at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:279)
    at java.desktop/java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:297)
    at java.desktop/java.awt.Component.processMouseEvent(Component.java:6635)
    at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3342)
    at java.desktop/java.awt.Component.processEvent(Component.java:6400)
    at java.desktop/java.awt.Container.processEvent(Container.java:2263)
    at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:5011)
    at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2321)
    at java.desktop/java.awt.Component.dispatchEvent(Component.java:4843)
    at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4918)
    at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4547)
    at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4488)
    at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2307)
    at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2772)
    at java.desktop/java.awt.Component.dispatchEvent(Component.java:4843)
    at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:772)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:95)
    at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
    at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:743)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
    at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:742)
    at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

這個例外一直在我們的錯誤日志中彈出,因為雖然用戶被指示不要輸入空格作為檔案名,但他們仍然會不時地輸入。

調查

對此進行調查后,問題似乎來自BasicFileChooserUI. 類中有一個用于缺失或空字串的過濾器:

if (filename == null || filename.length() == 0) {
                // no file selected, multiple selection off, therefore cancel the approve action
                resetGlobFilter();
                return;
}

但是,沒有針對空白檔案名的過濾器。所以這個名字沒有被 過濾BasicFileChooserUI,但是被 識別為以空格結尾WindowsPathParser,這會導致錯誤。

還有更多奇怪的行為。例如輸入一個完全由禁止字符組成的名稱,例如

  • ???

結果什么也沒發生,

  • 不拋出例外
  • JFileChooser#approveSelection也從未達到

怎么解決?

目前尚不清楚如何解決它,因為所有錯誤行為都發生在內部 Swing 和sun.nio.fs代碼中。例如,我們的實作中有正則運算式過濾器JFileChooser,它觸發approveSelection并檢查由空格和無效字符組成的名稱 - 但是approveSelection在這種情況下從未呼叫過。如果WindowsPathParser#parseWindowsPathParser#normalize被傳遞則呼叫它,否則錯誤處理是無用的,因為一些奇怪的內部錯誤處理是預先在內部完成的。

我已經研究過擴展 theWindowsFileChooserUIBasicFileChooserUI軟體設計,因為這兩個類都使用對手頭問題至關重要的私有成員。例如,將用戶輸入作為WindowsFileChooserUI私有JTextField成員處理并設定它并以相同的方法使用它,因此在任何嘗試擴展的類中訪問它甚至修改它WindowsFileChooserUI都是一個問題。

長話短說 -InvalidPathException當用戶打開JFileChooser對話框并只輸入一個空格時,如何防止拋出?

筆記

因為內部 API 受到影響,所以使用的 JDK 可能是相關的:11.0.14_9

對話創建本身并不壯觀,它是這樣創建的:

JFileChooser dialog = new CustomFileChooser( file );
dialog.setDialogType( JFileChooser.SAVE_DIALOG );
dialog.setAcceptAllFileFilterUsed( false );

唯一被覆寫的方法CustomFileChooser

  • createDialog
  • approveSelection

最小的可重現示例

因為請求了一個例子,錯誤可以重現如下:

  1. 設定一個搖擺應用程式(例如在 Eclipse 中)
  2. 像這樣創建一個JFileChooser對話框:
JFileChooser dialog = new JFileChooser( file );
dialog.setDialogType( JFileChooser.SAVE_DIALOG );
dialog.setAcceptAllFileFilterUsed( false );
  1. 運行應用程式,確保對話框創建被觸發
  2. 在對話框中輸入一個空格作為檔案名:
  3. 確認
  4. 一個InvalidPathException被拋出

請注意,此錯誤需要在 Windows 上運行 JVM,而我的測驗發生在 Java 11 上。

uj5u.com熱心網友回復:

雖然較舊的檔案選擇器版本從輸入的檔案名中去除了空格,但他們從不關心空格之外的名稱的有效性。例如,輸入類似\<\>\"的內容會被接受。無效的路徑名不會導致例外,因為java.io.File也不檢查語法。

在較新的版本中,FileSystem在某些地方使用了 NIO API,并且空間并不總是被剝離。發生特定例外是因為出于某種原因new File(" ").getAbsoluteFile().isDirectory()評估為(而沒有),因此檔案選擇器嘗試將目錄更改為無效路徑,而不是呼叫應用程式可以覆寫的路徑。truenew File(" ").isDirectory()approveSelection()

由于檔案選擇器的代碼無法處理無效檔案的例外,我做了這個解決方法,它使用了一個特殊的File子類,它報告不是一個目錄,可以在以下位置檢測到approveSelection()

public class FileChooserTest {
    static final class Invalid extends File {
        final String originalName;
        public Invalid(String pathname) {
            super(pathname);
            originalName = pathname;
        }

        @Override
        public boolean isDirectory() {
            return false;
        }

        @Override
        public String getName() {
            return originalName;
        }
    }
    public static void main(String... args) {
        if(!EventQueue.isDispatchThread()) {
            EventQueue.invokeLater(FileChooserTest::main);
            return;
        }
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (ReflectiveOperationException | UnsupportedLookAndFeelException e) {
            throw new RuntimeException(e);
        }
        JFileChooser fc = new JFileChooser() {
            @Override
            public void approveSelection() {
                if(getSelectedFile() instanceof Invalid) {
                    setSelectedFile(null);
                    return;
                }
                super.approveSelection();
            }
        };
        fc.setFileSystemView(new FileSystemView() {
            @Override
            public File createFileObject(String path) {
                try {
                    Paths.get(path);
                } catch(InvalidPathException ex) {
                    return new Invalid(path);
                }
                return super.createFileObject(path);
            }

            @Override
            public File createFileObject(File dir, String filename) {
                try {
                    Paths.get(filename);
                } catch(InvalidPathException ex) {
                    return new Invalid(filename);
                }
                return super.createFileObject(dir, filename);
            }

            @Override
            public File createNewFolder(File containingDir) throws IOException {
                return FileSystemView.getFileSystemView().createNewFolder(containingDir);
            }
        });
        if(fc.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
            System.out.println(fc.getSelectedFile());
        }
        else System.out.println("Not approved");
    }
}

這不僅可以消除例外,還可以防止無效檔案獲得批準。當然,它可以被改進,例如通過向用戶提供反饋。但是,如果像這樣的錯誤無論如何都能得到修復,那就更好JDK-8196673了。


*注意:名稱包含或不被拒絕的原因?是它們被轉換為檔案名過濾器。因此,當您輸入時,例如*.txt,它應該顯示在過濾器組合框中。

uj5u.com熱心網友回復:

如果您不想使用檔案選擇器或檔案系統的內部結構,您可以在呼叫檔案選擇器處理之前簡單地從檔案名中洗掉前導/尾隨空格:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Main
{
    public static void main(String[] args) throws Exception
    {
        JFileChooser fc = new JFileChooser( );

        JTextField tf = SwingUtils.getDescendantsOfType(JTextField.class, fc).get(0);
        tf.addFocusListener( new FocusAdapter()
        {
            @Override
            public void focusLost(FocusEvent e)
            {
                JTextField tf = (JTextField)e.getSource();
                tf.setText( tf.getText().trim() );
            }
        });

        fc.showOpenDialog(null);
    }
}

上面的代碼需要Swing Utils類。

uj5u.com熱心網友回復:

JFileChooser如果我要保存的檔案與現有檔案同名,我擴展為添加一個確認對話框。也許您可以使用它來啟動更強大的JFileChooser.

import java.io.File;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;

public class OSFileChooser extends JFileChooser {

    private static final long serialVersionUID = 1L;

    @Override
    public void approveSelection() {
        File f = getSelectedFile();
        
        if (f.exists() && getDialogType() == SAVE_DIALOG) {
            int result = JOptionPane.showConfirmDialog(this, f.getName()   
                    " exists, overwrite?",
                    "Existing file", JOptionPane.YES_NO_CANCEL_OPTION);
            switch (result) {
            case JOptionPane.YES_OPTION:
                super.approveSelection();
                return;
            case JOptionPane.NO_OPTION:
                return;
            case JOptionPane.CLOSED_OPTION:
                return;
            case JOptionPane.CANCEL_OPTION:
                cancelSelection();
                return;
            }
        }
        
        super.approveSelection();
    }
    
    @Override
    public File getSelectedFile() {
        File file = super.getSelectedFile();
        
        if (file != null && getDialogType() == SAVE_DIALOG) {
            String extension = getExtension(file);
            if (extension.isEmpty()) {
                FileTypeFilter filter = (FileTypeFilter) getFileFilter();
                if (filter != null) {
                    extension = filter.getExtension();
                    String fileName = file.getPath();
                    fileName  = "."   extension;
                    file = new File(fileName);
                }
            }
        }
        
        return file;
    }
    
    public String getExtension(File file) {
        String extension = "";
        String s = file.getName();
        int i = s.lastIndexOf('.');

        if (i > 0 && i < (s.length() - 1)) {
            extension = s.substring(i   1).toLowerCase();
        }

        return extension;
    }
    
}

以及相關的FileTypeFilter類。

import java.io.File;

import javax.swing.filechooser.FileFilter;

public class FileTypeFilter extends FileFilter {
    private String extension;
    private String description;
 
    public FileTypeFilter(String description, String extension) {
        this.extension = extension;
        this.description = description;
    }
 
    @Override
    public boolean accept(File file) {
        if (file.isDirectory()) {
            return true;
        }
        return file.getName().endsWith("."   extension);
    }
 
    @Override
    public String getDescription() {
        return description   String.format(" (*.%s)", extension);
    }
    
    public String getExtension() {
        return extension;
    }
    
}

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/518374.html

標籤:爪哇摇摆java-11

上一篇:JScrollPane不在JTextArea中滾動并保持禁用狀態

下一篇:如果串列的內容在變數中,如何創建回圈?

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more